Pwnhub 公开赛 Web writeup
前面
Pwnhub.cn 是老司机们经常开车的地方,新司机想学开车就更得多多关注了(/捂脸逃)。
戳这里关注官微:胖哈勃
因为是内测,司机要取得"通行证"(邀请码)才能上路,那么作为公开赛,其实就是拿 Flag 换邀请码啦。
两个方向,Web 和 binary,作为一只🐶,不要挣扎就选 Web 吧。
(了解到 Web 题是长亭 CSO 人称 V总的 Valo 在一次实战中遇到的, binary 题则是今年1024 GeekPwn 上破解 PS4 主力进攻选手所出)
过程
线上比赛地址:http://54.223.145.113:88/
做题没截图,大家意会好了。
看到是一个上传页面,难道要考上传拿 Shell ?诶?上传的文件内容会回显到页面中,会不会是 system(cat) 的,拼接一下命令,哦不是。可能是file_get_contents() 读取的,会不会有 SSRF,先看看可以控制的两个位置,文件名和文件内容,拼接一下文件名,后缀得是 txt 结尾,domain.com/1.txt绕过就好,但是 cloudeye 并没有反应。虽然文件内容会原样显示到页面,能造成 XSS 漏洞,但也只是 Self-XSS ,貌似没什么卵用。
陷入僵局,那试一下会不会有源代码泄露啥的,毕竟也是 CTF 常见套路,.bak、.swp、.php~、.svn、.git 等都试了一遍无果,扫目录吧😭,啪啪啪,一通扫发现 /upload/ 是HTTP 403,证明目录存在呀,也难怪,本身就是上传文件嘛,诶,目录如果403的话,那里面的文件不会也403吧,尝试访问一下**/1**,是 HTTP 404,那就知道了 Apache Directory 设置的是 var/www/html/upload 但知道这点也没有用呐,甚至还不知道 Flag 在哪。
* 先放一放,接着搬砖
然后晚上回家看到官微放出 hint ,还叫自行寻找,躲猫猫什么的最喜欢了😳,右键查看源代码,html注释中有 upload.php 关键代码。
<!--
@move_uploaded_file($_FILES['file']['tmp_name'], $dir.$name);
echo "上传成功!\n\n文件内容:\n\n";
echo file_get_contents($dir.$name);
$files = glob($dir . '*');
@unlink($files[0]);
--!>
第一行移动上传的文件,第二行无视掉,第三行果然是使用file_get_contents,不过前面有加路径。
关键是在第四行和第五行,glob 函数把 $dir 下的所有文件名匹配成数组赋值给 $files ,然后使用 unlink 删除掉排在最前面的那个文件。
翻一下PHP手册 知道 glob 函数默认是会自动进行排序的,也就是说(话说 Linux 也会自动排序吧)
这样每次删除的就是排在最前面的文件,也就是说是可以删除不属于自己上传的文件的,但知道这个还是没继续的思路,既然是放出关键代码,问题肯定是出在这几行代码中的,可是 flag 在哪呢。
然后看到官微又放 hint
Flag是个文件,不需要shell,并且听说放文件的人拥有服务器最高权限
soga,flag 是用 root 创建的,Apache 是 www-data 没权限对 flag 进行删除操作,那么如果 flag 就藏在upload 目录下,利用 glob 函数自动排序,学校老师就讲过文件排序方式。
(0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz)
# ls
111 19882 abc2321312312 b12345 c1222 ctf.php
可以逐步上传比 flag 文件名更名称靠后的文件,因为 unlink($files[0]); 删除排在第一位的文件,而且知道 flag 是 root 创建,Apache 删除不掉,比如一开始上传一个文件名为 S 没有被删除,那么就知道 S 排在了 flag 后面,进而知道 flag 开头是 R。 脚本代码可以参考紫霞仙子在先知社区发的 https://xianzhi.aliyun.com/forum/read/516.html
最后
这种 CTF 游戏很好呀,就像以前乌云做的三个白帽社区,在挑战中学习分享新姿势。放现在众多CTF 比赛中简直是一股清流。
长亭牛逼