【WEB】[BUUCTF] <GXYCTF2019禁止套娃>《php函数的运用》
目录
一.GitHack的安装和使用
1.介绍
2.安装
3.使用
二.flag
三.解析
1.localeconv()
编辑
2.current()
3.scandir()
4.array_reverse()
5.next()
6.highlight_file()
考点:GitHack,rce
难点:php函数的运用
一.GitHack的安装和使用
1.介绍
GitHack 是一款用于利用 Web 目录下 .git 泄露、恢复完整源码的 Python 工具,支持从 .git/index 与对象库重建文件与历史,适合安全审计与渗透测试场景。
2.安装
在GitHub上下载
GitHackhttps://github.com/lijiejie/GitHack
3.使用
GitHack工具是用python写的,在cmd上使用
首先打开下载后的文件,在上方输入cmd
使用格式(url后面是/.git)
python GitHack.py url
得到的源码在打开的文件夹内
得到了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__);
?>
代码分析:
- 协议过滤:禁止使用 data://、filter://、php://、phar:// 等可能用于读取文件的协议。
- 代码结构限制:输入的 exp 必须是纯函数嵌套结构(如 a (b (c ()))),替换函数调用部分后需仅剩分号。
- 关键词过滤:禁止包含 et、na、info、dec 等可能涉及文件操作或信息获取的字符串。
二.flag
?exp=highlight_file(next(array_reverse(scandir(pos(localeconv())))));
flag{fcc9dc99-915c-47b1-b53a-311c22946242}
三.解析
1.localeconv()
localeconv()
是一个 PHP 内置函数,它的作用是返回一个包含本地化数字和货币格式信息的关联数组。在大多数环境下,尤其是默认的 "C" 或 "en_US" locale,这个数组的第一个元素(键名为
decimal_point
)的值是一个点号.
。在我们的 payload 中,
localeconv()
并非直接用于获取地区信息,而是被巧妙地当作一个返回数组的“工具函数”来使用。我们的最终目标是获取
scandir(‘.’)
的结果,即扫描当前目录下的文件列表。.
代表当前目录。然而,题目代码的过滤规则
'[a-z,_]+\((?R)?\)'
不允许我们直接传入字符串‘.’
。规则只允许我们使用无参数的函数调用来嵌套组合。所以,我们需要找到一个无参数且返回值为字符串
‘.’
的函数。
localeconv()
完美地满足了这一要求。
2.current()
localeconv()
:首先,这个函数返回一个庞大的本地化信息数组,其结构类似于:Array ([decimal_point] => ‘.’, // 这是第一个元素![thousands_sep] => ‘’,[int_curr_symbol] => ‘’,... // 更多元素 )
current()
:接着,current()
函数被用于获取这个数组内部指针当前指向的元素的值。由于这个数组刚被返回,它的内部指针自然指向第一个元素decimal_point
,其值就是字符串‘.’
。所以,
current(localeconv())
的最终结果就是字符串‘.’
。这相当于我们“凭空”创造了一个点号,而这个点号正是
scandir()
函数所需要的参数,用来表示“当前目录”。
3.scandir()
scandir()
是一个 PHP 内置函数,它的作用是列出指定路径中的文件和目录。它会返回一个数组,其中包含指定目录下的所有文件和目录的名称。(
scandir()
函数必须传入一个参数,它不会默认扫描当前目录。 如果不传入参数,PHP 会抛出一个错误。)在我们的 payload 中:
scandir(current(localeconv()))
这行代码的最终效果是
scandir(‘.’)
。它的作用是获取当前目录(即网站根目录)下的所有文件和文件夹列表。这是我们寻找
flag.php
文件的唯一方法。
4.array_reverse()
array_reverse()
是一个 PHP 内置函数,它的作用是返回一个元素顺序相反的数组。它接受一个数组作为输入,然后创建一个新的数组,其中元素的排列顺序与原始数组完全相反。在我们的 payload 中,
array_reverse()
的作用是创建一个文件列表的反向副本,让目标文件(flag.php)出现在更靠前的位置。
5.next()
next()
是一个 PHP 内置函数,它的作用是将数组的内部指针向前移动一位,并返回移动后指针所指向元素的值。在我们的 payload 中,
next()
的作用是在文件列表数组中移动指针,使其指向flag.php
。
6.highlight_file()
highlight_file()
是一个 PHP 内置函数,它的作用是语法高亮显示一个PHP文件的源代码。它会读取指定文件的内容,并用HTML标签对PHP代码进行着色处理,使其在浏览器中更容易阅读。在我们的 payload 中,
highlight_file()
的作用是读取并显示flag.php
文件的内容。
flag{ea83431e-cff7-485e-a4fe-7db8d29c4ef3}