PHP序列化反序列化serialize和unserialize函数

本文详细介绍了PHP中序列化函数serialize()和反序列化函数unserialize()的基本原理及应用实例,通过代码示例展示了如何将对象序列化并存储,以及如何在不同的PHP程序间传递序列化后的对象。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

昨天网上看到一道面试题,如下:

类的属性可以序列化后保存到session中,从而以后可以恢复整个类,这要用到的函数是?”

我记得原来老师说过序列化函数是"serialize",查了下,果不其然,今天记录下,免得忘记。

<?php
    class aa{
        public $a = 1;
        private $b = 2;
        protected $c = 3;

        function afun(){
            return $this->a;
        }
        function bfun(){
            return $this->b;
        }
        function __destruct(){
            echo "变量销毁了";
        }
    }

    $v = new aa;
    echo $v->afun();
    $se = serialize($v);
    unset($v); //这里先销毁$v,这个时候会自动调用析构函数
    echo "<hr />";
    $v = unserialize($se); //再反序列化
    echo $v->bfun();

看看运行结果



如果觉得还不明显, 好,我们在改一下代码

aa.class.php

<?php
    class aa{
        public $a = 1;
        private $b = 2;
        protected $c = 3;

        function afun(){
            return '$a的值是:'.$this->a;
        }
        function bfun(){
            return '$b的值是:'.$this->b;
        }
    }

a1.php

<?php
    require './demo8.php';
    Session_start();
    $v = new aa();
    $_SESSION['v'] = serialize($v);

a2.php

<?php
    require './demo8.php';
    Session_start();
    $v = unserialize($_SESSION['v']);
    echo $v->bfun();

再看看结果是不是一目了然了呢,好了,试验做完了,结论调用下公论。

例子中的对象我们还可以换为数组等其他类型,效果都是一样的!
其实serialize()就是将PHP中的变量如对象(object),数组(array)等等的值序列化为字符串后存储起来.序列化的字符串我们可以存储在其他地方如数据库、Session、Cookie等,序列化的操作并不会丢失这些值的类型和结构。这样这些变量的数据就可以在PHP页面、甚至是不同PHP程序间传递了。
而unserialize()就是把序列化的字符串转换回PHP的值。

这里再引用一段PHP手册上的说明,看了上面的例子,应该很容易明白下面这些话的意思了
想要将已序列化的字符串变回 PHP 的值,可使用 unserialize()。serialize() 可处理除了 resource 之外的任何类型。甚至可以 serialize() 那些包含了指向其自身引用的数组。你正 serialize() 的数组/对象中的引用也将被存储。

当序列化对象时,PHP 将试图在序列动作之前调用该对象的成员函数 __sleep()。这样就允许对象在被序列化之前做任何清除操作。类似的,当使用 unserialize() 恢复对象时, 将调用 __wakeup() 成员函数
unserialize() 对单一的已序列化的变量进行操作,将其转换回 PHP 的值。返回的是转换之后的值,可为 integer、float、string、array 或 object。如果传递的字符串不可解序列化,则返回 FALSE。


### PHP反序列化的基本使用方法 PHP中的序列化(`serialize()`)反序列化(`d`eserialize())是用于将对象、数组等复杂数据结构转换为字符串以便存储或传输的机制。例如,一个对象可以通过 `serialize()` 转换为字符串形式,便于保存到数据库或会话文件中;当需要恢复该对象时,可以使用 `unserialize()` 将其还原为原始对象状态。 ```php class Example { public $data = "test"; } // 序列化对象 $obj = new Example(); $serialized = serialize($obj); // 输出: O:7:"Example":1:{s:4:"data";s:4:"test";} echo $serialized . "\n"; // 反序列化对象 $unserialized = unserialize($serialized); echo $unserialized->data; // 输出: test ``` ### PHP反序列化的原理 PHP在执行反序列化操作时,会根据字符串格式重建原始变量结构。序列化字符串中包含了类名、属性名及其值等信息。如果反序列化的数据被攻击者篡改,则可能触发某些危险的“魔术方法”(如 `__construct()`、`__destruct()`、`__wakeup()` 等),从而导致代码执行或其他恶意行为[^2]。 反序列化漏洞的核心在于:开发者没有对用户输入的数据进行严格的过滤验证,而直接将其作为参数传递给 `unserialize()` 函数。攻击者通过构造恶意输入,可以在反序列化过程中触发特定类的方法调用,进而实现任意代码执行或敏感信息泄露的目的[^3]。 ### PHP反序列化漏洞的常见利用方式 - **魔术方法触发**:攻击者通过构造特定的序列化字符串,使得在反序列化过程中自动调用某些魔术方法(如 `__wakeup()` 或 `__destruct()`)。这些方法内部若存在可被利用的功能(如文件操作、命令执行等),则可能导致严重后果[^1]。 - **POP链(Property Oriented Programming)**:这是一种高级利用技术,攻击者通过查找多个类之间的属性引用关系,构建出一条从入口点到目标函数的调用链路。即使没有直接暴露危险方法,也能通过间接方式达成攻击目的。 ### PHP反序列化漏洞的危害 PHP反序列化漏洞可能导致多种安全问题: - **远程代码执行(RCE)**:攻击者可通过构造恶意输入,在服务器上执行任意命令,获取系统控制权。 - **会话劫持**:由于PHP的session机制依赖于序列化/反序列化操作,因此攻击者可能伪造会话内容,冒充合法用户访问系统。 - **数据篡改与泄露**:攻击者可以修改反序列化后的对象属性,篡改业务逻辑,甚至读取数据库中的敏感信息。 ### 如何防止PHP反序列化漏洞 1. **避免反序列化不可信数据**:最根本的防护措施是不要对来自用户的输入执行 `unserialize()` 操作,除非绝对必要且已充分验证其安全性。 2. **使用 `json_encode()` `json_decode()` 替代**:相较于 `serialize()` / `unserialize()`,JSON编码/解码更安全,因为它不涉及类实例化过程。 3. **白名单校验**:如果确实需要处理用户提供的序列化数据,应限制允许反序列化的类名,并确保只接受预期类型的对象。 4. **启用 `__wakeup()` 验证机制**:在关键类中定义 `__wakeup()` 方法,检查反序列化后的对象状态是否合法。 5. **更新框架与依赖库**:及时修补第三方组件中存在的已知反序列化漏洞,防止被攻击者利用。 ### 示例:简单的PHP反序列化漏洞演示 ```php class VulnerableClass { public $cmd = "echo 'Hello, World!';"; function __wakeup() { eval($this->cmd); // 危险操作:执行任意代码 } } // 攻击者构造恶意序列化字符串 $input = 'O:14:"VulnerableClass":1:{s:3:"cmd";s:13:"system("id");";}'; unserialize($input); // 触发 __wakeup(),执行 system("id") ``` 上述代码展示了攻击者如何通过精心构造的序列化字符串,使原本仅用于输出“Hello, World!”的对象执行了 `system("id")` 命令,从而实现了远程命令执行攻击[^1]。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值