从一次漏洞挖掘入门Ldap注入

2019-07-22 约 3259 字 预计阅读 7 分钟

声明:本文 【从一次漏洞挖掘入门Ldap注入】 由作者 hpdoger 于 2019-07-22 09:16:00 首发 先知社区 曾经 浏览数 212 次

感谢 hpdoger 的辛苦付出!

在最近的一次测试中,随缘摸到了一个sso系统,留给前台的功能只有登陆。

没有验证码,但是登陆点强制要求每个用户更改强密码,而且除了管理员和测试账号其他大部分都是工号形式,直接fuzz一把梭

测试过程中发现username对于下面payload会存在两种不同回显

当时我并不理解这种payload是什么库的数据格式。但是看到存在"!"字符时,页面的回显是不同的,而"!"在绝大多数语言中都是取反的表达形式,自然会产生不同的布尔值,那么无疑就是个xxx注入点了

何为LDAP

通过payload的类型,看到是经典的ldap注入语句。一种老协议和数据存储形式了

LDAP协议

LDAP(Lightweight Directory Access Protocol):即轻量级目录访问协议。是一种运行于TCP/IP之上的在线目录访问协议,主要用于目录中资源的搜索和查询。使用最广泛的LDAP服务如微软的ADAM(Active Directory Application Mode)和OpenLDAP

LDAP存储

MySQL数据库,数据都是按记录一条条记录存在表中。而LDAP数据库,是树结构的,数据存储在叶子节点上。

LDAP目录中的信息是按照树形结构组织的:

dn:一条记录的位置
dc:一条记录所属的区域
ou:一条记录所属的组织
cn/uid:一条记录的名字/ID

这种树结构非常有利于数据的查询。首先要说明是哪一棵树(dc),然后是从树根到目标所经过的所有分叉(ou),最后就是目标的名字(cn/uid),借用一张图来表明结构如下:

条目&对象类&属性

  • 条目(entry):是目录中存储的基本信息单元,上图每一个方框代表一个entry。一个entry有若干个属性和若干个值,有些entry还能包含子entry
  • 对象类(obejectclass):对象类封装了可选/必选属性,同时对象类也是支持继承的。一个entry必须包含一个objectClass,且需要赋予至少一个值。而且objectClass有着严格的等级之分,最顶层是top和alias。例如,organizationalPerson这个objectClass就隶属于person,而person又隶属于top

  • 属性(atrribute):顾名思义,用来存储字段值。被封装在objectclass里的,每个属性(attribute)也会分配唯一的OID号码

LDAP查询语句

一个圆括号内的判断语句又称为一个过滤器filter。

( "&" or "|" (filter1) (filter2) (filter3) ...) ("!" (filter))

逻辑与&

(&(username=Hpdoger)(password=ikun))

查找name属性为Hpdoger并且password属性值为ikun的所有条目

逻辑或|

(|(username=Hpdoger)(displayname=Hpdoger))

查找username或者displayname为Hpdoger的所有条目

特殊说明

除使用逻辑操作符外,还允许使用下面的单独符号作为两个特殊常量

(&)     ->Absolute TRUE 
(|)     ->Absolute FALSE 
*       ->通配符

另外,默认情况下,LDAP的DN和所有属性都不区分大小写,即在查询时:

(username=Hpdoger) <=> (username=HPDOGER)

LDAP注入

由于LDAP的出现可以追溯到1980年,关于它的漏洞也是历史悠久。LDAP注入攻击和SQL注入攻击相似,利用用户引入的参数生成LDAP查询。攻击者构造恶意的查询语句读取其它数据/跨objectclass读取属性,早在wooyun时代就有师傅详细的剖析了这类漏洞。

上文说到LDAP过滤器的结构和使用得最广泛的LDAP:ADAM和OpenLDAP。然而对于下面两种情况

无逻辑操作符的注入

情景:(attribute=$input)

我们构造输入:$input=value)(injected_filter

代入查询的完整语句就为:

(attribute=value)(injected_filter)

由于一个括号内代表一个过滤器,在OpenLDAP实施中,第二个过滤器会被忽略,只有第一个会被执行。而在ADAM中,有两个过滤器的查询是不被允许的。

因而这类情况仅对于OpenLDAP有一定的影响。

例如我们要想查询一个字段是否存在某值时,可以用$input=x*进行推移,利用页面响应不同判断x*是否查询成功

带有逻辑操作符的注入

(|(attribute=$input)(second_filter))
(&(attribute=$input)(second_filter))

此时带有逻辑操作符的括号相当于一个过滤器。此时形如value)(injected_filter)的注入会变成如下过滤器结构

(&(attribute=value)(injected_filter))(second_filter)

虽然过滤器语法上并不正确,OpenLDAP还是会从左到右进行处理,忽略第一个过滤器闭合后的任何字符。一些LDAP客户端Web组成会忽略第二个过滤器,将ADAM和OpenLDAP发送给第一个完成的过滤器,因而存在注入。

举个最简单的登陆注入的例子,如果验证登陆的查询语句是这样:

(&(USER=$username)(PASSWORD=$pwd))

输入$username = admin)(&)(使查询语句变为

(&(USER=admin)(&))((PASSWORD=$pwd))

即可让后面的password过滤器失效,执行第一个过滤器而返回true,达到万能密码的效果。

后注入分析

注入大致分为and、or类型这里就不赘述,感兴趣的可以看之前wooyun的文章:
LDAP注入与防御剖析

还有一个joomla的一个userPassword注入实例:
Joomla! LDAP注入导致登录认证绕过漏洞

回到实例

大致了解注入类型,就开始了第一轮尝试

当通配符匹配到用户名时返回

用户名不存在时返回

构造用户名恒真username=admin)(%26&password=123

说明它判断用户的形式并不是(&(USER=$username)(PASSWORD=$pwd)),因为我们查到的用户名是true,但是验证密码false

由于自己也没搞过LDAP的开发..就盲猜后端应该就是这种情况:
执行了(&(USER=$username)(objectclass=xxx))后,取password与$password进行对比

ACTION

那么首先要知道它继承了哪些objectclass?因为树结构都有根,使我们能顺藤摸瓜。首先是top肯定存在,回显如下:

但是top的子类太多了,先fuzz一下objectclass的值缩小范围,payload:

username=admin)(objectclass%3d$str

发现存在personuser两个objectclass

再fuzz一下attribute得到的值如下:

username=admin)($str%3d*

凭借这些信息去LDAP文档里溯继承链,先去找user类,继承自organizationalPerson

同理organizationalperson又是继承自person的,person继承自top,最终的继承链为:

top->person->organizationalperson->user

也就是说这些类存在的属性都可能被调用。很遗憾的是我并没有fuzz到password类型参数,一般来说password会以userPassword的形式存储在person对象中,很多基于ldap的开发demo中也是这样写的。

但是userPassword毕竟也只是person类可选的属性,开发大概率是改名或者重写属性了,这也是这个漏洞没有上升到严重危害的瓶颈点

不过依然可以注出一些有用的数据。例如所有用户的用户名、邮箱、手机号、姓名、性别等等,说不定以后可以越权修改某账号性别呢-3-

盲注mobile

尝试注入管理员的手机号mobile

username=admin)(mobile=%s*&password=123

利用通配符不断添加数字,同理邮箱也可以注出来,与sql盲注的思路相同。

盲注username

毕竟对于sso,收集username是很有用的信息。那么问题来了,我们是可以通过生成字典来遍历存在的用户名,但是这个工作量是指数倍的增长,一天能跑完一个字母开头的就不错了,而且浪费了通配符的作用。

可是又想做到无限迭代把所有用户一个不漏的跑完,passer6y师傅提醒我用笛卡尔积

最后画出来的流程图大致如下:

最后跑了两三天才大概有1w多个用户,然而这些大部分是测试帐号,但也算是验证了思路的可执行性。至于为什么跑了两三天..因为打游戏忘了调bug(逃

总结

网上关于这类漏洞的fuzz思路也比较久远了,第一次接触这种漏洞,若文章思路如果有什么不对的地方还请师傅们斧正。自己对这类漏洞的姿势理解很浅,现在漏洞已经修复,但是如果有师傅对于password的注入有想法,可以私下交流一下

相关链接

https://wooyun.js.org/drops/LDAP%E6%B3%A8%E5%85%A5%E4%B8%8E%E9%98%B2%E5%BE%A1%E5%89%96%E6%9E%90.html
https://www.cnblogs.com/pycode/p/9495808.html
https://zhuanlan.zhihu.com/p/32732045

关键词:[‘渗透测试’, ‘渗透测试’]


author

旭达网络

旭达网络技术博客,曾记录各种技术问题,一贴搞定.
本文采用知识共享署名 4.0 国际许可协议进行许可。

We notice you're using an adblocker. If you like our webite please keep us running by whitelisting this site in your ad blocker. We’re serving quality, related ads only. Thank you!

I've whitelisted your website.

Not now