LDAP注入漏洞与防护(进阶篇)
字数 1405 2025-11-18 02:08:52
LDAP注入漏洞与防护(进阶篇)
1. 漏洞描述
LDAP(轻量级目录访问协议)注入是一种类似SQL注入的攻击手法,攻击者通过构造恶意的LDAP查询语句,绕过身份验证、越权访问或泄露敏感目录数据。LDAP常用于企业身份认证系统(如Active Directory、OpenLDAP),若用户输入未经过滤直接拼接到LDAP查询中,可能导致查询逻辑被篡改。
2. LDAP查询基础
LDAP查询使用过滤器(Filter) 语法,常见运算符:
=:等于(例如(cn=admin))&:逻辑与(例如(&(cn=admin)(objectClass=user)))|:逻辑或(例如(|(cn=admin)(cn=guest)))!:逻辑非(例如(!(cn=admin)))*:通配符(例如(cn=adm*))
示例查询:
(&(username=user1)(password=123456)) // 验证用户凭证
3. LDAP注入攻击原理
假设登录代码将用户输入直接拼接为LDAP过滤器:
String filter = "(&(username=" + userInput + ")(password=" + passwordInput + "))";
若用户输入 admin)(*)),密码任意,则过滤器变为:
(&(username=admin)(*))(|(password=anything))
由于 (*)) 匹配任意属性,后半部分被注释,查询可能返回 admin 用户信息,导致认证绕过。
4. 进阶攻击场景
(1)盲注攻击
当应用不返回详细错误信息时,攻击者通过布尔逻辑判断条件真假:
- 输入
admin)(objectClass=*)):若查询成功,说明objectClass存在。 - 输入
admin)(department=IT*)):通过响应时间或行为差异判断部门名称。
(2)多属性注入
利用 | 运算符构造复杂查询:
(|(username=admin)(username=user1))(password=xxx)
可能返回多个用户数据,导致信息泄露。
(3)特殊字符滥用
LDAP保留字符(如 *、(、)、\0 等)若未转义,可改变查询结构:
- 输入
*匹配所有条目。 - 输入
admin)(|(password=*))绕过密码检查。
5. 防护方案
(1)输入验证与白名单
- 限制用户名、密码等输入格式(如仅允许字母数字)。
- 示例代码:
import re
def validate_username(username):
if not re.match("^[a-zA-Z0-9_-]{1,20}$", username):
raise ValueError("Invalid username")
(2)参数化查询(LDAP编码)
使用LDAP API的转义函数处理特殊字符:
- Java:
javax.naming.ldap.Rdn.escapeValue(userInput) - Python:
ldap3.utils.conv.escape_filter_chars(userInput) - 示例:
from ldap3.utils.conv import escape_filter_chars
safe_input = escape_filter_chars(userInput) # 将 "admin)(*" 转义为 "admin\)\(\*"
(3)最小权限原则
- LDAP连接使用低权限账户,限制查询范围(如禁止访问敏感属性)。
- 在LDAP服务器端设置访问控制列表(ACL)。
(4)错误信息模糊化
避免返回详细的LDAP错误信息(如“属性不存在”),统一提示“认证失败”。
(5)逻辑层防护
- 避免将认证完全依赖LDAP查询结果,增加二次验证(如OTP)。
- 对查询结果严格校验(如只允许返回唯一用户)。
6. 实战检测技巧
- 工具辅助:使用Burp Suite的Scanner模块或手工测试特殊字符(如
*、|、))。 - Payload示例:
- 认证绕过:
admin)(*))、*)(& - 属性枚举:
admin)(objectClass=*))、admin)(mail=*))
- 认证绕过:
- 日志监控:检测LDAP查询中的异常模式(如频繁使用通配符)。
通过以上进阶防护策略,可显著降低LDAP注入风险,确保目录服务安全。