Column | Details |
---|---|
Name | CTF |
IP | 10.10.10.122 |
Points | 50 |
OS | Linux |
Difficulty | Insane |
Creator | 0xEA31 |
Nmap
1 | # Nmap 7.80 scan initiated Fri Jul 10 10:50:40 2020 as: nmap -sC -sV -oN ctf 10.10.10.122 |
查看80端口
大概的意思就是让我们尝试去登录这个系统,但是不能用SQLmap或者Dirbuster去暴力猜解用户名和密码。
再去登录界面看一下:
提示我们是一个OTP,及One Time Password,一般而言是1分钟更新一次。
查看源码,发现有一个Hint
如果比较熟悉LDAP的话,这里的两个名词schema和attribute已经提示了是关于LDAP注入。
靶机作者用一个已知的属性去存储了81位的token string,Google搜一下token string (81 digits)
。
可以看到一个关键的地方,Pure numeric (81-digit) "ctf" (compressed token format) strings
,和靶机的题目相契合,现在就有一点思路了,应该要去找到这个81位纯数字的token,然后用stoken工具去生成OTP。现在就主要是找到token,唯一可以利用的就是这个登录框了。
先随便用某个用户名和密码登录admin:1234
返回User admin not found
,再用SQL注入的万能密码试一试
直接是没有任何显示,应该是对一些特殊字符有黑名单过滤。Fuzz一下过滤了一些什么字符
1 | wfuzz -c --hw 233 -d 'inputUsername=FUZZ&inputOTP=1234' -w special-chars.txt 10.10.10.122/login.php |
–hw 233 代表过滤掉形如
User xxx not found
的返回信息。
我们发现+
和&
返回的是232 Words,但是在页面测试一下
发现返回的还是User + not found
或者User & not found
,这样的话应该是233 Words,而不是Wfuzz返回的232 Words。
我们尝试把这些特殊字符二次URL编码,看Web应用是否还能解析,用seclists中的doble_uri_hex.txt作为字典
1 | wfuzz -c --hw 233 -d 'inputUsername=FUZZ&inputOTP=1234' -w doble-uri-hex.txt 10.10.10.122/login.php |
最后Fuzz出来的被过滤的字符就是
1 | %2500 ---> %00 |
这些被过滤的字符就是LDAP注入需要过滤的所有字符,再结合login.php
页面源代码中的hint,可以确定是LDAP注入。
先来看LDAP注入的最基本形式
1 | (& |
具体到这个靶机的话,我们需要猜解括号的个数。运用类似盲注的思想,如果注入成功,那么就会返回User ca01h not found
。
假设只有一个括号:
假设有两个括号:
假设有三个括号:
当尝试到三个括号用于闭合时,成功返回了User ca01h%29%29%29%00 not found
,那么这个登录框的LDAP查询的基本形式就是
1 | (& |
接着,我们再回头去看一下Fuzz出来的被过滤的字符,其中%25%2a
返回的消息长度为231 Words
发现回显的消息是Cannot login
,说明可以用*
通配符来盲注用户名,脚本如下:
1 | #!/usr/bin/env python3 |
用户名为ldapuser
知道了用户名之后,我们就要去获取生成OTP的81位token,通过页面源代码的提示,这个token存储在某一个LDAP默认已经存在的属性当中。而默认的属性可以在PayloadsAllTheThings中找到:
1 | c |
如果不想写脚本的话用wfuzz来Fuzz靶机的LDAP中存在的属性可能会更快一些,但还是要先找到注入的形式:
1 | (& |
此外还要把注入的字符ldapuser)(FUZZ=*
进行二次URL编码,编码之后的结果ldapuser%2529%2528FUZZ%253d%252a
。
1 | wfuzz -c --hw 233 -d 'inputUsername=ldapuser%2529%2528FUZZ%253d%252a&inputOTP=1234' -w LDAP_attributes.txt http://10.10.10.122/login.php |
我们Fuzz出来了这么些属性是存在于靶机的LDAP服务中的,现在的工作就是一个一个的属性来猜解,属于一些重复性的工作,就不在这里过多赘述了,最后可以找到token是存储于pager属性中。接着写脚本burp81位token
1 | #!/usr/bin/python3 |
这里值得注意的是需要删掉最后的一个9,所以最后的token就是:
1 | 285449490011357156531651545652335570713167411445727140604172141456711102716717000 |
接着用stoken工具导入token
生成OTP
成功登录后,跳转到page.php
页面,可以执行命令
但是提示我们ldapuser
权限不够不能执行命令,这里有两种办法:
对group
属性进行注入,即把后面group属性的filter截断
1 | (& |
使用*
通配符作为用户名登录
这里演示一下第一种方案,payload直接放到burp中
1 | ldapuser%2529%2529%2529%2500 |
再去执行ls命令
读取page.php文件:
SSH登录:fdapuser:e398e27d5c4ad45086fe431120932a01