🛡️

setodaNote CTF Exhibition Writeup (Web)

2024/10/15に公開

Web - Body

作成中のサイトに機密情報が含まれてしまっているようです。サイトにアクセスして機密情報を見つけ出してください。

以下のサイトにアクセスして隠されたフラグを見つけてください。

https://ctfweb.setodanote.net/web001/

問題文末のWebサイトにアクセスし、ページのソースを表示します(長いため一部省略しています)。

~省略~

<!-- Three -->
    <section id="three" class="main style1 special">
        <div class="container">
            <header class="major">
                <h2>運命とは、選び出す物だ、受け容れる前に</h2>
            </header>
            <p>運命とは、受け入れるべきものではない、それは自ら選び創り出すものだ</p>
            <div class="row gtr-150">
                <div class="col-4 col-12-medium">
                    <span class="image fit"><img src="images/pic02.jpg" alt="" /></span>
                    <h3>フラグ形式</h3>
                    <p>特に指定がない限りフラグは flag{<!-- *** flag{Section_9} *** -->} という形式をとります。</p>
                    <ul class="actions special">
                        <li><a href="#four" class="button scrolly">More</a></li>
                    </ul>
                </div>
                <div class="col-4 col-12-medium">
                    <span class="image fit"><img src="images/pic03.jpg" alt="" /></span>
                    <h3>誤ったフラグ</h3>
                    <p>誤ったフラグを入力することによる減点はありません。</p>
                    <ul class="actions special">
                        <li><a href="#four" class="button scrolly">More</a></li>
                    </ul>
                </div>
                <div class="col-4 col-12-medium">
                    <span class="image fit"><img src="images/pic04.jpg" alt="" /></span>
                    <h3>より早くより多く</h3>
                    <p>より早くより多くのポイントを獲得したユーザがより上位となります。</p>
                    <ul class="actions special">
                        <li><a href="#four" class="button scrolly">More</a></li>
                    </ul>
                </div>
            </div>
        </div>
    </section>

~省略~

問題タイトルにもある通り、HTMLのボディ部にコメントとして<!-- *** flag{Section_9} *** -->という記載があり、これがflagになります。

正答:flag{Section_9}

Web - Header

作成中のサイトを管理しているサーバに問題があり、機密情報が漏洩しているようです。サイトにアクセスして機密情報を特定してください。

以下のサイトにアクセスして隠されたフラグを見つけてください。

https://ctfweb.setodanote.net/web002/

問題文末のWebサイトにアクセスし、ページのソースを表示します(長いため一部省略しています)。

~省略~

<head>
    <title>Web - setodaNote CTF</title>
    <meta charset="utf-8" />
    <meta name="robots" content="noindex">
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
    <meta name="hint" content="頭と言ってもここのことではないのです。 Nice try!" />
    <link rel="stylesheet" href="assets/css/main.css" />
    <noscript><link rel="stylesheet" href="assets/css/noscript.css" /></noscript>
</head>

~省略~

問題タイトルからHTMLのヘッダ部を見ればflagを取得できると思っていましたが、どうやら違うようです。
次に、ヘッダはヘッダでもレスポンスヘッダを確認してみます。

X-Setodanotectf-Flagヘッダの値としてflagが記載されています。
正答:flag{Just_a_whisper}

Web - puni_puni

近所の子供から「ぷにぷにこーどあげるね」と1枚の紙を手渡されました。見ると子供の字とは思えない正確な書体で英数字がびっしりと書き込まれています。これはいったい。そう聞こうとしましたが、紙に意識を取られた一瞬のうちにその子供はいなくなっていました。

紙に書かれた文字列を解析し、フラグを入手してください。フラグは得られた文字列を flag{} で囲んで答えてください。例えば flag が得られた場合は flag{flag} と入力します。

xn--q6jaaaaaa08db0x8nc9t1b8fsviei84atb4i0lc
xn--q6jaaaaa03dpd4mb3jc5rpa0g9jpk07acadc.
xn--q6jylla3va3j6c8138a8eptvb303cxv4ft3o4ue63a
xn--v8ja6aj2a3cri3ag4a2r6cx2a1rkk1272c7j4ajd4bmf0kjhg6rb.
xn--q6j6gav1a0b2e1bh1ac2cl29ad7728kdjen6cz80dju6bqexchl9gel8b.

問題からPunycode[1]であると分かります。
JPRSのWebサイトで変換すると以下のようになります。

https://punycode.jp/

  • xn--q6jaaaaaa08db0x8nc9t1b8fsviei84atb4i0lc:フラグは、さん、さん、ピー、ユー、エヌ、ワイ、
  • xn--q6jaaaaa03dpd4mb3jc5rpa0g9jpk07acadc.:シー、オー、ディー、イー、よん、よん、です.
  • xn--q6jylla3va3j6c8138a8eptvb303cxv4ft3o4ue63a:カタカナ表記は半角英小文字に、
  • xn--v8ja6aj2a3cri3ag4a2r6cx2a1rkk1272c7j4ajd4bmf0kjhg6rb.:ひらがな表記は半角数字にしたものがフラグです.
  • xn--q6j6gav1a0b2e1bh1ac2cl29ad7728kdjen6cz80dju6bqexchl9gel8b.:なお、読点は区切り文字なので取り除いてください.

正答:flag{33punycode44}

Web - Mistake

作成中のサイトに不備があると外部から指摘を受けています。どうやら機密情報が漏れてしまっているようです。サイトにアクセスして機密情報を特定してください。

以下のサイトにアクセスして隠されたフラグを見つけてください。

http://ctfweb.setodanote.net/web003/

問題文末のWebサイトにアクセスし、ページのソースを表示します(長いため一部省略しています)。

~省略~

<!-- Three -->
    <section id="three" class="main style1 special">
        <div class="container">
            <header class="major">
                <h2>運命とは、選び出す物だ、受け容れる前に</h2>
            </header>
            <p>運命とは、受け入れるべきものではない、それは自ら選び創り出すものだ</p>
            <div class="row gtr-150">
                <div class="col-4 col-12-medium">
                    <span class="image fit"><img src="images/pic02.jpg" alt="" /></span>
                    <h3>フラグ形式</h3>
                    <p>特に指定がない限りフラグは flag{<!-- Webserver directory index? -->} という形式をとります。</p>
                    <ul class="actions special">
                        <li><a href="#four" class="button scrolly">More</a></li>
                    </ul>
                </div>
                <div class="col-4 col-12-medium">
                    <span class="image fit"><img src="images/pic03.jpg" alt="" /></span>
                    <h3>誤ったフラグ</h3>
                    <p>誤ったフラグを入力することによる減点はありません。</p>
                    <ul class="actions special">
                        <li><a href="#four" class="button scrolly">More</a></li>
                    </ul>
                </div>
                <div class="col-4 col-12-medium">
                    <span class="image fit"><img src="images/pic04.jpg" alt="" /></span>
                    <h3>より早くより多く</h3>
                    <p>より早くより多くのポイントを獲得したユーザがより上位となります。</p>
                    <ul class="actions special">
                        <li><a href="#four" class="button scrolly">More</a></li>
                    </ul>
                </div>
            </div>
        </div>
    </section>

~省略~

<!-- Webserver directory index? -->というコメントが残されているため、ディレクトリインデックスリスティングが有効化されていると予想できます。
ここで、もう一度ソースを確認してみます(長いため一部省略しています)。

~省略~

<head>
    <title>Web - setodaNote CTF</title>
    <meta charset="utf-8" />
    <meta name="robots" content="noindex">
    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
    <link rel="stylesheet" href="assets/css/main.css" />
    <noscript><link rel="stylesheet" href="assets/css/noscript.css" /></noscript>
</head>
<body class="is-preload">

~省略~

    <!-- One -->
        <section id="one" class="main style1">
            <div class="container">
                <div class="row gtr-150">
                    <div class="col-6 col-12-medium">
                        <header class="major">
                            <h2>すべての実態は必然的に無限である</h2>
                        </header>
                        <p>setodaNote CTF はサイバーセキュリティに関する設問を解くことで得られるポイントを競う競技です。設問は9つあるカテゴリの中からそのテーマや解法などにより最も関連するカテゴリに割り振られています。</p>
                    </div>
                    <div class="col-6 col-12-medium imp-medium">
                        <span class="image fit"><img src="images/pic01.jpg" alt="" /></span>
                    </div>
                </div>
            </div>
        </section>

~省略~

すると、assets/css/noscript.cssimages/pic01.jpgという記載からassetsimagesというディレクトリが存在すると分かります。
まず、assetsディレクトリにアクセスしてみます。

ディレクトリインデックスリスティングが有効化されています。
しかし、assetsディレクトリ内のファイルにはflagが記載されていませんでした。
次に、imagesディレクトリにアクセスしてみます。

pic_flag_is_here.txtにflagが記載されています。

正答:flag{You_are_the_Laughing_Man,_aren't_you?}

Web - tkys_royale

んー、このサイトには重大な脆弱性があります。そう切り出してきた相手の姿にあなたは言葉が出ません。それは音信不通となっていた後輩の生き写し。聞きたいことが山ほどありますが、まずはサイトの脆弱性を修正しなければなりません。サイトを解析し、脆弱性を特定してください。

以下のサイトにアクセスしてフラグを得てください。

https://ctfweb.setodanote.net/web005/

問題文末のWebサイトにアクセスすると、ログインフォームが表示されます。
SQLインジェクションの脆弱性があると予想し、usernameに' OR 1=1 --、passwordに適当な文字列を入れてみます。
すると、ご丁寧にエラー文を表示してくれます。

エラー文によるとMySQLを使っているそうなので、コメントアウトは--ではなく#です。
usernameに' OR 1=1 #、passwordに適当な文字列を入れてみます。

正答:flag{SQLi_with_b1rds_in_a_b34utiful_landscape}

Web - Estimated

組織の関連サイトを監視している部署から「どうやら局長ブログで機密情報が漏洩しているようだ」と連絡が入りました。一部SNSで言及されているものの、幸いにしてまだ広まってはいないようです。なんとか穏便にすませたい上司に配慮し、被害を最小にすべくサイトを調査し漏洩している機密情報を特定してください。

以下のサイトにアクセスしてフラグを得てください。

https://ctfweb.setodanote.net/web006/

問題文末のWebサイトにアクセスすると、ブログが表示されます。
2021/06/03の記事を読んでみると、どうやら前日の2021/06/02の記事に公開してはいけない画像を掲載していたようです。

記事を削除しただけで画像を削除し忘れていると予想し、画像のパスを推測します。
例えば、2021/08/01の記事に掲載している画像のパスはhttps://ctfweb.setodanote.net/web006/images/20210801001b.jpgです。
そのため、公開してはいけない画像のパスはhttps://ctfweb.setodanote.net/web006/images/20210602001b.jpgだろうと推測し、アクセスしてみます。

画像内のPC画面にflagが映っています。

正答:flag{The_flag_wouldn't_like_to_end_up_in_other_peoples_photos}

Web - Mx.Flag

旗から手紙が届きました。

親愛なる貴方へ

こうして貴方に手紙を送るのは初めてですね。
実はとてもうまく隠れることができたので、嬉しくなりこのような手紙を送ることにしました。

どうか私を見つけてくれますか?

以下のサイトにアクセスしてフラグを得てください。

https://ctfweb.setodanote.net/web007/

問題文末のWebサイトにアクセスし、ページのソースを表示します。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>Letter of challenge from Flag</title>
    <meta name="robots" content="noindex">
    <meta name="description" content="Letter of challenge from Flag. Can you find me?">
    <link rel="icon" type="image/png" href="images/favicon.png">
    <link rel="stylesheet" href="assets/css/style.css">
</head>
<body>
    <header>
        <h1>Challenge</h1>
    </header>
    <hr>
    <main>
        <p>Dear you,</p>
        <p>This is the first time I've sent you a letter like this.<br />
        I was able to hide so well that I was so happy that I decided to send this letter to you.</p>
        <p>Can you find me?</p>
        <p>Flag.</p>
    </main>
    <hr>
    <footer>
        <p>setodaNote CTF.</p>
    </footer>
</body>
</html>

今までのWebサイトと異なりFaviconを設定しているようです。
https://ctfweb.setodanote.net/web007/images/favicon.pngにアクセスしてFaviconを保存します。
保存したfavicon.pngを普通に開こうとしても上手く開けないので、メモ帳で開いてみるとflagが記載されています。
正答:flag{Mr_Flag_hiding_in_the_favicon}

Web - Redirect

組織の関連サイトを監視している部署から「どうやら会長ブログが何らか侵害を受けてしまっているようだ」と連絡が入りました。再現方法が不明なものの、一部の訪問者から不審なサイトに飛ばされてしまうという指摘がされているようです。上司は休暇で不在ですが特に支障はありません。被害を最小にすべくサイトを調査し侵害状況を把握してください。

以下のサイトにアクセスしてフラグを見つけ出してください。

https://ctfweb.setodanote.net/web004/

問題文末のWebサイトにアクセスしてページのソースを見てみると、最終行付近に以下のスクリプトが記載されています。

!function(){
    var ref = document.referrer;
    var domain = ref.match(/^http([s]?):\/\/([a-zA-Z0-9-_\.]+)(:[0-9]+)?/)[2];
    if(domain == "www.google.com" || domain == "www.google.co.jp" ){
        location.href = atob('Li9iV0ZzYTJsMC5odG1s');
    }
}();

これはwww.google.comまたはwww.googole.co.jpから本Webサイトにアクセスした場合、https://ctfweb.setodanote.net/web004/bWFsa2l0.htmlにリダイレクトするスクリプトです。

試しにhttps://ctfweb.setodanote.net/web004/bWFsa2l0.htmlにアクセスしてみると、https://ctfweb.setodanote.net/web004/ZGFtbXlmbGFn/?callback=wantFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200にリダイレクトされます。

このWebページにはflagがなさそうなので、curlコマンドでリダイレクトの過程を追ってみます。
まず、https://ctfweb.setodanote.net/web004/bWFsa2l0.htmlにアクセスします。

$ curl https://ctfweb.setodanote.net/web004/bWFsa2l0.html
<!DOCTYPE HTML>
<html>
  <head>
    <title>start</title>
    <noscript>
      <meta http-equiv=refresh content="1; URL=./noscript.html">
    </noscript>
    <script>
      !function() {
        var params = new URL(window.location.href).searchParams;
        if(Array.from(params).length > 0){
          location.href = './bm9mbGFn/?'+params;
        }else{
          location.href = './bWFsa2l0.html?callback=wantFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200';
        }
      }();
    </script>
  </head>
  <body>
    <p>Find out the flag.</p>
  </body>
</html>
$

これは

  • クエリ文字列がある場合:同一のクエリ文字列を引き継いでhttps://ctfweb.setodanote.net/web004/bm9mbGFn/にリダイレクト
  • クエリ文字列がない場合:https://ctfweb.setodanote.net/web004/bWFsa2l0.html?callback=wantFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200にリダイレクト

という挙動をするスクリプトです。
次に、https://ctfweb.setodanote.net/web004/bm9mbGFn/?callback=wantFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200にアクセスします。

$ curl "https://ctfweb.setodanote.net/web004/bm9mbGFn/?callback=wantFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200"
<html>
  <head>
    <title>Next</title>
    <noscript>
      <meta http-equiv=refresh content="1; URL=../noscript.html">
    </noscript>
    <script>
      !function() {
        var params = new URL(window.location.href).searchParams;
        location.href = '../bmV4dG5leHQ/?'+params
      }();
      </script>
  </head>
  <body>
  <p>No flag here. Go to next.</p>
  </body>
</html>
$

これは同一のクエリ文字列を引き継いでhttps://ctfweb.setodanote.net/web004/bmV4dG5leHQ/にリダイレクトするスクリプトです。
そのため、次はhttps://ctfweb.setodanote.net/web004/bmV4dG5leHQ/?callback=wantFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200にアクセスします。

$ curl "https://ctfweb.setodanote.net/web004/bmV4dG5leHQ/?callback=wantFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200"
<html>
  <head>
    <title>Next-Next</title>
    <noscript>
      <meta http-equiv=refresh content="1; URL=../noscript.html">
    </noscript>
    <script>
      !function() {
        var params = new URL(window.location.href).searchParams;
        location.href = '../b25lLXR3by10aHJlZQ/?'+params
      }();
      </script>
  </head>
  <body>
  <p>No flag here too. Go to next.</p>
  </body>
</html>
$

これも同一のクエリ文字列を引き継いでhttps://ctfweb.setodanote.net/web004/b25lLXR3by10aHJlZQ/にリダイレクトするスクリプトです。
次はhttps://ctfweb.setodanote.net/web004/b25lLXR3by10aHJlZQ/?callback=wantFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200にアクセスします。

$ curl "https://ctfweb.setodanote.net/web004/b25lLXR3by10aHJlZQ/?callback=wantFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200"
<html>
  <head>
    <title>Branching point</title>
    <noscript>
      <meta http-equiv=refresh content="1; URL=../noscript.html">
    </noscript>
    <script>
      !function() {
        var params = new URL(window.location.href).searchParams;
        if (params.get('callback') == 'getFlag') {
          location.href = '../dGFjaGlrb21hX2thd2FpaV95b25l/?' + params;
        }else{
          location.href = '../ZGFtbXlmbGFn/?' + params;
        }
      }();
      </script>
  </head>
  <body>
  <p>You need the correct parameters to get the flag.</p>
  </body>
</html>
$

これは

  • callbackパラメータの値がgetFlagである場合:同一のクエリ文字列を引き継いでhttps://ctfweb.setodanote.net/web004/dGFjaGlrb21hX2thd2FpaV95b25l/にリダイレクト
  • callbackパラメータの値がgetFlagでない場合:同一のクエリ文字列を引き継いでhttps://ctfweb.setodanote.net/web004/ZGFtbXlmbGFn/にリダイレクト

という挙動をするスクリプトです。
ここでhttps://ctfweb.setodanote.net/web004/ZGFtbXlmbGFn/?callback=wantFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200にアクセスするとブラウザでアクセスした時と同様の流れになってしまうので、callbackパラメータの値をwantFlagからgetFlagに修正して、https://ctfweb.setodanote.net/web004/dGFjaGlrb21hX2thd2FpaV95b25l/?callback=getFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200にアクセスします。

$ curl "https://ctfweb.setodanote.net/web004/dGFjaGlrb21hX2thd2FpaV95b25l/?callback=getFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200"
<html>
  <head>
    <title>GO!GO!GO!</title>
    <noscript>
      <meta http-equiv=refresh content="1; URL=../noscript.html">
    </noscript>
    <script>
      !function() {
        var params = new URL(window.location.href).searchParams;
        var callback = params.get('callback');
        var data1    = params.get('data1');
        var data2    = params.get('data2');
        var data3    = params.get('data3');
        var data4    = params.get('data4');
        if (callback == 'getFlag' && data1 == "2045" && data2 =="0907" && data3 == "BiancoRoja" && data4 =="1704067200") {
          location.href = 'https://noisy-king-d0da.setodanote.net/?'+params;
        }else{
          location.href = '../ZGFtbXlmbGFn/hint.html?'+params;
        }
      }();
      </script>
  </head>
  <body>
  <p>Yes! Go to next.</p>
  </body>
</html>
$

これは

  • callbackパラメータの値がgetFlagかつdata1パラメータの値が2045かつdata2パラメータの値が0907かつdata3パラメータの値がBiancoRojaかつdata4パラメータの値が1704067200である場合:同一のクエリ文字列を引き継いでhttps://noisy-king-d0da.setodanote.net/にリダイレクト
  • パラメータの値が上記以外の場合:同一のクエリ文字列を引き継いでhttps://ctfweb.setodanote.net/web004/ZGFtbXlmbGFn/にリダイレクト

という挙動をするスクリプトです。
したがって、https://noisy-king-d0da.setodanote.net/?callback=getFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200にアクセスします。

$ curl "https://noisy-king-d0da.setodanote.net/?callback=getFlag&data1=2045&data2=0907&data3=BiancoRoja&data4=1704067200"
<!DOCTYPE html>
<body>
  <h1>Nice work!!</h1>
  <p>flag{Analyz1ng_Bad_Red1rects}</p>
</body>                                                                                                                   
$ 

正答:flag{Analyz1ng_Bad_Red1rects}

脚注
  1. Punycodeとは日本語などをドメイン名に変換する形式のことで、変換するとxn--から始まることが特徴です。 ↩︎

Discussion