PHP反序列化在CTF赛题中的常见利用场景

说起我第一次在CTF里被PHP反序列化玩得团团转,真是哭笑不得。那天我正准备刷Web题,忽然一个看似普通的unserialize($_GET['p'])把我直接送进了文件读取的坑,后来才发现这背后藏着一整套“魔术方法”玩意儿。

常见的利用切入口

PHP里几个魔术方法最爱被黑客盯上:__toString__wakeup__destruct__invoke。只要对象在序列化后被不经意地调用,就能把属性当成指令跑出来。

  • 读取任意文件——利用__toString在被echo时自动执行file_get_contents($this->file),常见于include($file)配合可控属性。
  • 命令执行——__destruct里写了system($this->cmd),对象销毁时直接跑shell,配合register_shutdown_function更是一键RCE。
  • 登录绕过——__wakeup里检查$this->isAdmin,只要序列化时把属性设为true,登录验证瞬间失效。
  • Gadget Chain——借助第三方库(如Laravel、Monolog)里的连环魔术方法,层层触发最终完成文件写入或代码注入。
<?php
class Flag{
    public $file;
    public function __toString(){
        echo file_get_contents($this->file);
        return "";
    }
}
?>

实战小技巧

我最常用的套路是把payload塞进php://input,配合GET参数的txt=php://input让服务器直接读取POST的序列化字符串。在线工具(比如1024tools的unserialize)能帮我快速把对象结构转成可读的数组,省下不少调试时间。

  • GET里控制file参数指向hint.php,再让txt指向php://input,实现“读取+执行”。
  • 利用O:4:"Flag":1:{s:4:"file";s:8:"flag.php";}的序列化字符串直接泄露flag
  • 别忘了把serialize()的结果做URL编码,否则GET太长会被截断。

每次看到审计报告里那句“未过滤的unserialize”,我都会忍不住笑出声——这不就是CTF里最常见的“甜点”吗?下次再遇到类似的题目,记得先把魔术方法列出来,找找有没有可以利用的属性,玩起来才会更顺手。

参与讨论

0 条评论

    暂无评论,快来发表你的观点吧!