# 用户输入在搜索过滤器中导致 LDAP 注入，允许未经授权访问目录条目

- **ID:** `security/ldap-injection-via-user-input-in-search-filter`
- **领域:** security
- **类别:** data_error
- **验证级别:** ai_generated
- **修复率:** 90%

## 根因

应用程序通过拼接用户提供的输入来构建 LDAP 搜索过滤器，而未进行清理，允许攻击者注入 LDAP 元字符（如 *、|、&）来修改过滤器逻辑并检索未经授权的数据。

## 版本兼容性

| 版本 | 状态 | 引入 | 弃用 |
|------|------|------|------|
| OpenLDAP 2.6.6 | active | — | — |
| Microsoft Active Directory | active | — | — |
| Spring LDAP 2.4.0 | active | — | — |
| Python ldap3 2.9.1 | active | — | — |

## 解决方案

1. ```
   使用专门的 LDAP 编码库在构建过滤器之前转义用户输入。对于 Java，使用 Spring LDAP 的 `LdapName.escapeValue(input)` 或 Apache Directory API 的 `DefaultTemporaryDirectory`。示例：`String escapedInput = LdapName.escapeValue(userInput); String filter = "(&(uid=" + escapedInput + ")(objectClass=user))";`。
   ```
2. ```
   实现输入验证，仅允许字母数字字符和特定安全字符（如电子邮件格式）。拒绝任何包含 LDAP 元字符的输入。用户名示例正则表达式：`^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`。
   ```
3. ```
   使用白名单方法，将用户输入映射到预定义的过滤器值。例如，如果输入是部门名称，则映射到安全列表：`String filter = "(&(department=" + departmentMap.get(input) + ")(objectClass=user))";`。
   ```

## 无效尝试

- **Use a blacklist to block common LDAP metacharacters like * and |** — Attackers can use alternative characters or encoding (e.g., URL encoding, Unicode) to bypass the blacklist. Blacklists are incomplete and not a robust defense. (60% 失败率)
- **Escape only parentheses and asterisks in user input** — LDAP injection can also use other metacharacters like &, !, =, ~, or null bytes. Incomplete escaping leaves vulnerabilities. (45% 失败率)
- **Use a stored procedure or prepared statement (as in SQL) for LDAP queries** — LDAP does not support prepared statements in the same way as SQL. Parameterized queries are not available in most LDAP libraries, so this approach is not applicable. (80% 失败率)
