这一题用githack获取源码我就不讲了,我想说的是这个题的方法和我自己的理解
!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp'])
这段代码就是禁止我们用一些php伪协议之类的东西
if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp']))
这个就比较有意思了
大概的意思就是把'a-z,_'之后的东西转义为NULL,通俗来说就是可以使用函数但是不能使用参数,下面是在shell中的测试结果
解法一:
函数介绍:
scandir() :将返回当前目录中的所有文件和目录的列表。返回的结果是一个数组,其中包含当前目录下的所有文件和目录名称(glob()可替换)
localeconv() :返回一包含本地数字及货币格式信息的二维数组。(但是这里数组第一项就是‘.’,这个.的用处很大)
current() :返回数组中的单元,默认取第一个值。pos()和current()是同一个东西
使用常规解法,最终payload为:
?exp=highlight_file(next(array_reverse(scandir(current(localeconv())))));
接下来逐个解析,1、 这里的var_dump(localeconv());我们能看见第一个string[1]就是一个“.”,这个点是由localeconv()产生的
2、 利用current()
函数将这个点取出来的,点代表的是当前目录,那接下来就很好理解了,我们可以利用这个点完成遍历目录的操作,相当于就是linux
中的ls
指令
3、既然current()取第一个值,那么current(localeconv())就能构造一个‘.’,而
'.'
表示当前目录,scandir('.')
将返回当前目录中的文件和子目录,这里我们得知flag所在的文件名就是flag.php
4、然而flag的文件名在比较后端我们可以通过array_reverse()将数组内容反转,让它从倒数第二的位置变成正数第二
5、移动指针读取第二个数组,参照下列数组移动操作可知我们应选用next()函数:
end() : 将内部指针指向数组中的最后一个元素,并输出
next() :将内部指针指向数组中的下一个元素,并输出
prev() :将内部指针指向数组中的上一个元素,并输出
reset() : 将内部指针指向数组中的第一个元素,并输出
each() : 返回当前元素的键名和键值,并将内部指针向前移动
6、最后用highlight_file()返回文件内容
解法二:
在知道文件名为flag.php的情况下直接读文件
如果已知文件名,改包手动添加cookie头把文件名写在PHPSESSID后面,
添加Cookie:PHPSESSID=flag.php
构造payload为:
readfile(session_id(session_start()));
---------------------------------------------------------------------------------------------------------------------------------我们来看另外一个无参rce
<?php
highlight_file(__FILE__);
if (';' === preg_replace('/[^\W]+\((?R)?\)/', '', $_GET['star'])) {
if(!preg_match('/high|get_defined_vars|scandir|var_dump|read|file|php|curent|end/i',$_GET['star'])){
eval($_GET['star']);
}
}
题目源码如上
这是gpt的解释,也就是说我们调用函数的时候不能有参数,只能像这样func1(func2());
本来还想利用?star=highlight_file(next(array_reverse(scandir(current(localeconv())))));来做的,但是很多函数这题都被过滤了
这里使用 getallheaders() 或者apache_request_headers()函数,获取全部 HTTP 请求头信息。
?star=print_r(getallheaders());
那么我们还要用到两个函数:
array_flip:反转键值
array_rand:随机取一个键名
那么什么是键值、键名?
使用burpsuite抓包后随便增加一个请求头
比如 myon:ls /(前面是请求头名字,后面是我们要执行的命令)
比如我们上面打印出来的东西:
[User-Agent] => Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36 Edg/114.0.1823.86
前面的User-Agent叫做键名,后面的内容就是键值。
实际上在这里它一定程度上对应了我们的请求头和请求头内容,
因此,我们构造payload:
?star=system(array_rand(array_flip(getallheaders())));
使用burpsuite抓包后随便增加一个请求头
比如 myon:ls /(前面是请求头名字,后面是我们要执行的命令)
关于payload的解释:
先用 getallheaders() 获取全部请求头信息,再用 array_flip() 反转键值,即将 ls / 放到键名的位置,因为 array_rand 是随机取一个键名,反转之后获取到的就是命令,如果没有进行反转,获取到的就是myon。
这里需要多发几次包,因为array_rand 是随机获取的;
原文链接:https://blog.csdn.net/Myon5/article/details/133839819
原文链接:https://blog.csdn.net/2301_76690905/article/details/134089541