はまやんはまやんはまやん

hamayanhamayan's blog

Empire2 [picoCTF 2019 Web 400]

https://ctftime.org/task/9498

前提知識

  • Flask (SSTIの代表格?)
  • SSTI: Server-Side Template Injection
  • base64, url-encoding

解説

先程の脆弱性は修正されているようだ。
問題文にXX is passing secrets around when you log inと挑戦的なことが書いてあり、
ログイン時に置かれるといえばクッキー内のセッション情報である。
ここをどう読むか。

セッションを見てみると、Flaskで使われる形式であると分かる。
Flaskのセッションは「セッションデータ.タイムスタンプ.暗号化ハッシュ」という構成となっている。
セッションデータはBase64エンコードしてあるので、見ることはできるとのこと。
だが、先頭にドットはあるし、途中に-とか_とかがあって、どう見ても違う感じがするが特殊なBase64らしい。
インターネットを目を皿にして探すと、この記事にたどり着く(と思ったらここに全て書いてあった)。
復元scriptまで公開されているので確認すると、以下の手順で復元すればいいことが分かる。
どうやら、先頭にドットがあると、gzipで圧縮されている形式となるとのこと。

  1. 先頭の.と2番目の.の間の文字をとってくる
  2. Base64のURLsafeでエンコードされているので、デコードする(ここではURLアプリケーションのための変形 Base64として紹介されてる)
  3. zlib.decompressで復元する

これで目的のフラグが得られる。

他の人の解説に、Flaskで作られているという所から、サーバサイドテンプレートインジェクションを狙ってセッションの秘密鍵を奪取する方法が紹介されている。
お手軽に{{ config.items() }}とTODOに入れれば秘密鍵が出てくる。
秘密鍵picoCTF{your_flag_is_in_another_castle12345678}という意味深な感じなので、こちらが想定解なのだろう。