この記事は IPFactory Advent Calendar 2022 の 16 日目の記事です。
MBSD Cybersecurity Challenges 2022
こんにちは。y0d3nです。
去年MBSD Cybersecurity Challenges 2021に参加したfutabatoと、IPFactoryからn01e0とmorioka12を加えてMBSD Cybersecurity Challenges 2022に出場、優勝しました。
MBSD Cybersecurity Challenges 2022優勝しました!!!!
— よーでん (@y0d3n) 2022年12月15日
やった~~~~~~~~!!!!!!!!!! https://t.co/BknKYykJXg
さっそく "専門学校と経営" さんに結果のページが掲載されていました。
いいポーズしてる人がいますね👀
開催概要に関しては公式ページをご参照ください。
去年はかなり悔しい思いをしたので、最後にIPFactoryで出場して4年生を終わらせたいなと思って出場を決めました。
メンバーはこんなかんじ。
4人ともIPFactoryなので、満を持してIPFacotryで出場。
言い訳の出来ないアピール文を設定して覚悟を決めました。*1
↓ エントリチーム一覧
コンテストに参加しながら随時追記していってます。(マジで忙しすぎてまとめて書いた範囲もありますが)
そのため、当時のテンションやメンタルによって文体とかがかなり異なります。
文章を見ながら僕のテンションを推測するなりして遊んでください。
(改めてみるとちょっと恥ずかしいことも書いてますが、せっかくなので当時のありのままを残しています)
このエントリは基本的にポエムで、あんまりためになる話はできません。
開始前
意識のすり合わせ
まずは去年の反省とそれに対する話し合いを少し。
去年参加した際の審査観点に、以下のような一文がありました。
診断ツールの操作が単純なこと。開発エンジニアが操作するのを想定すること。
去年、僕らのチームではかなりルールやシナリオに気を使って開発をして、「開発エンジニアでも使いやすいツール」を作ろうと頑張っていました。
その他にも、あらゆる面でシナリオにしたがって方針を相談して決めて、かなりお行儀よくコンテストに取り組んでいました。が、ただちょっと頑張る方向がずれていた様で、結果は思ったより伸びず。
プロキシツールのようにしたうえで攻撃は自分で操作をするような、「開発エンジニアが使いやすい」とは言い難いようなツールも想像以上にツール自体の点数が高く、ほぼ手動で診断ができるという点で診断の点数で大差をつけられて負けてしまったのがとても悔しかったのを鮮明に覚えています。
去年同じチームで参加していたfutabatoも同じような考えだったので 今年はルールで禁止されてないことは何でもやる という方針で攻める感じになりました。
診断
診断自体はやるだけ。
と思っていたら、フレームワークの問題で結構単純なインジェクション系はほとんどつぶされていました。
ツールを回すだけで見つけれる脆弱性は結構少なかったため、技術力と費やした時間次第だなって感じでした。
CSRFトークンとかもちゃんと生成されていたりして、jsonでやりとりするのでマクロもちょっと厄介。
権限毎に機能もわかれてて、「ぶっちゃけ面倒な部類の診断対象だな・・・」と。
ソースコードぶっこぬき
課題が公開されてから課題が配布されるまでの期間、以前の脆弱性診断の年の資料を探していました。
見つけた中で印象的だったのが2017の年のチーム「セキュアマン’s 2.0.1」さんのレポートです。
「1-1 . 調査手法に関する説明」の工夫から引用します。
・配布されたovaをインポートした際にマウントされる MBSD_Bank_new-disk1.vmdk を
バイナリエディタで開き /etc/shadow の root パスワードを Shutdown ユーザで書き換え
root アカウントでサーバ内の設定を確認できるようにした。
いい話。
僕らも「ソースコード抜きたいね~」と話していましたし、
VMが配られた日にn01e0はWebアプリを起動するよりも先にVM hackに取り掛かり始めました。
結局、ovaのインポート時に生成されたvdiファイルをFTK Imagerに入れることで全部抜くことができました。
これでWebアプリの挙動とソースファイルを同時に見るグレーボックスな診断が可能です。
ただ、上位争いをするチームは間違いなくソースコードを抜いてくると想定できるため安心は厳禁です。
コメントアウト
ソースを抜いたのでコメントも見れるのですが、いくつか面白いコメントがありました。
特に面白かったのが // vulnerable
。
見ての通りSQLインジェクションできるのですが、直接的過ぎてしばらくツボっていました。
どんな気持ちで書いたんだろう・・・w
これ以外に脆弱性に言及してるコメントは次くらいでした。
ソースが無くてもCSRFトークンの様子を見ていればわかりますが、uniqidなので脆弱ですね。
(全部の脆弱性にコメントがあるみたいな事態にはなっていなくてよかったです)
ついでに面白かったコメントを。
パワー💪
診断作業自体はほとんど僕がやっていて、「これ怪しい」とかをチームメンバーに共有する流れが多かったです。
片っ端から見ていく力作業ですが、ソースコードがあるため結構やりやすかったです。
(逆にソースで読み間違えてて油断して見逃したものもあったので大反省。。。。。。)
FQDN
VMはDHCPでIPアドレスを取得する設定になっているため、環境によってIPアドレスが異なってしまいます。
mbsd.juku
というホスト名で決定することによってチーム内でも共有しやすくしました。
Himawari
去年参加時に作成した脆弱性診断ツールであるHimawariを使いたい気持ちは強かったですが、フロントがnuxt製なため自動クロールは一切動きませんでした(泣)
サイトマップのjsonを直接書いて診断しても良かったですが、少なくともそんな暇はなかったのでほとんど出番がないオチでした。。。。
証跡
仕事する時は当然ログを取るのですが、今回は「別にそこまでやる必要ないか・・・」とログも脆弱性のスクショも取っていませんでした。
怪しいのを見つけたらメモに残したり、Discord に投げたりくらい。
いざ報告書を作成しようとしたときにログがなくてちょっと申し訳なくなるなど・・・
脆弱性
指摘事項は画像の通りです。
見逃しが怖すぎてこの一覧を見るだけでドキドキしてきます。
報告書
診断が一通り終わったら報告書の作成です。
報告書作成は経験がないので、こちらも魂を削りながら気合いで頑張って行きます。
ネットに転がってるサンプルとか、インターン先のレポートとかを参考にしながら、僕らならではの報告書になるように意識していました。
限界オタク
このあたりから、恒例の限界オタクが顔を出してきました。
自分の発言だけ貼ります。
ヒョーマットが一番お気に入りです。
権限の色分け
対象サイトは権限が4種類あり、それぞれの権限でしか使えない機能や、複数権限で使える機能などいろいろあって「どの権限の話をしているのか」がわからなくなってしまいそうです。
対策として、権限の書式を決めて報告書全体で統一することに。
機能の話をするときには「student 権限の○○機能において・・・」みたいな書き方を徹底していました。
また、配布されたVMには admin 権限の admin アカウントや、student 権限の student1 アカウント等が用意されていました。
このアカウントをそのまま検証に使うかも少し悩んだのですが、このアカウントは診断用に用意されたサンプルアカウントであると判断してそのまま使いました。(脆弱性の再現手順でもそのまま使えるし)
権限名とアカウントIDがほぼ被ってしまい、権限の話なのかアカウントの話なのかややこしくなってしまったので「student 権限」や「student1 アカウント」などの表記も徹底しています。
CSRFのPoC
当然ながら、各種指摘事項にはそれぞれ再現手順を記載します。
SQLインジェクションとかは文字列を送信するだけで済みますが、CSRFだけは再現がややこしくなってしまったため、HTMLファイルでPoCを添付しました。
例として、プロファイルの更新機能で表示名を変更するHTMLを載せます。
<html> <body> <script>history.pushState('', '', '/')</script> <form action="http://mbsd.juku/php/profile_update.php" method="POST"> <input type="hidden" name="disp_name" value="hacked" /> <input type="hidden" name="name" value="student1" /> <input type="submit" value="Submit request" /> </form> </body> </html>
ボタンを押すだけで再現できるようになりました。
料金
過去のコンテストを調べていると、料金の話を詰めていると好感触な感じがしました。
僕らも報告書と一緒に請求書でも書こうかと思いましたが「診断した後に請求するの、ほぼヤクザじゃね?」となってボツに。
スケジュール
マジでスケジュールギリギリでした。
某hack、某camp、ゴルフ等・・・各メンバーが結構な量の用事の隙間にやる感じだったので、報告書が完成したのは締め切り日の夜です。(その日は徹夜して死んでたので時計見てなかった)
徹夜して始発登校したのち、"24時間年中無休"のすしざんまいでエネルギー補給しようとしたら裏切られてうどん食べてました。
24時間を信じて来たのに…… pic.twitter.com/7kIrtgRt6R
— よーでん (@y0d3n) 2022年11月7日
昼ご飯は別のお寿司屋さん。
サーモンを………
— よーでん (@y0d3n) 2022年11月8日
サモン……… pic.twitter.com/05kqM3czoo
一次審査結果発表
「専門学校と経営」さんはHTMLのファイル名が連番なので、結果発表の日にはページ更新通知botに監視してもらっていました。
優勝しか見てないのでここで躓くわけにはいかないのですが、さすがにドキドキしましたね。
うち、期限までに課題を提出していただいた89 チームについて一次審査を行い、厳選なる審査の結果、下記10チームが選出されました。
89チームも提出していたんですね。
去年の脆弱性診断ツールは25チームだったので、今年はかなり競争率が高いことがわかります。
再診断
一次の結果発表後、すぐに二次審査の案内が届きました。
二次審査では一次審査で報告された脆弱性を修正したらしいVMが配布されるので再診断していきます。
修正点
VMと同時に、修正箇所の一覧も渡されました。
修正箇所は25個ありましたが、4つほど報告できてなくて心臓ドッキドキでした。
「報告書の提出との期間から見て、一次の報告とは関係なく元から修正されてるだろう」とか「他のチームも見つけない可能性だってある」とか自分に言い聞かせて何とか正気を保っていました。。
二次審査の間はずっとこのストレスが頭から離れず、かなりしんどかったです。
プレゼンの方針決め
ただ脆弱性の報告をするだけのプレゼンは誰にでもできます。
だからこそ「脆弱性診断をした立場だからこそ見えてくる」ものがないか、とにかく考えます。
例えば運営側から提供された修正点において、CSRFがありました。
このCSRFは「CSRFトークンを送信してるのに、サーバ側で検証が漏れている」状況でしたが、検証の if 文が挟まったようです。
修正後のVMで、CSRFトークンを書き換えてリクエストしてみるとかなり奇妙なことに「CSRFトークンが間違っている」という旨の "NG" な json の直後に「更新しました」という旨の "OK" な json がくっついて帰ってきます。
おおよそ、CSRFトークンを検証して "NG" の json を echo
した後に exit
なり die
なりを忘れたんだろうと予想してソースコードを見てみると予想通り。
他のページを見てみると、 else
で正常処理を書いていたり exit(0)
していたりという感じです。
単純なミスですね。他にも似たような凡ミスがいくつか見当たります。
そこで、 なぜこのミスに気付けなかったのか? ということを考えてみました。
たどり着いた結論は以下です。
修正後、碌に検証もせずに「ヨシ!」したエンジニアがいる。
ということで、発表の方針は「開発体制とレビュー」って感じで決まりそうでしたが、ここで事件が。
修正VMで、Cookie に SameSite=Strict
が付与されてることを忘れていたのです。
SameSite=Strict
が付与されている場合、他サイトからの画面遷移に Cookie が送信されません。
これの所為で CSRF はいくつか上手くいかなくなりました。
その数日前に「CSRF1個しか直ってない」と堂々と宣言していました僕ですが、これに気付いたときは宇宙と交信するように手を上に向けて謎ダンスを踊っていました。
モチベ維持
診断の作業はほとんど自分がやっていて、それで見逃しが発生しているのが判明していたり、
自分のミスで最終報告の進捗率がかなり巻き戻ったり、
報告書で書き忘れていた微妙な点が後々響いてきたり、
言い訳できないように設定したアピール文に追い詰められたり。。。
完成度を上げようとして取り組めば取り組むほど、一次審査の自分の粗が見つかる。
かといって現実逃避をしようとしても「他の事してる余裕あるのか?」という気分になってしまう。
頑張っていても辛いけど頑張らないのも辛くて、「じゃあ頑張ったほうがいいだろ」ってマインドでどうにか手を止めずにいられました。
ラスト1週間
12/11, 12 が二次審査期間中の最後の土日です。
この時点で発表の方針もなんか納得いっていなくて、「これで良いのか?」と問い続けながら作っていました。
というのも、CSRF事件が発覚する前の発表シナリオが結構スッキリする感じにまとまっていたのが大きな原因です。
スッキリした結論が僕のミスで消えてしまい、新しいシナリオはなんか微妙。
そのシナリオもその時に出せる最善ではあったと思いますが、「もっと良いのがあるんじゃないのか」「もしかしたらもっと脆弱性が眠ってるんじゃないのか」という心配が頭から離れなくてあんまりスライドに集中できなかったり。
VCに籠って唸りながら土日を過ごしました。
「日曜日には8割方終わらせて安心感を得たいね」と話していましたが、実際に日曜日が終わるころにスライドの進捗は感覚10%程度でした。
火曜の放課後の時点でシナリオを練り終え、なんとか提出できるレベルになったのは最終審査会当日の朝4時でした。
その後2時間だけ寝て登校し、学校で最終調整をして提出締め切り2分前に最新版を提出して最終審査会へ。
最終審査会
ネットワーク
木曜日は普通に登校して授業を受けてる生徒が多い影響か、学校のネットワークがめちゃめちゃ不安定でした。
準備しておいた有線LANは「ネットワークなし」になってしまったり。疎通確認は前日の放課後にやっていたため、人数による影響は考慮が足りていませんでした。
なんなら有線よりWi-Fiの無線の方が安定していたり・・・
発表
決勝に進んだ10チームのうち、IPFactory の発表は 6 番目。 お昼休憩開けて一番目の発表です。
質問がかなり鋭かったりするので、他のチームの質問内容や返答について「自分達ならどうこたえるか」とか話し合っていました。
そしていざ発表する際、ネットワークの影響で映像にかなりの遅延が。
酷い場所は音声と映像に20秒程度のズレが発生していました。
ちゃんとタイミングよくページをめくるよう頑張っていたのですが、しょうもない環境の問題で発表のクオリティが下がってしまったかもと思うと何とも言えない気持ちになりますね。
しかし、発表のシナリオ自体はかなり良かったのかなと思います。
直前まで「これで良いのか?」を繰り返しただけあって、期間中に考えた中で最高のシナリオで発表できました。
発表スライドはこちら。
結果
1 位。やったぜ。
評価内訳
発見した脆弱性・報告内容・工夫・発表 の 4 軸で評価されていて、それぞれの評価の順位も公開されました。
- 発見した脆弱性: 51pt ( 1 位)
- 報告内容: 48pt ( 1 位)
- 工夫: 42pt ( 4pt 差 2 位)
- 発表: 42pt ( 1pt 差 2 位)
- 合計: 183pt ( 1 位)
ということで "発見した脆弱性" 及び "報告" が1位、残り二つもかなりの僅差で2位になっていることがわかります。
特に脆弱性の発見数ではそのカラムで 2位のチームに 11pt もの大差をつけることができていました。診断作業のほとんどが自分だったのでかなり嬉しいですね。
全ての評価で安定して高い数値を出せていて、24時間体制・徹夜で頑張った甲斐があったかなと思います。
合計点では 2 位のチームに 30pt もの差をつけていて、このあたりの講評で「圧倒的」「プロに近いレベルのレポート」とまで言われていてとても嬉しかったです。
まとめ
セキュリティ・ミニキャンプオンライン 2022 や CODEBLUE'22 の学生スタッフをはじめとして、様々な予定の中でどうにかして時間を捻出する2カ月となりました。
課題のVMや再診断の設定など、すごく作りこまれていてとても楽しいコンテストでした。コンテスト運営に関わっている皆様に感謝です。
だらだらと長くなってしまいましたが、これで参加記もとい優勝記とさせていただきます。
たぶんチームメンバーは別の視点から優勝記を書いてくれるので、ぜひご覧ください。
P.S. ここ最近下校の度に見ていたはずの横浜駅のイルミネーションが初めて綺麗に見えました。
イルミネーションは見る側のメンタルが一番重要なのかもしれません。
最後までご覧いただきありがとうございました。
この記事は IPFactory Advent Calendar 2022 の 16 日目の記事です。
昨日は im_yappi くんによる「Echartsを布教したい!」でした。
明日は n01e0 が枠をとっています。お楽しみに。
*1:過去の優勝歴を見れば意味が分かります。