从用户控制的来源构建的 LDAP 查询¶
ID: cs/ldap-injection
Kind: path-problem
Security severity: 9.8
Severity: error
Precision: high
Tags:
- security
- external/cwe/cwe-090
Query suites:
- csharp-code-scanning.qls
- csharp-security-extended.qls
- csharp-security-and-quality.qls
如果使用字符串连接构建 LDAP 查询,并且连接的组件包含用户输入,则用户很可能能够运行恶意 LDAP 查询。
建议¶
如果必须在 LDAP 查询中包含用户输入,则应对其进行转义,以避免恶意用户提供更改查询含义的特殊字符。如果可能,请使用现有的库,例如 AntiXSS 库。
示例¶
在以下示例中,代码接受用户提供的“组织名称”和“用户名”,并使用它们查询 LDAP 以访问“类型”属性。
第一个示例将未经验证和未编码的用户输入直接连接到用于 LDAP 查询的 DN(可分辨名称)和搜索过滤器中。恶意用户可以提供特殊字符来更改这些查询的含义,并搜索完全不同的一组值。
第二个示例使用 Microsoft AntiXSS 库对用户值进行编码,然后再将它们包含在 DN 和搜索过滤器中。这确保了恶意用户无法更改查询的含义。
using Microsoft.Security.Application.Encoder
using System;
using System.DirectoryServices;
using System.Web;
public class LDAPInjectionHandler : IHttpHandler
{
public void ProcessRequest(HttpContext ctx)
{
string userName = ctx.Request.QueryString["username"];
string organizationName = ctx.Request.QueryString["organization_name"];
// BAD: User input used in DN (Distinguished Name) without encoding
string ldapQuery = "LDAP://myserver/OU=People,O=" + organizationName;
using (DirectoryEntry root = new DirectoryEntry(ldapQuery))
{
// BAD: User input used in search filter without encoding
DirectorySearcher ds = new DirectorySearcher(root, "username=" + userName);
SearchResult result = ds.FindOne();
if (result != null)
{
using (DirectoryEntry user = result.getDirectoryEntry())
{
ctx.Response.Write(user.Properties["type"].Value)
}
}
}
// GOOD: Organization name is encoded before being used in DN
string safeOrganizationName = Encoder.LdapDistinguishedNameEncode(organizationName);
string safeLDAPQuery = "LDAP://myserver/OU=People,O=" + safeOrganizationName;
using (DirectoryEntry root = new DirectoryEntry(safeLDAPQuery))
{
// GOOD: User input is encoded before being used in search filter
string safeUserName = Encoder.LdapFilterEncode(userName);
DirectorySearcher ds = new DirectorySearcher(root, "username=" + safeUserName);
SearchResult result = ds.FindOne();
if (result != null)
{
using (DirectoryEntry user = result.getDirectoryEntry())
{
ctx.Response.Write(user.Properties["type"].Value)
}
}
}
}
}
参考¶
OWASP:LDAP 注入防御备忘单。
OWASP:防止 Java 中的 LDAP 注入。
AntiXSS 文档:LdapFilterEncode。
AntiXSS 文档:LdapDistinguishedNameEncode。
常见弱点枚举:CWE-90。