关于 Flask 会话 Cookie 的事情

Something About Flask Session Cookie

提问人:b3nguang 提问时间:10/22/2023 更新时间:10/22/2023 访问量:71

问:

当我参加 CTF 比赛时,我的烧瓶会话饼干出现了问题。

我尝试通过 noraj/flask-session-cookie-manager 解码 cookie: :cookie: Flask Session Cookie 解码器/编码器 (github.com)。例如

python flask_session_cookie_manager3.py decode -c ".eJwtjkGKAzEMBL-S9TkHy5Yte96wP1jCIEvyJmxIYDxzCvn7-pBTUw1N18ut_c7jasMtPy932me4cYjYGO7svp-_t8fpw_24f7nL-3Kem83G1S37dtikm7rFQUJBRSOL1GKWVCoRC3ED7VAz9FKsVi9aO2RgJmgSi88VuQCmXghjaRZjSCqBDTm3qE1LAh8bGnuG3jAHCV4iZlAoPkhiAGghT9v1GLZ9bCbK2Pq6P__sMQuev2ZcKQFkMinJWhRSqB4hYyWv2oWre_8D5vtQyA.ZTUbZQ.erv_yZmYg44tiaJ0u8fqKailHUc"


b'{"_flashes":[{" t":["success","Login successful!"]}],"_fresh":true,"_id":"154c4d4e7e37b36c58977ac7ab1df1961f88e990cd9f161aa71bc380694a8145f87438be3325dc2ae4a6b3dbd85103b4ea0a1fb462c20c3461d1802c5a111b26","_user_id":"1","csrf_token":"acd9eea9751167ec85eb3c7d1904164970ddfca9"}'

如您所见,我可以在没有密钥的情况下对其进行解码。但是当我尝试伪造cookie时,我发现我必须使用密钥来加密数据,这是为什么?

任何帮助都值得赞赏!

烧瓶 CTF

评论


答:

0赞 ilias-sp 10/22/2023 #1

您描述的是设计上的预期行为 - 可以在没有密钥的情况下解码 cookie,但没有密钥就无法修改。

文档

如果已设置Flask.secret_key(或从 SECRET_KEY 配置),则可以在 Flask 应用程序中使用会话。会话可以记住从一个请求到另一个请求的信息。Flask 执行此操作的方式是使用签名的 cookie。用户可以查看会话内容,但除非他们知道密钥,否则无法修改它,因此请确保将其设置为复杂且不可猜测的内容。

6赞 Andreas Violaris 11/22/2023 #2

正如Elias已经提到的,cookie可以在没有密钥的情况下进行解码,但出于明显的安全原因,没有密钥就无法对其进行操作。如果 cookie 篡改就这么简单,没有人会使用 Flask 会话。因此,您的任务是找到密钥,并且由于 SHA-1 哈希函数是不可逆的,因此您应该将注意力转向人为因素。

话虽如此,你必须使用蛮力“猜测”比赛中粗心程序员的密钥,幸运的是,Flask-Unsign可以帮助你做到这一点。

您可以使用以下命令通过 pip 安装它:

pip3 install flask-unsign

但在使用它之前,您需要一个像 rockyou 这样的单词列表,您可以使用以下命令从 Kali Linux GitLab 存储库下载该列表:

curl -JO https://gitlab.com/kalilinux/packages/wordlists/-/raw/kali/master/rockyou.txt.gz && gunzip rockyou.txt.gz
  • -J, --remote-header-name:在本地保存文件时,使用服务器指定的 Content-Disposition 文件名,而不是从 URL 中提取文件名。
  • -O, --remote-name:使用服务器指定的文件名将输出写入与获取的远程文件类似的本地文件。

现在,您可以使用以下命令执行暴力攻击:

flask-unsign --unsign --cookie '.eJwtjkGKAzEMBL-S9TkHy5Yte96wP1jCIEvyJmxIYDxzCvn7-pBTUw1N18ut_c7jasMtPy932me4cYjYGO7svp-_t8fpw_24f7nL-3Kem83G1S37dtikm7rFQUJBRSOL1GKWVCoRC3ED7VAz9FKsVi9aO2RgJmgSi88VuQCmXghjaRZjSCqBDTm3qE1LAh8bGnuG3jAHCV4iZlAoPkhiAGghT9v1GLZ9bCbK2Pq6P__sMQuev2ZcKQFkMinJWhRSqB4hYyWv2oWre_8D5vtQyA.ZTUbZQ.erv_yZmYg44tiaJ0u8fqKailHUc' --no-literal-eval -w rockyou.txt   
  • 之所以使用 --no-literal-eval 参数,是因为 Flask-Unsign 默认假定给定单词列表中的每个单词都用引号括起来。然而,rockyou的词汇表并非如此。

并在几千次尝试后找到密钥:

[*] Session decodes to: {'_flashes': [('success', 'Login successful!')], '_fresh': True, '_id': '154c4d4e7e37b36c58977ac7ab1df1961f88e990cd9f161aa71bc380694a8145f87438be3325dc2ae4a6b3dbd85103b4ea0a1fb462c20c3461d1802c5a111b26', '_user_id': '1', 'csrf_token': 'acd9eea9751167ec85eb3c7d1904164970ddfca9'}                       
[*] Starting brute-forcer with 8 threads..                                                                                                     
[+] Found secret key after 175360 attempts                                                                                                     
b'Galaxy'

最后,找到密钥后,您可以根据需要使用它使用修改后的会话数据对自己的 cookie 进行签名:

flask-unsign --sign --cookie "modified session data here" --secret 'Galaxy'