2022/09/07

テクノロジー

SECCON Beginners CTF 2022のWriteup (前編)

この記事の目次

    2022年6月4日〜5日に開催されたSECCON Beginners CTF 2022にチームマイナビで参加しました。
    本記事はそのWriteupとなります。

    概要

    CTF(Capture the Flag)とは、情報セキュリティの知識を使うセキュリティコンテストの一つです。

    いくつかのジャンルに分かれており、例えば

    • リバースエンジニアリングによって実行ファイルの脆弱性をつく
    • Webアプリの脆弱性をつく
    • ファイル内に隠された情報を抜き取る

    などの、そういった攻撃をして隠された『Flag』を手に入れることを目的としています。

    今回、国内のCTFの中で最大となるSECCONが開催しているビギナー向けのコンテストに参加しました。

    ※ちなみに昨年も参加しています。

    結果

    結果は891チーム中63位でした!

    • 結果
    • 解いた問題のカテゴリ割合

    メンバー

    メンバー紹介(筆者の偏見が混じっています)
    S.H.さんチームmnsecのポイントゲッター
    S.R.さんおいおい知らねえぜ、俺が全完しててもよォ
    S.T.さん期待のにゅーふぇいす
    M.W.(私)特に言うことなし

    流れ

    Writeup

    web

    textex

    課題ページ( https://textex.quals.beginners.seccon.jp/ )に移動し、適当にTeX文書を入力すると、コンパイルされてPDFが返ってくるというアプリケーションが実装されている。

    サーバのソースコードを見てみると、flag というファイルがあるので、その中をTeX経由で覗くと正解が得られると考えられる。
    ファイルの中身をそのまま展開することのできる\verbatiminputコマンドでやろうとする。

    \documentclass{article}
    \usepackage{verbatim}
    \begin{document}
    
    \verbatiminput{../../flag}
    
    \end{document}

    しかし、TeXのソースコードに flagという文字列が含まれているとエラーになるように app.pyが実装されている。

    # No flag !!!!
    if "flag" in tex_code.lower():
        tex_code = ""

    そこで、 flagというファイル名を、マクロで分解して、TeXで展開した時に flagに見えるようにするとフラグの中身を覗くことができる。

    \documentclass{article}
    \usepackage{verbatim}
    \newcommand{\fl}{fl}
    \newcommand{\ag}{ag}
    \begin{document}
    
    \verbatiminput{../../\fl\ag}
    
    \end{document}

    gallery

    絵文字のギャラリーサービスからフラグを取得する問題です。

    https://gallery.quals.beginners.seccon.jp/?file_extension=flaにアクセスすると、flag_7a96139e-71a2-4381-bf31-adf37df94c04.pdfというファイルが存在していることが分かります。

    こちらはブラウザからそのままダウンロードはできません。
    サーバーサイドアプリケーションで10,240バイト以上のレスポンスは、そのまま返さないように制限がかけれているからです。

    Rangeヘッダを利用して、10,000バイトづつに分割してダウンロードし、それらを結合できればよさそうです。
    参考: https://developer.mozilla.org/ja/docs/Web/HTTP/Headers/Range

    $ curl 'https://gallery.quals.beginners.seccon.jp/images/flag_7a96139e-71a2-4381-bf31-adf37df94c04.pdf' -H 'Range: bytes=0-9999' --output 0.bin
    $ curl 'https://gallery.quals.beginners.seccon.jp/images/flag_7a96139e-71a2-4381-bf31-adf37df94c04.pdf' -H 'Range: bytes=10000-19999' --output 1.bin
    $ cat 0.bin 1.bin > test.pdf

    無事、フラグを取得できました。

    Ironhand

    お題としてWebサイトが与えられます。ユーザー名を指定してログインすると、user(一般ユーザー)としてログインします。テキストを読むに、adminとしてログインするとflagをもらえそうです。

    Cookieを確認すると、JWT(JSON Web Token)が与えられていました。デコードすると、IsAdminというパラメータを持っていることが分かります。現在falseになっていますが、これをtrueにすれば万事解決……しません。なぜなら、JWTはヘッダー部、ペイロード部、およびヘッダー部とペイロード部を結合した文字列のデジタル署名からなり、IsAdminだけを変更すると、署名検証が失敗するからです。署名は改ざん検知に有用だということがよく分かります。

    adminになるためには適切な署名を生成する必要があり、そのためには署名に使われたシークレットを入手しなければなりません。提供されているアプリのコードを読むと、署名に使われたシークレットであるJWT_SECRET_KEYは、アプリケーションの環境変数として宣言されていることが分かります。

    コードを追っていくと、/static/:pathにきな臭さを感じます。具体的には、静的ファイルの配信ならNginxでやればいいのに、わざわざアプリケーションでやっているあたりが臭いです。

    更に、Nginxの設定ファイルにもmerge_slashes offという馴染みのないオプションがあります。URLにスラッシュをたくさん投げてくれと言わんばかりです。

    検証の結果、案の定/static/:pathにパストラバーサル脆弱性があることが分かりました。画像は脆弱性を利用して、本来表示できないはずの/etc/passwdを表示しているところです。

    パストラバーサルを使ってどうやって環境変数を窃視するかというと、/proc/self/environを呼び出すことで、アプリケーションの環境変数を含むファイルを取得できます。

    JWT_SECRET_KEYが含まれていることが分かります。

    あとは、IsAdmintrueを変更して、JWT_SECRET_KEYを使った正しい署名を含むJWTを作ったら、ブラウザのCookieを書き換えて更新してやればflagです。

    なお、この問題には刺さりませんが、alg: noneにして署名検証そのものをバイパスするという手法・脆弱性もあるみたいです。その発想はなかった。いずれにせよ、パストラバーサル怖~~というのが教訓です。

    後編へ続く・・

    • 2022/09/09

      SECCON Beginners CTF 2022のWriteup (後編)

      CTF(Capture the Flag)とは、情報セキュリティの知識を使うセキュリティコンテストの一つです。今回、国内のCTFの中で最大となるSECCONが開催しているビギナー向けのコンテストに参加しました。

      テクノロジー

    ※サムネ画像ロゴは『SECCON Beginners CTF』より引用

    ※本記事は2022年09月時点の情報です。

    著者:マイナビエンジニアブログ編集部