更多渗透技能 欢迎搜索公众号:白帽子左一
一、Python反序列化
与PHP存在反序列化一样
Python也存在反序列化漏洞、并且Python反序列化更加强大
除了能反序列化当前代码中出现的类(包括import引入的模块中的类)
还能反序列化types创建的匿名对象!
二、Python反序列化高危模块
marshal
PyYAML
pickle和cpickle
shelve
unzip
对高危模块的分析
1.marshal
特点
1.不是一个通用的“持久性”模块;
2.主要用于读取和编写.pyc文件的Python模块的“伪编译”代码。
3.并不是所有的Python对象类型都被支持;通常,只有值与特定的Python调用的对象无关才能被这个模块编写和读取。支持以下类型:布尔值、整数、浮点数、复数、字符串、字节、字节数组、元组、列表、集合、frozenset(不可变集合)、字典和代码对象。单独的None、Ellipsis和StopIteration也可以编组和解组。对于低于版本3的格式,递归列表、集合和字典不能编写
使用
marshal.dump(value, file[, version])
将值写入到一个打开的输出流里。参数value表示待序列化的值。file表示打开的输出流。
如:以”wb”模式打开的文件,sys.stdout或者os.popen。
对于一些不支持序列类的类型,dump方法将抛出ValueError异常。
但也会将垃圾数据写入文件。
该对象将不能通过load()来正确读取。
marshal.load(file)
从打开的文件中读取值并返回它。
如果没有读取有效的值(例如,因为数据具有不同的Python版本的不兼容的编组格式),会引发EOFError、ValueError或TypeError错误。
文件必须是可读的二进制文件。
注意,如果一个包含不支持类型的对象被编组了dump(), load()将会用None代替unmarshallable类型。
marshal.dumps(value[, version])
返回将被转储(值、文件)写入文件的字节对象。
该值必须是受支持的类型。
如果值有(或包含有)不支持类型的对象,则抛出ValueError异常。
marshal.loads(bytes)
将bytes样对象转换为值。
如果没有找到有效值,会引发EOFError、ValueError或TypeError错误。
输入中的额外字节被忽略。
2.PyYAML
特点
1.YAML是专门用来写配置文件的语言
2.大小写敏感
3.使用缩进表示层级关系
4.缩进时不允许使用Tab键,只允许使用空格。
5.缩进的空格数目不重要,只要相同层级的元素左侧对齐即可
6.# 表示注释,从这个字符一直到行尾,都会被解析器忽略,这个和python的注释一样
7.列表里的项用"-“来代表,字典里的键值对用”:"分隔
8.支持的数据结构
1、对象:键值对的集合
2、数组:一组按次序排列的值,序列(sequence)或列表(list)
3、纯量(scalars):单个的、不可再分的值,如:字符串、布尔值、整数、浮点数、Null、时间、日期
使用
yaml.load("""
… - Hesperiidae
… - Papilionidae
… - Apatelodidae
… - Epiplemidae
… “”")
[‘Hesperiidae’,‘Papilionidae’,‘Apatelodidae’,‘Epiplemidae’]
yaml.load
函数的作用是用来将YAML文档转化成Python对象;
yaml.load
函数可以接受一个表示YAML文档的字节字符串、Unicode字符串、打开的二进制文件对象或者打开的文本文件对象作为参数。
若参数为字节字符串或文件,那么它们必须使用 utf-8 、utf-16 或者 utf-16-le 编码。
yaml.load会检查字节字符串或者文件对象的BOM(byte order mark)并依此来确定它们的编码格式。
如果没有发现 BOM ,那么会假定他们使用 utf-8 格式的编码。
注意:如果要load Python的实例,需要在字符串前加入标签!!python/object
>>>classPerson:
...def __init__(self, name, age, gender):
... self.name = name
... self.age = age
... self.gender = gender
...def __repr__(self):
...return f"{self.__class__.__name__}(name={self.name!r}, age={self.age!r}, gender={self.gender!r})"
...
>>> yaml.load("""
... !!python/object:__main__.Person
... name: Bob
... age: 18
... gender: Male
... """)
Person(name='Bob', age=18, gender='Male')
如果字符串或者文件中包含多个YAML文档,
那么可以使用 yaml.load_all
函数将它们全部反序列化,
得到的是一个包含所有反序列化后的YAML文档的生成器对象:
>>> documents ="""
... name: bob
... age: 18
... ---
... name: alex
... age: 20
... ---
... name: jason
... age: 16
... """
>>> datas = yaml.load_all(documents)
>>> datas
<generator object load_all at 0x105682228>
>>>for data in datas:
...print(data)
...
{
'name':'bob','age':18}
{