作为网安初学者,PHP是绕不开的核心知识点之一,尤其是类与对象、序列化与反序列化,不仅是PHP基础,更是后续挖掘反序列化漏洞的关键。我结合自己的学习笔记,整理了这篇入门内容,适合和我一样刚接触网安的小伙伴一起夯实基础,避开常见安全坑。
一、PHP核心基础:类与对象
在PHP中,类与对象是面向对象编程的核心,也是理解后续反序列化漏洞的前提,先把基础概念吃透,再谈漏洞就会轻松很多。
1. 核心概念拆解
类:对象的“抽象模板”,相当于一个“蓝图”,定义了对象具备的属性(数据)和方法(行为)。比如“用户类”,就可以定义用户的姓名、年龄(属性),以及登录、获取信息(方法)。
对象:类的“具体实例”,是根据类这个“蓝图”创建出来的实体。比如根据“用户类”,创建出“张三”这个具体的用户对象,张三的姓名、年龄就是这个对象的具体数据。
属性:类中定义的变量,专门用来存储对象的数据。比如用户对象的
$name(姓名)、$age(年龄),都是属性,用来描述对象的特征。方法:类中定义的函数,用来实现对象的功能。比如用户对象的
getInfo()(获取用户信息)、login()(用户登录),通过方法实现对象的具体行为。$this:类内部的“当前对象引用”,相当于对象的“自我指针”,用来在类内部访问当前对象的属性和方法。比如在类中用
$this->name,就能访问当前对象的$name属性。
2. 简单示例
下面是一段简单的PHP代码,可以把上面的概念串联起来看,如果有不会的也欢迎私信我~
<?php // 定义一个用户类(模板) class User { // 定义属性(存储数据) public $name; public $age; // 定义方法(实现功能) public function getInfo() { // 用$this访问当前对象的属性 return "姓名:" . $this->name . ",年龄:" . $this->age; } public function login() { echo $this->name . " 登录成功!"; } } // 创建对象(类的具体实例) $user1 = new User(); $user1->name = "张三"; $user1->age = 20; // 调用对象的方法 echo $user1->getInfo(); // 输出:姓名:张三,年龄:20 $user1->login(); // 输出:张三 登录成功! ?>二、序列化与反序列化
序列化与反序列化是PHP中对象持久化、数据传输的核心机制,但也是反序列化漏洞的根源。简单来说,就是“对象的打包与解包”过程。
1. 核心定义
序列化:将内存中的对象状态(属性、值等),转换为可存储(如写入文件)或可传输(如网络传输)的格式(通常是字节流或字符串)的过程。目的是保存对象的状态,方便后续使用。
反序列化:将序列化后的数据(如字符串),恢复为内存中原来的对象的过程。相当于把“打包好的对象”解包,还原成可操作的对象实例。
2. 核心函数(实操必备)
PHP提供了两个核心函数,实现序列化与反序列化,直接上手实操:
(1)序列化函数:serialize()
作用:将变量(通常是对象)序列化为字符串,可配合var_dump()输出查看序列化结果。
<?php class User { public $name = "张三"; public $age = 20; } $user = new User(); // 序列化对象,并用var_dump输出结果 var_dump(serialize($user)); ?>运行结果如下图(序列化后的字符串):
string(52) "O:4:"User":2:{s:4:"name";s:6:"张三";s:3:"age";i:20;}"
序列化后的字符串包含了类名、属性数量、属性名和属性值,是后续反序列化的核心数据:
(2)反序列化函数:unserialize()
作用:将序列化后的字符串,恢复为原来的对象,可直接操作该对象。
<?php class User { public $name = "张三"; public $age = 20; } $user = new User(); // 先序列化,再反序列化 $serialized = serialize($user); $unserialized = unserialize($serialized); // 反序列化后,可正常调用对象的方法 var_dump($unserialized->getInfo()); // 输出对象的信息 ?>补充:实际开发中,序列化常用于数据缓存、跨页面传输;但在网安领域,一旦反序列化的数据被攻击者控制,就会引发严重漏洞。
三、反序列化漏洞触发核心
对于网安初学者来说,重点不是掌握序列化的用法,而是理解“反序列化漏洞”的触发机制,这是后续挖洞、防护的关键。而漏洞的核心,就和PHP的魔术方法密切相关。
1. 先懂魔术方法(漏洞触发的“开关”)
PHP中的魔术方法,是以两个下划线(__)开头的特殊方法,不需要手动调用,会在特定场景下自动触发。其中,和反序列化漏洞最相关的,就是__wakeup()方法。
魔术方法的触发场景:
- new实例化对象时,会触发
__construct(); - 反序列化时,会触发
__wakeup(); - 对象被销毁时,会触发
__destruct()。
2. __wakeup():反序列化漏洞的核心入口
触发机制:当调用
unserialize()函数,对数据进行反序列化时,会自动执行对象所属类中的__wakeup()方法(如果该方法存在)。核心作用:正常情况下,用于反序列化后重建对象状态、恢复资源(比如重新连接数据库)、数据校验,是PHP提供的“安全机制”。
安全重点(漏洞关键):正因为
__wakeup()会自动执行,一旦攻击者控制了反序列化的数据,就可能利用该方法执行危险操作(比如调用系统命令、写入恶意文件),从而引发漏洞。因此,开发时必须避免在__wakeup()中执行危险操作,同时做好输入校验。
3. 漏洞示例
以下是一个简单的漏洞代码示例,帮助理解漏洞触发过程(实际漏洞会更复杂,但核心逻辑一致):
<?php class Evil { public $cmd; // 反序列化时自动执行__wakeup() public function __wakeup() { // 危险操作:执行系统命令 system($this->cmd); } } // 攻击者构造恶意序列化字符串,控制$cmd的值 $payload = 'O:4:"Evil":1:{s:3:"cmd";s:10:"id;whoami";}'; // 反序列化,触发__wakeup(),执行恶意命令 unserialize($payload); ?>上述代码中,攻击者通过构造序列化字符串,控制了$cmd的值,反序列化时自动执行__wakeup(),调用system()函数执行恶意系统命令,从而控制服务器。
四、拓展:高危函数与漏洞补充
结合反序列化漏洞,补充几个网安学习中必记的高危函数和漏洞类型,这些都是后续挖洞时经常遇到的“攻击点”。
1. 高危函数(禁止随意使用)
system():直接执行系统命令,属于高危危险函数,一旦被攻击者利用,可直接控制服务器,开发时需避免使用,或严格校验输入。
代码执行函数:如
eval()、exec(),可直接执行传入的字符串作为PHP代码,极易被攻击者利用,导致服务器被完全控制,生产环境中需禁用这类函数(可通过php.ini配置禁用)。
2. 文件包含相关(常见漏洞类型)
文件包含:通过
include()、require()函数,将另一个文件的内容复制到当前文件中并执行,是PHP中常用的功能。远程文件包含:若
include()、require()函数的参数的是远程文件路径,且参数可控,就会形成远程文件包含漏洞,攻击者可包含远程恶意文件,执行恶意代码。文件包含漏洞:核心是“参数可控”,攻击者可在URL中通过参数,直接指定要包含的文件(如恶意脚本),从而执行恶意代码,控制网站。
五、学习小结
作为网安初学者,学习PHP类与对象、序列化与反序列化,核心是抓住“漏洞触发点”:
先夯实基础:理解类、对象、属性、方法、$this的核心概念,能看懂简单的PHP面向对象代码;
掌握核心机制:明白序列化是“打包”、反序列化是“解包”,记住两个核心函数的用法;
重点突破漏洞:牢记
__wakeup()的触发机制,理解“反序列化+危险操作”如何形成漏洞;牢记高危函数:禁用或严格控制system()、eval()等高危函数,避免人为引入漏洞。
后续会继续深入学习反序列化漏洞的具体利用方法和防御措施,也欢迎和我一样刚入门网安的小伙伴一起交流,查漏补缺,共同进步!
(本文为网安基础学习笔记,若有错误,欢迎各位大佬指正~)