BugKu实战:从备份文件泄露到PHP弱类型漏洞的完整利用链
1. 从备份文件泄露开始的信息收集
做CTF题目时,信息收集永远是第一步。很多运维人员为了方便,会在服务器上留下备份文件,比如.bak、.swp、.git等。这些文件往往包含了源代码、配置文件等敏感信息。我在实战中遇到过不少因为备份文件泄露导致的安全问题,这次我们就从备份文件泄露开始,一步步拿到flag。
首先,我们需要使用工具对目标网站进行目录扫描。这里推荐使用dirsearch,它是一个基于Python的目录扫描工具,速度快、效果好。安装也很简单,直接克隆GitHub仓库即可:
git clone https://github.com/maurosoria/dirsearch.git cd dirsearch运行dirsearch扫描目标网站:
python3 dirsearch.py -u http://example.com -e php,bak,swp参数说明:
-u:指定目标URL-e:指定要扫描的文件扩展名,这里我们重点关注php、bak和swp文件
扫描完成后,如果运气好,可能会发现类似index.php.bak这样的备份文件。这就是我们的突破口。
2. 分析泄露的PHP源码
假设我们通过dirsearch扫描发现了index.php.bak文件,下载下来分析它的内容。通常备份文件就是源代码的副本,我们可以直接查看其中的逻辑。
从题目给出的源码来看,关键部分是这样的:
$str = strstr($_SERVER['REQUEST_URI'], '?'); $str = substr($str,1); $str = str_replace('key','',$str); parse_str($str); echo md5($key1); echo md5($key2); if(md5($key1) == md5($key2) && $key1 !== $key2){ echo $flag."取得flag"; }这段代码的逻辑很清晰:
- 从URL中获取查询字符串
- 去掉所有的'key'字符串(这是个干扰项)
- 解析查询字符串为变量
- 比较$key1和$key2的md5值,如果相等且$key1不等于$key2,就输出flag
这就是典型的PHP弱类型比较漏洞。PHP在比较时会进行类型转换,导致一些特殊的值在比较时会出现意想不到的结果。
3. PHP弱类型比较漏洞详解
PHP的弱类型比较是个老生常谈的问题了,但在CTF中依然经常出现。理解这个漏洞的原理,对安全测试很有帮助。
PHP中有两种比较运算符:
==:松散比较,会进行类型转换===:严格比较,不会进行类型转换
在本题中,使用的是==比较,这就给了我们可乘之机。具体来说,当比较两个值的md5时,有以下几种绕过方式:
3.1 使用数组绕过
md5函数无法处理数组,如果传入数组,md5会返回NULL。因此,可以构造两个不同的数组,它们的md5值都是NULL,在松散比较时会被认为相等。
payload示例:
http://example.com/?kekeyy1[]=a&kekeyy2[]=b3.2 使用科学计数法绕过
PHP在处理以"0e"开头的字符串时,会将其解释为科学计数法(0乘以10的n次方),结果就是0。因此,如果两个不同的字符串经过md5后都变成"0e"开头的形式,它们的松散比较就会相等。
已知的一些md5后为"0e"开头的字符串:
- 240610708 → 0e462097431906509019562988736854
- QNKCDZO → 0e830400451993494058024219903391
- s878926199a → 0e545993274517709034328855841020
payload示例:
http://example.com/?kekeyy1=240610708&kekeyy2=QNKCDZO4. 构造payload获取flag
根据上面的分析,我们可以构造两种不同的payload来获取flag。
4.1 数组绕过法
这种方法简单直接,适用于大多数PHP弱类型比较的场景。构造URL如下:
http://example.com/?kekeyy1[]=a&kekeyy2[]=b注意观察题目源码中的str_replace('key','',$str),它会去掉所有的'key'字符串。所以我们在参数名中使用'kekeyy',经过替换后变成'keyy',这样就能保留我们需要的变量名。
4.2 科学计数法绕过法
这种方法需要找到特定的字符串,但更加隐蔽。使用已知的md5碰撞字符串:
http://example.com/?kekeyy1=240610708&kekeyy2=QNKCDZO这两种方法都能满足md5($key1) == md5($key2) && $key1 !== $key2的条件,从而获取到flag。
5. 防御措施
作为开发者,如何避免这类安全问题呢?我有几点建议:
- 不要使用松散比较:在安全相关的代码中,始终使用
===进行严格比较。 - 妥善处理备份文件:不要在web目录下存放备份文件,如果必须存放,确保配置服务器不解析这些文件。
- 使用hash_equals函数:PHP提供了
hash_equals函数来安全地比较哈希值,它能防止时序攻击。 - 定期安全审计:使用自动化工具扫描网站,检查是否存在备份文件泄露等常见问题。
6. 实战中的思考
在实际渗透测试中,备份文件泄露是个很常见的入口点。我遇到过不少案例,都是通过扫描发现了备份文件,进而分析出更严重的漏洞。比如有一次,通过.git目录泄露,我拿到了完整的源代码,进而发现了数据库配置信息,最终获取了整个系统的控制权。
对于CTF选手来说,掌握这些基础漏洞的原理和利用方法非常重要。它们往往是更复杂攻击链的第一步。建议新手多练习这类基础题目,理解其中的原理,而不仅仅是记住payload。
