学习PHP反序列化魔术方法构造和析构
FLYFISH什么是魔术方法
一个预定义好的,在特定情况下自动触发的行为方法
魔术方法的作用
反序列化漏洞的成因:反序列化过程中,unserialize()接收的值(字符串)可控;通过修改这个值(字符串),得到所需要的代码;通过调用方法,触发代码执行。
魔术方法在特定条件下自动调用相关方法,最终导致触发代码
相关机制
- 触发时机(动作不同,触发的魔术方法也不同)
- 功能
- 参数(一些特殊魔术方法会传参)
- 返回值
魔术方法

__construct()
触发时机:
构造函数,在实例化一个对象的时候,首先会去自动执行的一个方法;
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?php highlight_file(__FILE__); class User { public $username; public function __construct($username) { $this->username = $username; echo "触发了构造函数1次" ; } } $test = new User("benben"); $ser = serialize($test); unserialize($ser);
?>
|
__destruct()
触发时机
析构函数,在对象的所有引用被删除或者当对象被显式销毁时执行的魔术方法
1 2 3 4 5 6 7 8 9 10 11 12 13
| <?php highlight_file(__FILE__); class User { public function __destruct() { echo "触发了析构函数1次"."<br />" ; } } $test = new User("benben"); $ser = serialize($test); unserialize($ser);
?>
|
?benben=O:4:"User":1:{s:3:"cmd";s:13:"system("id");";}
__sleep()
触发时机
序列化serialize()函数会检查类中是否存在魔术方法__sleep()
如果存在,该方法会先被调用,然后猜执行序列化操作
此功能可以用于清理对象, 并返回一个包含对象中所有应被序列化的变量名称的数组。
如果该方法未返回任何内容,则NULL被序列化,并产生一个E_NOTICE级别的错误
功能
对象被序列化被触发,返回需要被序列化存储的成员属性,删除不必要的属性
参数
成员属性
返回值
需要被序列化存储的成员属性
例题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| <?php highlight_file(__FILE__); class User { const SITE = 'uusama'; public $username; public $nickname; private $password; public function __construct($username, $nickname, $password) { $this->username = $username; $this->nickname = $nickname; $this->password = $password; } public function __sleep() { return array('username', 'nickname'); } } $user = new User('a', 'b', 'c'); echo serialize($user); ?>
O:4:"User":2:{s:8:"username";s:1:"a";s:8:"nickname";s:1:"b";}
|