こんにちは! 1月に入社したセキュリティチームの坂梨です。この記事はセキュリティチームブログリレーの1日目の記事です。

みなさん、セキュリティはつらく大変なものだと思っていませんか? セキュリティはどうしても「義務としてやるもの」というイメージがつきまといがちです。
しかし私にとっては、セキュリティはまるで古代遺跡を発掘する冒険です。システムという遺跡の奥深くには、まだ誰にも発見されていない脆弱性というお宝が眠っています。エラーメッセージ、レスポンスヘッダー、ソースコードなどは遺跡の壁に刻まれた碑文の断片であり、それらを読み解いてお宝の場所を特定できたときの達成感は一度味わうとクセになります。
このように捉えると、セキュリティがぐっと面白く見えてきます。 その「面白さ」を通じて攻撃テクニックを学び、逆説的に守りを強化できるのではないか——そんな考えから、今回社内CTFを開催しました。
CTFとは
CTF(Capture The Flag)とは、用意されたWebサイトなどをハッキングして中に隠された「フラグ」と呼ばれる文字列を探し出す競技です。 一般のCTFでは、Webアプリケーションの脆弱性を突く「Web」、暗号を解読する「Crypto」、バイナリを解析する「Reversing」など、様々なジャンルの問題が出題されます。
エンジニアリンググループにはWebアプリ開発に長けたメンバーが多いことから、今回は「Web」問題を中心に18問出題しました。SQLインジェクションやXSS、認証バイパスといった基礎的なものからプロトタイプ汚染のような少しマニアックなものまで用意しました。
当日の様子
今回のイベントはオンラインをベースに開催し、Slack上で参加者同士がリアルタイムで盛り上がりつつ、出社メンバーは会議室に集まってワイワイと楽しんでいました。
参加募集をかけたのが開催1週間前という直前だったにも関わらず、当日の参加者はなんと40名! さらにイベント終了後も問題サーバを数日間開放していたところ、後から挑戦した方も合わせると参加者は50名超えとなりました。

参加者の中にはCTF経験者もおり、他の追従を許さない圧倒的強者として終始君臨していました。

途中、問題に行き詰まった参加者からは
- 1on1の予定を入れて上記の圧倒的強者を妨害する(エムスリーには気軽に1on1をする文化があります)
- SRE権限で問題サーバに侵入しフラグを取得する
- 作問者である私のPCを覗き見る
といった冗談(本気?)も飛び出し、盛り上がりを見せていました。


後半戦に入ると、集中するがゆえに現地での会話も少なくなり、より本気度が増しているのが伝わってきます。 その分解けたときの感嘆の声も大きく、達成感があふれているのが見て取れて作問者冥利に尽きました。
競技終了後はお楽しみの解説パートです。各問題の解き方や脆弱性の仕組みを順番に解説しました。 解説中のSlackはとても賑やかで、問題のネタが明かされるたびに「これがハッカーの発想⋯」「解けたけど、解けたことより、(とあるミドルウェアに)こんな脆弱性があったことに震えた」といったリアクションが飛び交いました。
イベント終了後には「他のCTFもやってみたくなった」「第2回も開催してほしい」「次は作問してみたい」といった嬉しい声をいただき、参加者のみなさんにセキュリティを楽しんでもらえるイベントになったと実感しています。

問題をチラ見せ
いくつか出題したXSSの問題のうち1つをご紹介します。
プロフィールを入力するフォームがあり入力した文字列が確認画面に出力されます。

ただし、Content-Security-Policyにより、 https://cdn.jsdelivr.net 以外からのスクリプト読み込みが禁止されています。当然インラインスクリプトも動きません。
この状態でどうにかしてXSSを成功させるという問題です。

ここからは解説です。
スクリプトの読み込みがjsDelivrに限定されているということは裏を返せばjsDelivrからは読み込めるということです。
jsDelivrにはGitHub連携機能があり、任意のGitHub上のファイルをjsDelivrで配信できます。
すなわちGitHub上に実行したいスクリプトを配置しそれをjsDelivr経由で配信することで、Content-Security-Policyの制限を回避してスクリプトを実行させることができます。
GitHub連携機能を利用しなくても、こういったCDNでは様々なライブラリが配信されておりその中にはscriptタグを利用せずとも任意のスクリプトを実行できるものも存在します。
例えば、csp-bypassを使うと、任意のタグの csp 属性にスクリプトを書くだけでCSPの制限を回避して実行できます。
作問の裏話
作問者として一番の悩みどころは難易度調整でした。 参加者の方々は、たとえCTF未経験であっても開発者としては経験豊富な方ばかり。簡単な問題ばかりでは一瞬で解かれてしまい盛り上がりに欠けますし、一方で難しすぎると誰も解けず楽しさが味わえません。
そこで、難易度の異なる問題を多く用意し、初心者でも達成感を味わいながら徐々に難しい問題へと挑戦できる構成を目指しました(興が乗って作りすぎただけ、とも言います)。 例えばXSSの問題では、最初は素直にスクリプトが実行できる状態から始まり、問題を重ねるごとにContent-Security-Policyが厳格になっていき最終的にはJSが全て禁止されCSSインジェクションでフラグを取得する、といったシリーズものにしました。
また、CTFあるあるとして、問題のタイトルが遠回しのヒントになっていることが多々あります。 今回も問題サーバの実装と同じくらい時間をかけてタイトル考案に悩み、それなりに凝った名前をつけられたのではないかと思います。 中でも、5年前のブログにあるX-Forwarded-Forヘッダを利用したアクセス制御バイパス問題を「police」というタイトルで出題し、懐かしさを感じた方もいたようです。

今回の作問ではAIを積極的に活用したことで、2日間という非常に短い期間で問題サーバを用意できました。 基礎的な問題も含むとはいえ、18問を2日間で揃えられたのは驚異的なスピードだと思います。
CTFのWeb問題を作る際、脆弱性の本質部分よりもWebアプリとして成立させるための周辺実装に工数を取られることが多いのですが、AIを活用することでその負担を大幅に削減できました。 問題によっては「◯◯という脆弱性を使ったCTF問題用のアプリを実装して」と指示するだけでほぼ完成形が作れたものもあります。
それぐらい簡単に作問できますので、みなさまも社内や仲間内でCTFイベントを開催してみてはいかがでしょうか。 (前述した圧倒的強者によってものすごい勢いで問題が解かれていったため、競技中に全問正解阻止用として急遽問題を追加しようとしていたのはここだけの秘密です)
参加者からの期待の声もあり、私もすでに第2回に向けた問題のネタを考え始めています。 今回はWeb問題を中心に出題しましたが、エムスリーではiOS/Androidアプリも開発していますので、次回はモバイルアプリのReversing問題を出すのも面白そうです。 www.m3tech.blog
最後に
AIが大半のコードを書く時代になり、エンジニアの役割はコードの実装よりもレビューや設計の判断へと移りつつあります。だからこそ、「このコードのどこが危ないか」を見抜く目が、これからのエンジニアにとってより一層重要になると感じています。 CTFで攻撃側の視点を体験することは、その目を鍛える有効な道の1つだと考えています。今回のイベントを通じて、参加者のみなさんにセキュリティの面白さを少しでも実感していただけたなら幸いです。
We are Hiring!
エムスリーでは、セキュリティエンジニアも絶賛募集中です! 医療に関わる機微な情報を守るという社会的意義の大きなミッションにやりがいを感じる方、そして何よりエンジニアリングそのものを楽しめる方をお待ちしています。 少しでも興味を持っていただけたら、下記リンクよりご応募ください!
なお、この記事にもフラグがいくつか隠されていますので気になった方はぜひ探してみてください。
エンジニア採用ページはこちら
jobs.m3.com open.talentio.com speakerdeck.com