web渗透PHP反序列化漏洞
web渗透PHP反序列化漏洞
1)PHP反序列化漏洞
反序列我们可以控制对象中的值进行攻击
O:1:"C":1:{s:3:"cmd";s:8:"ipconfig";}
http://127.0.0.1/1.php?x=O:1:%22C%22:1:{s:3:%22cmd%22;s:3:%22ver%22;}
常见的反序列化
魔术方法:PHP 中特殊方法(如__construct、__destruct、__wakeup等)在对象生命周期自动调用,若方法中存在危险操作(如命令执行),可被反序列化触发。
漏洞绕过:如 CVE-2016-7124(PHP 5.6.25 前的__wakeup方法绕过,通过修改对象属性数量使__wakeup失效)。
原生类:利用 PHP 内置类(如DirectoryIterator、SimpleXMLElement)实现文件遍历、XXE 等攻击。
Phar 文件:Phar 文件包含序列化元数据,即使无unserialize函数,通过文件操作函数(如file_exists)也可触发反序列化。
字符串逃逸:当程序对序列化字符串进行过滤 / 替换时,可通过构造特殊字符串改变序列化结构,实现属性注入。
黑盒查看漏洞:
功能关联:观察功能是否涉及对象存储 / 传输(如用户配置、会话管理、数据备份),此类功能可能使用序列化。
参数测试:对疑似传入序列化数据的参数(如data、payload、user)传入畸形序列化字符串,观察是否返回 PHP 错误(如unserialize()错误)。
白盒代码审计:
关键词搜索:查找unserialize()函数,确认其参数是否可控(如来自用户输入的$_GET、$_POST、$_COOKIE)。
跟踪变量:确认可控变量是否直接传入unserialize(),且未经过严格过滤。
分析类结构:检查反序列化涉及的类是否包含危险魔术方法或函数调用(如system()、exec())。
2)反序列检查方法
黑盒测试:
参数探测:收集所有用户可控参数(GET/POST/COOKIE/ 请求体),尝试传入基础序列化字符串(如O:0:{}),观察响应差异。
畸形测试:传入不完整 / 错误的序列化数据(如O:1:"A":),若返回unserialize()相关错误(如Error at offset),说明存在反序列化操作。
功能触发:结合业务功能(如提交配置、恢复数据),在关键步骤传入恶意序列化字符串,观察是否执行预期操作(如文件生成、命令输出)。
白盒测试:
函数定位:全局搜索unserialize(),标记所有调用位置。
数据流分析:确认unserialize()的参数是否来自用户输入,是否经过过滤(如preg_replace、htmlspecialchars等),过滤规则是否可绕过。
类与方法审计:分析反序列化涉及的类及其魔术方法,判断是否存在可利用的危险操作(如调用eval()、文件写入等)。
3)反序列工具
PHPGGC:PHP 反序列化漏洞利用工具,包含多种框架(如 Laravel、ThinkPHP、Yii)的 Gadget 链,可直接生成恶意序列化字符串。
Burp Suite 插件:如Deserialization Scanner,可自动检测请求中可能存在的反序列化参数并尝试注入测试 payload。
手动构造工具:Python 脚本(如通过pickle模块辅助生成符合格式的序列化字符串)、在线 PHP 序列化 / 反序列化工具(用于验证 payload 格式)。
漏洞扫描器:Nessus、AWVS 等包含反序列化漏洞检测模块,可批量扫描目标是否存在相关漏洞。
4)靶场
DVWA(Damn Vulnerable Web Application):包含反序列化漏洞模块,适合入门学习基础利用。
CTF 平台:CTFtime、XCTF 等平台的 Web 题目中常见反序列化考点(如 “安恒杯”“西湖论剑” 相关题目)。
VulnHub 靶机:如Mutillidae II(包含反序列化漏洞场景)、Metasploitable 3(集成多种 Web 漏洞)。
框架漏洞环境:通过Vulhub搭建特定框架漏洞环境(如 ThinkPHP 5.x 反序列化漏洞、Laravel deserialization RCE)。
自定义环境:手动编写含漏洞的 PHP 代码(如调用unserialize($_GET['x'])且类中包含__destruct方法执行system()),本地测试验证。
<?php
// 一个简单的文件操作类
class FileHandler {
private $filename;
private $content;
public function __construct($filename = '') {
$this->filename = $filename;
}
// 魔术方法:当对象被反序列化时调用
public function __wakeup() {
// 危险操作:直接使用成员变量作为命令执行
if (!empty($this->filename)) {
// 这里存在命令注入漏洞
exec("type " . $this->filename, $output);
$this->content = implode("\n", $output);
}
}
public function getContent() {
return $this->content;
}
}
// 接收用户输入的序列化数据
if (isset($_GET['data'])) {
$data = $_GET['data'];
// 反序列化操作,存在安全风险
$fileHandler = unserialize($data);
if ($fileHandler instanceof FileHandler) {
echo "<pre>文件内容:\n" . $fileHandler->getContent() . "</pre>";
} else {
echo "无效的数据格式";
}
} else {
echo "请通过data参数提交数据";
}
?>