PHP反序列化漏洞

一.PHP的序列化和反序列化

(1).作用

PHP的序列化和反序列化是PHP中用于存储或传输PHP的值的一个过程。序列化是将变量转换为可存储或传输的字符串的过程,而反序列化则是将这些字符串转换回PHP变量的过程。这两个过程在PHP开发中非常有用,特别是在需要保存对象状态、进行深拷贝或在网络间传输复杂数据结构时。

(2).序列化实列

当序列化一个对象时,PHP会保存对象的类名、对象的所有属性(包括私有和受保护的属性),以及这些属性的值。但是,不会保存对象的方法(即类的函数)。这是因为PHP的序列化机制主要是用于保存对象的状态,而不是行为。

php 复制代码
class MyObject {  
    public $var1 = 'Hello World!';  
    protected $var2 = 'Protected var';  
    private $var3 = 'Private var';  
  
    function showVars() {  
        echo $this->var1 . "\n";  
        echo $this->var2 . "\n";  
        echo $this->var3 . "\n";  
    }  
}  
  
$obj = new MyObject();  
$serialized = serialize($obj);  
echo $serialized;

输出

php 复制代码
O:8:"MyObject":3:{s:5:"var1";s:12:"Hello World!";s:8:"*var2";s:13:"Protected var";s:10:"MyObjectvar3";s:10:"Private var";}

这里,O表示对象,8是类名的长度,MyObject是类名,3是对象属性的数量。每个属性都表示为s(字符串类型)后跟属性名、长度和值。对于受保护和私有属性,PHP在属性名前添加了前缀(*对于受保护属性,以及类名和var前缀对于私有属性)来确保它们在反序列化时能够正确地映射回原始对象。

(3).反序列化

反序列化是序列化的逆过程,即将序列化的字符串转换回PHP的原始数据结构。PHP提供了unserialize()函数来实现这一功能。

php 复制代码
$serializedData = 'O:8:"MyClass":1:{s:7:"myValue";s:5:"Hello";}';  
$object = unserialize($serializedData);  
  
// 假设 MyClass 有一个公共属性 myValue  
echo $object->myValue; // 输出: Hello

在上面的例子中,$serializedData 是一个序列化的字符串,它表示一个名为 MyClass 的对象,该对象有一个名为 myValue 的公共属性,其值为 "Hello"。通过 unserialize() 函数,我们能够将这个字符串转换回原始的 MyClass 对象。

二.PHP反序列化漏洞

(1).原理

PHP 的 serialize() 函数用于将 PHP 值(包括数组和对象)转换成可存储或传输的字符串。相反,unserialize() 函数则用于将这些字符串转换回原始的 PHP 值。然而,如果 unserialize() 被用于处理恶意构造的序列化字符串,它可能会实例化未预期的类、调用未授权的方法或执行其他危险操作。

攻击者可以通过构造一个特制的序列化字符串,该字符串在反序列化时会触发某些有害的行为,如执行任意代码、修改应用程序的状态或泄露敏感信息。

(2).pikachu靶场练习

我们可以尝试反序列化一个XSS攻击

php 复制代码
O:1:"S":1:{s:4:"test";s:25:"<script>alert(1)</script>";}
php 复制代码
O:1:"S":1:{s:4:"test";s:39:"<script>alert(document.cookie)</script>";}//弹出cookie
(3).防御
  1. 输入验证
    • 对所有输入数据进行严格的验证,确保它们符合预期的格式和类型。在反序列化之前,检查输入数据是否确实是有效的序列化字符串。
    • 使用正则表达式或其他验证方法来检查序列化字符串的格式是否正确,但请注意,这种方法可能无法完全防止所有类型的攻击,因为序列化字符串的格式相对复杂且可以构造出绕过简单验证的恶意数据。
  2. 使用安全的替代方案
    • 如果可能,避免使用unserialize()函数,而是寻找更安全的替代方案来存储和传输数据。例如,可以使用JSON、XML或其他格式来编码数据,并使用相应的解析函数来处理它们。
    • 对于需要存储复杂数据结构的情况,可以考虑使用数据库或其他数据存储系统来管理这些数据,而不是将它们序列化为字符串。
  3. 限制反序列化的使用
    • 仅在绝对必要时才使用unserialize()函数,并尽量减少其使用范围。避免在不受信任的数据上调用unserialize()
    • 如果必须使用unserialize(),请确保在受控的环境中执行它,并限制可以反序列化的类。可以使用allowed_classes选项(在PHP 7.0.0及以上版本中可用)来指定允许反序列化的类。
  4. 更新和修补
    • 定期更新PHP及其相关组件到最新版本,以获取最新的安全补丁和修复。
    • 监控与PHP反序列化漏洞相关的安全公告和漏洞报告,以便在发现新漏洞时及时采取行动。
  5. 使用自定义的反序列化函数
    • 如果需要更细粒度的控制,可以编写自定义的反序列化函数来替代unserialize()。在自定义函数中,可以添加额外的验证和清理步骤来确保数据的安全性。
  6. 日志和监控
    • 对所有反序列化操作进行日志记录,以便在发生异常时能够追踪和调查。
    • 监控应用程序的性能和异常行为,以便及时发现和响应潜在的安全威胁。
  7. 安全编码实践
    • 遵循最佳的安全编码实践,如最小权限原则、错误处理和日志记录等。
    • 对开发人员进行安全培训,提高他们对安全漏洞的认识和防范能力。

请注意,这些防御措施并不是孤立的,而是应该相互结合使用,以形成一个全面的安全防御体系。此外,随着PHP及其相关组件的不断发展,新的安全漏洞和攻击技术可能会出现,因此持续关注和更新安全策略是非常重要的。

相关推荐
JaguarJack1 天前
PHP 的异步编程 该怎么选择
后端·php·服务端
BingoGo1 天前
PHP 的异步编程 该怎么选择
后端·php
JaguarJack2 天前
为什么 PHP 闭包要加 static?
后端·php·服务端
ServBay3 天前
垃圾堆里编码?真的不要怪 PHP 不行
后端·php
用户962377954483 天前
CTF 伪协议
php
BingoGo5 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack5 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
BingoGo6 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack6 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
JaguarJack7 天前
推荐 PHP 属性(Attributes) 简洁读取 API 扩展包
后端·php·服务端