news 2025/12/24 3:09:51

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

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
[网鼎杯 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博客

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2025/12/13 22:30:42

38、Python编程:回调函数、包管理与系统操作全解析

Python编程:回调函数、包管理与系统操作全解析 1. 回调函数基础 回调函数和传递函数的概念对于一些人来说可能比较陌生,但深入了解它是很有价值的。在Python中,函数是“一等公民”,这意味着可以像操作对象一样传递和处理函数。 1.1 函数作为一等公民示例 In [1]: def …

作者头像 李华
网站建设 2025/12/13 22:24:14

39_Spring AI 干货笔记之 Ollama 嵌入

一、Ollama 嵌入 使用 Ollama&#xff0c;您可以在本地运行各种 AI 模型 并从中生成嵌入。嵌入是一个浮点数向量&#xff08;列表&#xff09;。两个向量之间的距离衡量它们的相关性。距离小表示相关性高&#xff0c;距离大表示相关性低。 OllamaEmbeddingModel 实现利用了 O…

作者头像 李华
网站建设 2025/12/16 19:28:01

终极指南:解锁Quansheng对讲机隐藏功能的完整方案

终极指南&#xff1a;解锁Quansheng对讲机隐藏功能的完整方案 【免费下载链接】uv-k5-firmware-custom This is a fork of Egzumer https://github.com/egzumer/uv-k5-firmware-custom 项目地址: https://gitcode.com/gh_mirrors/uvk/uv-k5-firmware-custom 还在为对讲机…

作者头像 李华
网站建设 2025/12/20 8:06:22

AI大模型之Agent,RAG,LangChain(二)

这一期我来详细分析一下RAG的基础理论知识.RAG作为LLM重要的一种思想,在工作中的应用是相当广泛的.一.为什么使用RAG1.传统LLM在传统LLM中,有四个重要的缺陷有待解决.LLM的数据不是实时的.在这里我举个例子,比如说,不使用LLM工具,直接询问当下热点事件,大模型会回答你他不知道,…

作者头像 李华
网站建设 2025/12/17 15:14:52

CLI形态的智能编程

CLI形态的智能编程&#xff0c;是指把AI编程能力做成“命令行工具&#xff08;Command-Line Interface&#xff09;”&#xff0c;让开发者在终端里直接敲自然语言指令&#xff0c;就能完成写代码、改Bug、跑测试、部署等任务&#xff0c;而不必打开图形界面或IDE。它的核心特点…

作者头像 李华
网站建设 2025/12/17 10:33:03

说说Redis的单线程架构

回答框架建议 一句话概括核心&#xff1a;先给出精准的定义&#xff0c;纠正常见误解。详细阐述“单线程”的含义&#xff1a;具体是哪里单线程。深入分析为什么采用单线程还能如此高效&#xff1a;这是回答的精华部分。客观讨论单线程模型的优缺点&#xff1a;体现你的辩证思考…

作者头像 李华