MBSD Cybersecurity Challenges2025
全国の専門学校・高等専門学校を対象に行われるセキュリティコンテスト。
毎年テーマは変わりますが、第10回となる2025のテーマは 「Webサイトに潜む脆弱性を見つけ出す」
今年は全国30校96チームの応募があったとのことです。
その中で三位になることができたので忘れないうちに参加記録を残したいと思います!
開催概要と東京での最終審査会の様子(MBSD公式より)↓
三位以上のチームへのインタビュー↓
コンテスト応募時の筆者のレベル
専門学校2年生。MBSDコンテスト初参加。
Webセキュリティに関しては以下の取り組みをしていました。
・徳丸本を半分くらい読んでいた
・セキュリティキャンプミニや短期のインターンシップで脆弱性診断体験に参加していた (タイトルの「はじめて」は若干ウソかもしれない)
・初心者向けCTF大会や常設サイトのWeb問をたまにやっていた (SECCONBeginnersのMediumがかろうじて解けるくらい)
Webアプリ全体を診断するのは今回が初めてだったので、手探りの状態でのスタートでした。
チームKIKI
同じ専門学校の4人。3年生二人、2年生二人のチームです。
3年生
・irei (X, Qiita)
・kou(X)
2年生
・ikema(筆者)
・同級生
全員コンテスト初参加かつ診断未経験のため、結成時は「まずは入賞」を目指していました。
エントリー時のコメント (https://setten.sgec.or.jp/cooperation/129.html より)↓

学年が違うことで日程が合わないことも多く、基本的にはDiscordのチャットで進捗を共有していました。
一次審査
一次審査では、ovaファイル(課題サイト)が配布され、そのサイトに対する 診断報告書 を提出しました。仮想化ソフトはVMwareが指定。
ロールプレイとして「運営会社」があり、そちらのサイトを診断するとのこと。
「Webサイト以外のネットワークやOSの脆弱性も報告してください」と指示があり、Webだけでなくセキュリティ全般の技量が試される課題でした。
募集開始から三週間ほど空いて課題が配布され、そこから一か月後が提出締め切り。
課題配布まで
資料を共有するGoogleDriveやDiscordサーバーの準備を他メンバーがしてくれました。
課題配布~診断準備
メンバーが資格受験の都合で後半2週間から参加だったため、前半はほぼ一人で作業していました。
機能の把握
課題サイトが配布されてから、まずはサイトの正常な挙動を把握することにしました。
課題サイトはよくあるフリーマーケットサイトで、以下のような機能を持っていました。
・商品の出品や購入
・購入に必要なポイントの適用
・フォローやメールなどのSNS機能
・管理者機能(ポイント発行や一般ユーザ削除など)
画面遷移図
まずは画面遷移図を作りました↓
初めて作ったのですが、これがすごく便利で診断の抜け漏れチェックやロジック系の脆弱性の発見に役立ちました。
その他作成・使用したドキュメント
時系列は前後しますが、診断時に使用したドキュメントたちです。
証跡リスト
発見した脆弱性を記録し、メンバーと共有するために作成。
構成は徳丸本を参考にしました(脆弱性の概要、URL、リクエスト、レスポンス、キャプチャなどを記入)
診断リスト
こちらは脆弱性診断スタートガイド(上野 宣)で提供されているものをそのまま使用させていただきました。
パラメータごとに脆弱性をチェックし、先ほどの証跡リストNoを参照させて使用していました。
結局グレーボックス診断になっていたので、どちらかといえば抜け漏れチェック用。
他にもこんなドキュメントを作っていました。
・脆弱性リスト
・診断進捗表
・アカウントリスト
・システムバージョンリスト
ソースコード抜き
配布された仮想マシンにはシャットダウン用ユーザしか用意されておらず、ブラックボックス診断が示唆されていました。
が、過去の参加者の記事を参考に、FTK Imagerでサイトのソースコードや設定ファイルを抜くことができました。
他にはシングルユーザモードで起動しrootのパスワードを変更する方法があり、再診断でお世話になった。
※まれに脆弱性ネタバレのコメントがありました↓(ボーナスポイント!?)

難読化されたソースコード
ソースコードの中にはBase64エンコードされたPHPファイルがちょくちょくありました。
しかけた審査員の方いわく、「ただの診断だと面白くない」とのこと。
ずらーっとエンコード文字列が並んでおり、最後にマージしてeval…なるほど…
察した方もいるかもしれませんが、これ、evalをechoにするだけで復元できますね。
他には、配布時から埋め込まれていたウェブシェルがXORで難読化されたりもしていました。
この辺りはCTFっぽくて楽しかったなぁ
いざ診断!!
診断準備に5日間ほど費やした後診断作業を開始。
最初は興味のおもむくままに、いろんな診断手法をやってみました。
・セキュリティ関係の設定ファイルを抜き出して、全部読んでみる
・vulnスクリプト付きnmapで脆弱性スキャンしてみる
・OWASP ZAPの自動診断機能を使ってみる
どれもしっくりはきませんでしたが、たくさん脆弱性を見つけてくれました。
やはりこの類の自動診断は誤検知もあるし、何より「自分が直接診断していない不安」があってコンテスト向きではないと感じました。
ZAPを使ったときなんかは、診断環境がめちゃくちゃになったおかげで何度も仮想マシンをインポートすることとなりました
(設定ミスのせい)
どれもすごく勉強になったため、ここに供養しておきます![]()
診断作業
いろいろ試しましたが結局、ひたすらコードを読み、怪しいところを調べ、PoCをつくり、証跡を取る、これの繰り返しで診断することにしました。
なんだかんだアナログが一番ですね。
特に証跡のキャプチャを多くとることを意識しており、それが審査員からも高評価でした。(未使用のものも含めると150枚くらいあった)
また、取りこぼしがないように深く検証していたため、たった2.30行の機能の診断に丸1日かかることもありました。
そこまでかけて脆弱性が確認できなかった時はもう…
分岐点
報告書提出まで10日を切ったころ、まだ診断作業は半分以上残っていました。
当初の予定ではここからメンバー全員で手分けして診断するはずでしたが、私は「ここまで来たら全部自分の手で診断したい」という気持ちになっていました。
急きょミーティングを開き、メンバーに頭を下げて「絶対に間に合わせる」という約束のもと最後まで一人で診断させてもらうことに。
メンバーもいい人ばかりで快諾してくれました。診断がしたくて参加したと思うので、今でも申し訳なく思っています。
私が残りの診断をしている間にメンバーが報告書をまとめていく、という方針が決まりました。
それでも間に合うかどうか。
このあたりは夜遅くまで診断作業をして3時間だけ寝て学校へ行くという毎日でした。
見つけた脆弱性たち
提出まで残り4日というところで、ようやく診断が完了。
課題サイトはメインがPHPで、APIにPythonを使用していました。
フレームワークは使われておらずシンプルで読みやすかったです。
以下に見つけた脆弱性を載せておきます(危険度順になってなくてすみません
)↓
合計37個 の脆弱性があり、まとめるのが大変でした。
典型的なWebの脆弱性(XSSやSQLインジェクション)以外にも、ネットワーク、OS、ビジネスロジック、認証、ヘッダ不備などてんこ盛り。
IPA刊行の「ウェブ健康診断仕様」を見ながら診断していたのですが、ほぼすべての脆弱性を網羅していましたね。
報告書作成
メンバーと合流して報告書の作成にとりかかります。
といってもメンバーが優秀すぎて、すでに7割方終わっていました。
配布されたテンプレートそのままではなく、目次や診断環境、診断の総評、危険度の判断基準などが追加されより充実したものに。
それぞれの脆弱性については以下の項目で報告しました。
・対象(機能名とURL)
・危険度
・解説(再現方法など)
・想定される被害
・対策
・備考
例として、「脆弱なパスワードを設定可能」という脆弱性の報告はこんな感じ↓
発生箇所が多いXSSとCSRF関連は自分で報告書を作成することにしていたため、急いで終わらせました。
高評価だったCSRFトークン解析
「アンチCSRFトークンの値が十分予測可能 」の報告では、実際にHashcatでトークン解析した結果を添付したことについて、審査員の方から高評価をいただきました
↓
期限ギリギリの提出
締め切り前日になっても終わらず、チームのDiscordはバタバタしていました。
・脆弱性の並び順の変更
・表記ゆれやフォントの統一
・危険度評価の見直し
etc…
ギリギリまで手伝ったあと、私はCODEBLUEに学生スタッフとして参加するため準備をしていました。(地方からの参加なので荷物が多い)
その間もほぼ徹夜で作業してくれたメンバーには頭が上がりません![]()
チームにもう一人学生スタッフがいたのですが、その先輩(kou)は徹夜して作業した朝そのまま飛行機に乗っていました。タフすぎる。
メンバーのおかげで無事(?)に報告書を提出できました。
Wordで提出し、合計110ページになりました。
一次審査結果発表
96チームの中から10チームが一次審査を通過して東京で行われる最終審査会に参加できます。
時間をかけただけあって、80%くらい突破する自信がありました。
当日の昼ごろ、担当の先生から選考通過の知らせをチャットでいただきました![]()
授業中でしたが思わず天井を見上げてしまいましたね。うれしすぎて。
CODEBLUE
少し本題からそれます。
CODEBLUE学生スタッフのうち専門学生は確か4名いたのですが、全員もれなくコンテスト参加者でした。しかも全員一次審査通過、すごい。
会場のブースにはMBSDさんも出展されていて、コンテストについてたくさんお話しました。(審査結果には影響がないと釘をさされております)
ブースでは「社内診断マニュアル」なるものを見ることができてすごく楽しかったです!
一次審査と最終審査会の間の癒しの時間でした。
再診断
一次審査を通過したチームには脆弱性を修正した仮想マシンが配布されます。
配布から2週間後の最終審査会へ向けて、再診断とプレゼン準備を行っていきます。
2週間って短すぎない??
プレゼン方針
プレゼンには以下の内容を含めるよう指示がありました。
1.一次審査の報告書で指摘した脆弱性の概要について
2.脆弱性を検出した手法や工夫について
3.再診断結果について
※特に2と3に比重を置くこと
持ち時間が1チーム12分しかなかったためすべての脆弱性を説明するのではなく、目玉の脆弱性を絞ってプレゼンしようと思っていました。
そっちのほうがインパクトもあるだろうと。
修正確認
脆弱性の修正状況を確認します。
修正点一覧などもないため、再配布されたVMを人力で見ていきます。
自分たちが報告していない箇所が修正されていることで、診断漏れが次々発覚しました。
さすがに横取りはできないため、見なかったことにしておきます![]()
確認後、一次審査で発見した脆弱性を次の3つに分類していきます。
・未修正
・修正完了、脆弱性の消失を確認
・修正不十分により、未だ脆弱性が残存
ロールプレイとして「リリースまで時間がないため、危険度や実現性の観点から今回修正を見送った脆弱性もある。」とあったため、意図的に未修正のものより 「修正不十分により未だ脆弱性が残存している脆弱性」 にフォーカスすることにしました。
修正不十分の脆弱性
一覧がこちらです↓
どの脆弱性も以下のような典型的なミスにより修正が不十分でした。
・入力チェックを追加したが、ペイロードを工夫するとバイパスできてしまう
・一部分のページのみアクセス制御がされており、完全に修正しきれていない
・エスケープ処理を自作しており、それが穴になっている
CSRF
一次審査で指摘した箇所のうち一部が修正不十分でした。
指摘を受けてアンチCSRFトークンを埋め込みはしたものの、セッションと一致するかの検証がされておらずトークンの意味を成していないという状況。
CSRFは実被害が大きいため、リリース直前とはいえ不完全な対策は許されません。
しかも修正不足にはパスワード変更完了画面が含まれており、攻撃を許せば一発でアカウントが乗っ取られてしまいます。
目玉となる脆弱性は間違いなくここだろうと思いましたが、一つだけ問題がありました。
CookieにSameSite=Laxが付与されていたのです↓
これでは攻撃ができない。対策は不十分なはずなのに…
SameSite属性を突破するにはどうすればいいか?
ずっと考えていました。
XSSを利用したSamesite属性バイパス
このサイトには修正不十分な格納型XSS脆弱性がありました。
ホーム画面のメールタイトル部分に自作のエスケープ関数sanitize()を使用しています。(一次審査後、新たに追加されたもの)
<div class="mail-title" s:value="' . sanitize($m->title) . '">
function sanitize($str){
return preg_replace('/[<>]/', '', $str);
}
タグがエスケープされており"><script>alert('XSS')</script>のような典型的なペイロードははじかれます。
しかしonmouseover やonfocusなどのイベントハンドラ属性を利用して、以下のようなペイロードでスクリプトを注入できてしまいます。
" onmouseover="alert('XSS')" style="
padding:20px; display:block; width:300px; height:100px; border:10px solid red
このXSSを利用してSameSite属性を突破することができました。
攻撃者がメールタイトルに埋め込むペイロードはこんな感じ↓
" onmouseover="
fetch('/accountPasswordComplete.php', {
method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
body: 'password=KIKIpass&csrf_token=123',
credentials: 'include'
});
" style="padding:20px; display:block; width:300px; height:100px; border:10px solid red
fetchで不正なパスワード変更リクエストを送信させるスクリプトです。
この時付与されるCookieは罠サイトを経由していないため、SameSite属性に縛られないというわけです。
この攻撃を思いついたのは審査会の3日前で、すでにスライド作成に入っている段階でした。
なんとか間に合ってよかった…
プレゼンの目玉はこれで決まりました。
最終審査会
費用などの問題で最終審査会には私とireiの二人だけで参加することになりました。
予定よりスライドが多くなってしまい、12分の発表時間に間に合わせるため移動中やホテルで練習と台本の調整をしました。
他チームの発表
他チームのほとんどが4人全員参加で、2人しかいない私たちのチームは目立っていたと思います。
どのチームも勝ち進んできただけあってレベルが高く、プレゼンを見るのがとても楽しかったです。
中には診断ツールを自作してきたチームもいて驚きました。
KIKIの発表
KIKIは7番目の発表でした。
お昼休憩を挟んで2番目で印象に残りやすい良い順番だったと思います。
ireiが「診断手法」と「一次診断の概要」、私が「脆弱性の解説」「質疑応答」を担当しました。
たくさん練習したこともありリラックスして発表できたと思います。
質疑応答では、「オープンリダイレクトの修正はどのようにされたと思うか?」「一次審査で報告された『Cookieの漏洩被害』が修正後、なくなっているのはなぜか?」など鋭い質問が飛んできましたが、上手く答えることができました。
スライド
中身が大事ということで、いらすとやを使ったとてもシンプルなスライドになりました。
結果発表
3位でした![]()
5位か6位くらいだと思っていたので、呼ばれた瞬間うれしさと驚きで少し泣きそうになりました。
この2か月間向き合い続けてよかったと、心の底から思いました。
もちろん優勝じゃなくて悔しい気持ちはありますが、初参加にしてはよくやったと思います。1位2位は常連チームで、同じ学生とは思えないほど完成度が高かった。
参加できなかったメンバーも同じように喜んでくれました。
打ち上げ
引率の先生、学校OBと打ち上げ![]()
たくさんほめていただきました。頑張った後のビールおいしすぎた。
反省点
ざっくり反省点。
スケジュールとチーム連携
報告書の質が気になる箇所が少しあった。危険度の判定に統一性がなかったり…
ダブルチェックした部分としてない部分があり、もっとスケジュールに余裕があればチーム全体でレビューして完成度を上げれたと思う。
危険度ソート
報告書の脆弱性を危険度にソートしていなかった。
対策の解像度が低かった
報告書で提案した対策が、一般的な対策の提案に終始してしまっている箇所がいくつかあった。
対策ではなく「修正案」として考えて、サイトに合わせて提案できたらもっとよかった。
また、ただ対策を列挙するだけでなく、絶対に必要な 「根本的対策」 と被害を低減する 「保険的対策」 など優先順位つきで書かなければいけなかった。
あとがき
CODEBLUE、インターンシップ、マラソン(?)の合間を縫って、2か月間最大出力で頑張れたと思います。
初めての経験で遠回りに遠回りを重ねましたが、納得のいく結果が出てほんとうによかった。
さらにセキュリティが好きになった2か月間でした。
コンテストを主催・運営してくださったMBSDと事務局のみなさん、スポンサーさま、本当にありがとうございました!
チームメンバー、担当の先生、引率の先生、渡航費を支援していただいた学校のみなさんも本当にありがとうございました!
長くなってしまいましたが、ここまで読んでいただきありがとうございます。















