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

反序列化漏洞1

一、PHP类与对象
1. 类
  • 概念理解: 类是共享相同结构和行为的对象的集合,可以理解为特征的提取。例如将耳朵长、尾巴短、红眼睛、吃胡萝卜、蹦跳行走的动物特征抽象为"兔子"类。
  • 代码结构:
    • 使用class关键字定义类
    • 类名遵循大驼峰命名法
    • 包含成员变量(属性)和方法(行为)
  • 成员组成:
    • 属性: 描述对象的特征,如$var1、$var2
    • 方法: 定义对象的行为,如myfunc()函数
  • 抽象特性: 类是特征的抽象集合,不是具体实例
2. 对象
  • 实例关系: 对象是类的具体实例,如"兔子类"的具体实例可以是"小白兔"
  • 创建方式: 使用new关键字实例化对象
  • 实际案例:
    • $baidu = new Site; 创建网站类的百度实例
    • $kitty = new Cat; 创建猫类的Kitty实例
    • $benz = new Car; 创建汽车类的奔驰实例
  • 面向对象原则: PHP遵循"一切皆对象"的面向对象编程思想
二、代码实例
  • 类定义:
  • 实例化过程:
    • $obj = new ClassDemo(); 创建类实例
    • $obj->echoString(); 调用对象方法
  • 执行结果: 输出成员变量$var的字符串值
  • 关键语法:
    • public 访问修饰符
    • $this 指代当前对象实例
    • -> 对象操作符
三、知识小结

知识点

核心内容

考试重点/易混淆点

难度系数

PHP类与对象

类为共享结构和行为的对象集合(如Rabbit类抽象兔子特征);对象是类的实例(如new创建Baidu网站实例)

类(抽象)vs对象(具体实例)

⭐⭐

PHP序列化与反序列化

序列化函数使用、数据格式转换意义

serialize()与unserialize()的安全风险

⭐⭐⭐

反序列化漏洞原理

恶意数据触发对象注入,破坏程序逻辑

魔术方法(如__wakeup())的利用

⭐⭐⭐⭐

CTF题目实战分析

外部网站漏洞挖掘与利用方法

输入点检测、POP链构造

⭐⭐⭐⭐

CMS漏洞案例(tCMS)

实际漏洞复现与成因分析

未过滤用户输入导致对象注入

⭐⭐⭐⭐

漏洞修复与防御

输入验证、禁用危险函数、使用安全库

__wakeup()方法的安全实现

⭐⭐⭐

一、PHP的magic函数
1. 函数作用
  • 定义:魔术方法是以双下划线(__)开头的特殊方法,当对对象执行特定操作时会覆盖PHP的默认行为
  • 数量:PHP中共有17个魔术方法,包括__construct()、__destruct()等
  • 命名规范:PHP保留所有以__开头的方法名称,不建议自定义此类方法名
  • 生命周期方法:
    • __construct():对象创建时调用(通过new或反序列化)
    • __destruct():对象销毁时调用(如脚本执行结束)
  • 类型转换方法:
    • __toString():对象被当作字符串使用时调用(如echo输出或字符串拼接)
  • 序列化相关:
    • __sleep():对象被序列化前调用
    • __wakeup():对象被反序列化后调用
    • __serialize():PHP7.4新增,替代__sleep()
    • __unserialize():PHP7.4新增,替代__wakeup()
  • 访问控制方法:
    • __call():调用不可访问方法时触发
    • __callStatic():静态调用不可访问方法时触发
    • __get():读取不可访问属性时触发
    • __set():写入不可访问属性时触发
    • __isset():对不可访问属性调用isset()或empty()时触发
    • __unset():对不可访问属性使用unset()时触发
  • 其他方法:
    • __invoke():将对象作为函数调用时触发
    • __clone():对象克隆时调用
    • __debugInfo():var_dump()对象时调用
  • 访问限制:除__construct()、__destruct()和__clone()外,所有魔术方法必须声明为public
  • 类型声明:PHP8.0起,魔术方法的类型声明必须与文档描述一致
2. 例题:magic函数案例使用
  • 实现原理:
    • 自动触发:魔术方法无需显式调用,满足条件时自动执行
    • 生命周期控制:通过预定义方法实现对对象生命周期的统一管理
    • 代码复用:避免在每个对象中重复编写相同逻辑
  • 设计目的:
    • 统一控制点:提供对象生命周期关键节点的标准控制接口
    • 减少重复代码:集中处理对象创建、使用和销毁的通用逻辑
    • 扩展性:允许开发者在不修改核心代码的情况下扩展对象行为
  • 使用场景:
    • 资源管理:在__construct中初始化资源,在__destruct中释放资源
    • 调试跟踪:通过魔术方法记录对象操作日志
    • 动态属性:使用__get/__set实现动态属性访问
    • 方法重载:通过__call实现方法重载功能
  • 注意事项:
    • 性能影响:魔术方法调用会增加额外开销
    • 命名冲突:避免自定义__开头的方法名
    • 版本兼容:注意不同PHP版本对魔术方法的支持差异
二、知识小结

知识点

核心内容

关键特性/易混淆点

应用场景

__construct()

对象创建时自动调用

通过new或反序列化触发

对象初始化、资源分配

__destruct()

对象销毁时自动调用

程序结束或对象显式销毁时触发

资源释放、清理操作

__toString()

对象被当作字符串使用时调用

echo输出或字符串拼接时触发

对象字符串化表示

__sleep()

对象序列化前执行

与serialize()相关

选择性序列化属性

__wakeup()

对象反序列化后执行

与unserialize()相关

反序列化后初始化

__call()

访问不可访问方法时触发

包含方法名和参数数组

动态方法处理

__callStatic()

静态上下文访问不可访问方法时触发

静态方法调用拦截

静态方法重载

__get()

读取不可访问属性时触发

属性访问拦截

动态属性处理

__set()

写入不可访问属性时触发

属性赋值拦截

属性访问控制

__isset()

对不可访问属性调用isset()或empty()时触发

属性存在性检查拦截

动态属性验证

__unset()

对不可访问属性调用unset()时触发

属性删除拦截

属性删除控制

__invoke()

对象被当作函数调用时触发

使对象可调用

函数式编程接口

__clone()

对象克隆时触发

通过clone关键字调用

深拷贝控制

魔术方法特点

自动触发机制

以双下划线__开头

对象生命周期控制点

设计目的

统一对象行为控制

减少重复代码

提供预置控制点

一、PHP序列化和反序列化
1. 序列化
1)序列化与反序列化概述
  • 序列化: 将对象转换成一个可存储的字符串,便于存储或传递PHP的值,同时不丢失其类型和结构。
  • 反序列化: 将已序列化的字符串变回PHP的值。
  • 魔术方法:
    • _serialize(): 在序列化之前执行,返回一个代表对象序列化形式的关联数组。
    • _unserialize(): 在反序列化时执行,用于恢复对象的属性。
  • 注意:
    • 如果类中同时定义了_serialize()和_sleep(),则只有_serialize()会被调用。
    • 如果对象实现了Serializable接口,则接口的serialize()方法会被忽略,类中的serialize()方法会被调用。
2)serialize() 函数
  • 功能: 产生一个可存储的值的表示,返回一个包含表示value的字节流的字符串。
  • 处理类型: 可处理除了resource之外的任何类型,包括包含指向其自身引用的数组。
  • 对象序列化:
    • 在序列化对象时,PHP会尝试调用对象的_sleep()方法(如果存在_serialize()则忽略_sleep()),允许对象在被序列化之前做清除操作。
  • 示例:

number=32;number = 32; number=32;

str = 'wuya';

bool=true;bool = true; bool=true;

null = NULL;

arr=array(′aa′=>1,′bbbb′=>9);arr = array('aa' => 1, 'bbbb' => 9); arr=array(′aa′=>1,′bbbb′=>9);

obj = new SerialType(data: 'somestr', pass: true);

var_dump(serialize(

number));//string(5)"i:32;"vardump(serialize(number)); // string(5) "i:32;" var_dump(serialize(number));//string(5)"i:32;"vard​ump(serialize(

str)); // string(11) "s:4:"wuya";"

var_dump(serialize(

bool));//string(4)"b:1;"vardump(serialize(bool)); // string(4) "b:1;" var_dump(serialize(bool));//string(4)"b:1;"vard​ump(serialize(

null)); // string(2) "N;"

var_dump(serialize(

arr));//string(34)"a:2:s:2:"aa";i:1;s:4:"bbbb";i:9;"vardump(serialize(arr)); // string(34) "a:2:{s:2:"aa";i:1;s:4:"bbbb";i:9;}" var_dump(serialize(arr));//string(34)"a:2:s:2:"aa";i:1;s:4:"bbbb";i:9;"vard​ump(serialize(

obj)); // string(75) "O:10:"SerialType":2:{s:4:"data";s:7:"somestr";s:16:"SerialTypepass";b:1;}"

###### 3)序列化结果解析
- **整数**: 以`i:`开头,后跟整数值,如`i:32;`。
- **字符串**: 以`s:`开头,后跟字符串长度和字符串内容,如`s:4:"wuya";`。
- **布尔值**: `b:1;`表示true,`b:0;`表示false。
- **空值**: 用`N;`表示。
- **数组**: 以`a:`开头,后跟元素个数和元素内容,如`a:2:{s:2:"aa";i:1;s:4:"bbbb";i:9;}`。
- **对象**: 以`O:`开头,后跟类名长度、类名、元素个数和元素内容,如`O:10:"SerialType":2:
- **注意**:
- 对象序列化时,私有成员变量名会拼接类名,如`s:16:"SerialTypepass";`。
- 常量不会被序列化。
###### 4)反序列化
- **功能**: 将序列化的字符串恢复成PHP的值。
- **魔术方法**:
- `_unserialize()`: 在反序列化时执行,用于恢复对象的属性。
- 如果类中同时定义了`_unserialize()`和`_wakeup()`,则只有`_unserialize()`会生效。###### 5)序列化与反序列化的应用
- **存储**: 可以将序列化后的字符串存储在文件、数据库、Redis等存储系统中。
- **传输**: 便于在网络中传输复杂的数据结构。##### 2. 其他序列化格式 <timestamp>574000</timestamp>
###### 1)序列化格式种类 
- **json字符串**: 使用$json_encode$方法,常用于数据传输,如JAVA框架和消息中间件。
- **xml字符串**: 使用$wddx_serialize_value$方法,早年流行于web service数据交换。
- **二进制格式字节数组**: 也是一种序列化方式。
###### 2)序列化示例 
- **示例对象**: `JsonClass`类,包含字符串成员变量`word`和数组成员变量`prop`。
- **json序列化**: 使用`json_encode`方法,输出为json字符串。
- **xml序列化**: 使用`wddx_serialize_value`方法,输出为xml字符串。###### 3)序列化输出 
- **json输出**: `{"word": "hello wuya", "prop": {"name": "wuya", "age": 31, "motto": "Apple keep doctor"}}`
- **xml输出**: 包含`wddxPacket`、`header`、`data`、`struct`等标签,详细描述了对象的结构和内容。###### 4)XML格式化 
- **格式化工具**: 可使用在线XML格式化工具查看XML结构,如[BEJSON]
###### 5)序列化与反序列化 
- **反序列化**: 使用相应的方法(如`json_decode`、`wddx_deserialize`)可将序列化的字符串还原为对象。###### 6)敏感字段处理 
- **敏感字段**: 如密码等,不需要序列化。
- **处理方法**: 重写`_sleep`方法,返回一个数组,包含需要序列化的变量名,排除敏感字段。###### 7)_sleep方法示例 
- **示例代码**: `User`类重写`_sleep`方法,排除`password`字段。
- **序列化结果**: 序列化字符串中不包含`password`字段。###### 8)序列化应用 
- **应用场景**: 将对象保存为字符串,存储在文件、数据库或通过网络传输,再在需要的地方还原使用。##### 3. 反序列化 <timestamp>851000</timestamp>
###### 1)反序列化例子 <timestamp>891000</timestamp>- **反序列化函数**: 使用 `unserialize()` 函数可以将已序列化的字符串还原成 PHP 的值或对象。
- **示例代码**:
```php
class User {public$username;public$nickname;private$password;public function __construct($username,$nickname,$password) {
$this->username =$username;
$this->nickname =$nickname;
$this->password =$password;}
}
// 序列化对象
$user = new User("hackerwuya", "wuya", "password123");
$serializedUser = serialize($user);
echo$serializedUser;
// 反序列化对象
$unserializedUser = unserialize($serializedUser);
var_dump($unserializedUser);
  • 注意事项:
    • 如果反序列化的字符串格式不正确,unserialize() 将返回 FALSE。
    • 如果反序列化的对象类不存在,将得到一个 __PHP_Incomplete_Class 对象,并且无法调用未定义类的方法。
  • Magic 方法:
    • _sleep(): 在对象序列化之前调用,可以用于清理对象。
    • _wakeup(): 在对象反序列化之后调用,可以用于重新初始化对象。
  • 反序列化后的对象方法调用: 反序列化后的对象可以调用其定义的方法,如 echoString()。
  • 篡改序列化字符串: 反序列化过程中可以篡改序列化字符串中的值,但需注意保持格式正确。
  • 类不存在时的处理:
    • 如果反序列化的类不存在,PHP 将返回一个 __PHP_Incomplete_Class 对象。
    • 尝试调用未定义类的方法将导致致命错误。
  • 反序列化注意事项:
    • 如果传递的字符串不可序列化,unserialize() 返回 FALSE。
    • 如果对象类未定义,反序列化得到的对象是 __PHP_Incomplete_Class。
  • 格式错误处理: 如果序列化字符串格式错误,unserialize() 将无法正确解析并返回 FALSE。
4. 序列化和反序列化的作用
1)序列化和反序列化的概念

  • 序列化: 对象和字符串之间的转换过程,将对象转换为字符串,以便进行传输或存储。
  • 反序列化: 将序列化后的字符串转换回对象的过程。
  • 注意:
    • 如果传递的字符串不可以序列化,则返回FALSE。
    • 如果对象没有预定义,反序列化得到的对象是

      PHP_Incomplete_ClassPHP\_Incomplete\_ClassPHP_Incomplete_Class

2)序列化和反序列化的作用
  • 传输对象: 序列化可以将对象转换为字符串,方便在网络中传输或存储到文件中,然后在需要的地方进行反序列化,恢复成对象。
  • 用作缓存: 序列化后的对象可以存储到Cookie或Session中,作为缓存数据。在需要时,通过反序列化可以快速恢复对象状态。
  • 配合magic方法: 在反序列化时,可以自动触发magic方法(如__wakeup()),进行一些初始化或清理工作。
3)序列化和反序列化与magic函数的关联
  • magic函数: 在PHP中,magic函数是指一些以双下划线(__)开头的方法,它们在特定情况下会自动被调用。
  • 关联: 反序列化过程中,如果对象类中定义了__wakeup()等magic方法,这些方法会在反序列化时自动被调用,可以用于执行一些初始化操作或恢复对象状态。
5. 反序列化与Magic函数
1)序列化和反序列化例题



  • _unserialize()与_wakeup()的关系
    • 关系: 如果类中同时定义了_unserialize()和_wakeup()两个魔术方法,则只有_unserialize()方法会生效,_wakeup()方法会被忽略。
    • 版本: 此特性自PHP7.4.0起可用。
  • _serialize()与_sleep()的关系
    • 关系: 如果类中同时定义了_serialize()和_sleep()两个魔术方法,则只有_serialize()方法会被调用,_sleep()方法会被忽略。
    • 接口: 如果对象实现了Serializable接口,接口的serialize()方法会被忽略,作为代替类中的_serialize()方法会被调用。
  • _unserialize()的用途
    • 用途: _unserialize()用于定义对象序列化友好的任意表示,数组的元素可能对应对象的属性,但这并不是必须的。
    • 触发: 在反序列化时,如果存在_unserialize()魔术方法,则会自动调用此方法,并传递从_serialize()返回的恢复数组。
  • 示例代码
    • 代码示例:

this−>dsn=this->dsn =this−>dsn=

dsn;

this−>username=this->username =this−>username=

username;

this−>password=this->password =this−>password=

password;

this->connect(); } public function __serialize() { echo "_serialize\n"; } public function __unserialize(

data) {

echo "_unserialize\n";

}

public function __wakeup() {

echo "_wakeup\n";

}

}

- **测试**: 通过创建对象并调用unserialize()方法,观察_serialize()、_unserialize()和_wakeup()的触发情况。
###### 2)版本影响与测试 
- 版本差异
- **版本差异**: _unserialize()方法自PHP7.4.0起可用,在低于此版本的PHP中,反序列化时会调用_wakeup()方法。- **测试方法**: 通过在不同PHP版本下运行相同的测试代码,观察_unserialize()和_wakeup()的调用情况。
- 测试示例
- **测试代码**:
```php
$obj1 = new UnSerializeTest();
$obj2 = unserialize('0:15:"UnSerializeTest":1:{s:3:"var";s:15:"hello wuyaziabc";}');
$obj2->echoString();
  • 结果分析: 在PHP7.4.0及以上版本,反序列化时会调用_unserialize()方法;在低于此版本的PHP中,会调用_wakeup()方法。
3)PHP版本管理
  • PHP Study工具
    • 工具介绍: PHP Study是一个本地的集成工具,可以方便地下载和安装不同版本的PHP。
    • 版本管理: 通过在PHP Study中添加不同版本的PHP,可以方便地在不同项目中使用不同版本的PHP进行开发和调试。
  • 版本配置
    • 配置方法: 在项目的配置中指定使用的PHP版本路径,即可使用该版本的PHP进行运行和调试。
    • 注意事项: 确保指定的PHP版本路径正确,且该版本的PHP已正确安装和配置。
二、知识小结

知识点

核心内容

考试重点/易混淆点

难度系数

PHP序列化和反序列化

PHP对象存活于内存时可访问属性和方法,消亡后则不可访问;序列化是将对象转换成字符串形式以便存储和传输,反序列化是将字符串恢复成对象。

序列化和反序列化的概念、方法、应用场景。

★★★

序列化方法

使用serialize()方法将对象转换成字符串,可存储于文件、数据库、Redis等。

serialize()方法的使用,不同数据类型序列化后的格式。

★★★★

反序列化方法

使用unserialize()方法将字符串恢复成对象。

unserialize()方法的使用,反序列化后的对象状态。

★★★

序列化格式解读

整数、字符串、布尔值、空值、数组、对象的序列化格式。

各种数据类型序列化后的字符串格式,特别是对象和数组的复杂格式。

★★★★☆

序列化注意事项

对象序列化时不包括方法和常量,只包括类名、属性和值。

方法和常量不被序列化,私有成员变量序列化时包含类名。

★★★

其他序列化格式

JSON、XML、二进制等序列化格式。

JSON和XML序列化的方法和应用场景。

★★

防止敏感信息序列化

重写sleep方法,返回需要序列化的属性数组,排除敏感信息。

sleep方法的重写,防止敏感信息被序列化。

★★★★

反序列化注意事项

反序列化时类不存在会报错,但仍可返回对象;字符串格式错误会返回false。

类不存在时的反序列化结果,字符串格式错误的处理。

★★★★

相关文章:

  • python pymysql如何保证数据库更新成功
  • 12.thinkphp验证
  • 隧道调频广播覆盖的实现路径:隧道无线广播技术赋能行车安全升级,隧道汽车广播收音系统助力隧道安全管理升级
  • 海量信息处理分析有效决策
  • 控件和QWidget核心属性
  • Android——Activity与Fragment通信
  • SpringBoot 常用注解大全
  • 智能分析网关摄像机实时接入分析平台,如何开启周界防护智能新时代?
  • Allegro23.1新功能之将差分过孔替换成via structure操作指导
  • ArkTS中的空安全:全面解析与实践
  • 使用浏览器的Clipboard API实现前端复制copy功能
  • django.db.utils.OperationalError: (1050, “Table ‘你的表名‘ already exists“)
  • HTML基础标签
  • YOLOv12 改进有效系列目录 - 包含卷积、主干、检测头、注意力机制、Neck上百种创新机制 - 针对多尺度、小目标、遮挡、复杂环境、噪声等问题!
  • Synopsys 逻辑综合的整体架构概览
  • 电子电子架构 --- 主机厂视角下ECU开发流程
  • 【前端】如何检查内存泄漏
  • 如何把两个视频合并成一个视频?无需视频编辑器即可搞定视频合并
  • 知识知多少——Matplotlib 库
  • QT窗口相关控件及其属性
  • 中日友好医院通报“医师肖某被举报”:基本属实,开除党籍并解聘
  • 上海市政府常务会议研究抓好稳就业稳企业稳市场稳预期工作,让企业感受温度
  • 伊朗外长: 美伊谈判进展良好,讨论了很多技术细节
  • 70后供销合作总社理事会原副主任侯顺利任中国融通外部董事
  • 《深化养老服务改革发展的大湾区探索》新书将于今年6月出版
  • 印媒称印巴在克什米尔控制线沿线发生小规模交火,巴方暂未回应