当前位置: 首页 > news >正文

[网鼎杯 2020 青龙组]AreUSerialz(个人记录写题笔记,含PHP反序列化的原理、漏洞成因以及利用技巧)

源代码

<?php include("flag.php"); highlight_file(__FILE__); class FileHandler { protected $op; protected $filename; protected $content; function __construct() { $op = "1"; $filename = "/tmp/tmpfile"; $content = "Hello World!"; $this->process(); } public function process() { if($this->op == "1") { $this->write(); } else if($this->op == "2") { $res = $this->read(); $this->output($res); } else { $this->output("Bad Hacker!"); } } private function write() { if(isset($this->filename) && isset($this->content)) { if(strlen((string)$this->content) > 100) { $this->output("Too long!"); die(); } $res = file_put_contents($this->filename, $this->content); if($res) $this->output("Successful!"); else $this->output("Failed!"); } else { $this->output("Failed!"); } } private function read() { $res = ""; if(isset($this->filename)) { $res = file_get_contents($this->filename); } return $res; } private function output($s) { echo "[Result]: <br>"; echo $s; } function __destruct() { if($this->op === "2") $this->op = "1"; $this->content = ""; $this->process(); } } function is_valid($s) { for($i = 0; $i < strlen($s); $i++) if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125)) return false; return true; } if(isset($_GET{'str'})) { $str = (string)$_GET['str']; if(is_valid($str)) { $obj = unserialize($str); } }

漏洞点分析

  1. 反序列化用户输入unserialize($_GET['str'])直接反序列化用户可控数据

  2. 危险方法调用read()方法中的file_get_contents()可以读取任意文件

  3. 属性可控:通过反序列化可以控制类的属性值

  4. 构造函数缺陷:构造函数中使用局部变量而非类属性

知识点梳理

1. PHP序列化与反序列化基础

序列化:将对象转换为字符串,便于存储或传输

$obj = new FileHandler(); $serialized = serialize($obj); // 输出:O:11:"FileHandler":3:{...}

反序列化:将字符串还原为对象

$obj = unserialize($serialized);

2. PHP魔术方法

​​​​​​​​​​​​​​
  • __construct():构造函数,对象创建时调用

  • __destruct():析构函数,对象销毁时调用

  • __wakeup():反序列化时调用

  • __sleep():序列化时调用

更多魔术方法可看:PHP之十六个魔术方法详解_php魔术方法-CSDN博客

在本题中,关键魔术方法的执行顺序:

​​​​​​​​​​​​​​
  1. unserialize()创建对象

  2. 执行__construct()(如果存在)

  3. 脚本结束,执行__destruct()

3. 可见性修饰符与序列化

PHP中属性的可见性影响序列化格式:

​​​​​​​​​​​​​​
  • public属性名

  • protected\x00*\x00属性名

  • private\x00类名\x00属性名

示例:

class Test { public $public = "public"; protected $protected = "protected"; private $private = "private"; } // 序列化输出包含不可见字符

4. PHP类型比较

  • 弱比较(==):类型转换后比较值(只比较值,不比较类型)

    2 == "2" // true 0 == "abc" // true "1e3" == 1000 // true
  • 严格比较(===):比较值和类型

    2 === "2" // false 0 === "abc" // false
重要区别总结
比较方式示例结果说明
弱比较 (==)2 == "2"true类型转换后值相等
严格比较 (===)2 === "2"false类型不同,值相等也没用
弱比较 (==)0 == "abc"true字符串"abc"转为整数是0
严格比较 (===)0 === "abc"false类型和值都不同
弱比较 (==)false == "0"true都转换为布尔值比较
严格比较 (===)false === "0"false类型不同

5. 文件读取技巧

​​​​​​​​​​​​​​
  • 直接读取:file_get_contents("flag.php")

  • PHP Wrapper读取源码:php://filter/convert.base64-encode/resource=flag.php

  • 目录遍历:./flag.php../flag.php

漏洞利用过程

第一步:分析利用链

目标:读取flag.php文件
利用链:unserialize() -> __construct() -> process() -> read() -> file_get_contents()

第二步:绕过限制

​​​​​​​​​​​​​​
  1. 绕过is_valid()过滤:只允许ASCII 32-125的字符,我们的payload符合要求

  2. 绕过__destruct()修改:使用整数2而非字符串"2"

  3. 利用构造函数缺陷:构造函数使用局部变量,不影响反序列化设置的属性

第三步:构造payload

使用public属性和整数2

O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";s:0:"";}

第四步:执行效果

​​​​​​​​​​​​​​
  1. 反序列化设置$op=2,$filename="flag.php"

  2. 执行__construct(),但局部变量不影响属性值

  3. process()$this->op == "2"为 true(弱比较)

  4. 执行read(),读取flag.php

  5. 输出flag内容

  6. __destruct()$this->op === "2"为 false(严格比较),不修改$op​​​​​​​

扩展知识

1. PHP反序列化漏洞常见利用点

  • POP链构造:寻找从源点到危险函数执行的路径

  • Phar反序列化:通过Phar协议触发反序列化

  • 内置类利用:使用SimpleXMLElementSoapClient等内置类

2. 自动化工具

  • PHPGGC:PHP反序列化payload生成工具

  • CodeQL:静态代码分析工具,可用于发现反序列化漏洞

3. 相关CVE

  • CVE-2016-7124__wakeup()绕过漏洞

  • CVE-2019-11043:PHP-FPM漏洞

  • CVE-2020-7068get_headers()漏洞

总结

通过本题我们学习了:

  1. PHP反序列化基本流程:序列化格式、魔术方法执行顺序

  2. 类型比较的差异:弱比较与严格比较的安全影响

  3. 属性可见性的处理:public/protected/private在序列化中的表现

  4. 漏洞链构造:从用户输入到危险函数的完整路径

  5. 安全编码实践:如何避免和修复这类漏洞

反序列化漏洞是Web安全中常见且危害较大的漏洞类型,理解其原理和利用方式对于安全开发和渗透测试都至关重要。

参考:PHP之十六个魔术方法详解_php魔术方法-CSDN博客

http://www.gsyq.cn/news/94588.html

相关文章:

  • Comsol Multiphysics数值模拟
  • 战网注册后显示无法登录
  • PINBAI平板电脑维修实例
  • 13. django中间件
  • 人工智能之数学基础:离散条件分布和连续条件概率密度
  • 精通 Flutter 网络请求:从基础 GET/POST 到拦截器 + 缓存 + 断点续传的全维度实践
  • 前端最新技术,零基础入门到精通,收藏这篇就够了
  • 前端失业有多严重?
  • 第二章-依赖属性
  • ARM 架构中的数据内存屏障指令 DMB
  • TileLang终极指南:45分钟内打造你的首个高性能GPU算子
  • 窗口相关操作的总结
  • 北京陪诊服务权威推荐榜单 - 品牌排行榜单
  • 2026中专毕业想做出纳,考哪些证书企业比较认可?这些证让你轻松入职!
  • 峰值检测电路
  • 量子计算驱动的分布式云存储系统在数据安全与高效检索中的创新应用 - 教程
  • 从零到一:构建一个实时语音翻译应用(Vue3 + Web Speech API)
  • 基于PyTorch的深度学习基础课程之十:损失函数
  • Spark:革命性的命令行数据可视化工具,让DevOps监控更高效
  • 基于Java的安全生产智慧管理系统的设计与实现全方位解析:附毕设论文+源代码
  • 基于Java的安全生产智经营理系统的设计与实现全方位解析:附毕设论文+源代码
  • 基于Java的安全生产检查统计分析智慧管理系统的设计与实现全方位解析:附毕设论文+源代码
  • 3步打造Switch专属开机动画:让你的主机从启动就与众不同
  • 北京上门收画服务权威推荐榜单​ - 品牌排行榜单
  • 重练算法(代码随想录版) day39 - 动态规划part7
  • LLM - 从 Prompt 到上下文工程:面向 Java 的生产级 AI Agent 设计范式
  • AI元人文构想:元协议、行为重塑与文明免疫系统——通往意义原生的智能未来
  • 影刀RPA×AI强强联合!小红书笔记转化数据智能分析,3分钟洞察爆款密码![特殊字符]
  • test tags - itnews
  • 20251213 - 最小生成树