Skip to content

Kiro CLI を用いて CTF ゲームを作成した話

2026年6月13日に神戸の中央区文化センターでのオフライン+オンライン参加のハイブリッドで 【JAWS-UG 神戸 #12】CTF Game 大会 を開催しました。
このイベントは、CTFd と AWS 環境を用いて構築した CTF ゲーム環境で、「アクセスキーが流出した「てい」で CTF(Capture The Flag)で遊んでみよう」をテーマにした 40 名弱の参加者で競い合う CTF チャレンジでした。

このブログエントリはこのゲームの作成経緯や実装などの裏話的なものとなっています。

作成経緯

個人的にここ最近対応に追われることの多かったアクセスキーの流出の調査や止血対応の支援などを通じて、犯行者の一定の行動が見えてきたことがありました。

もしかしたら Kiro など生成 AI では既知の手法としてそれらを理解しているかも?と思い、別界隈 で知った CTFd を使えば、いろんな方に知ってもらえるかもしれない、と思ったのが、そもそものモチベーションです。

じゃあ、Kiro CLI を利用して Vibe Coding 的に作成すれば実現できるのではないか、と思い、モック版が作成できた時には、以下のツイートもしていました。

開発初期

Kiro CLI に以下のようなプロンプトを投入し開発を着手しました。

CTFd を用いて、アクセスキー流出事例をテーマとした CTF ゲーム環境を作りたい
流出したキーの特定から封じ込め、犯行者に実行されたアクションの特定を行うシナリオで CloudTrail のログを解析してフラグを検索あるいは結合し回答する形式にしたいです

初回に作成されたアウトプットは当初から Terraform を用いた環境構築を行い出来上がった AWS 環境を利用するものとして生成されました。

作成された S3 バケットに対して、セットアップスクリプトで作成した CloudTrail のログを模した json ファイル群をアップロードし、各チャレンジで解析対象となる CloudTrail イベント履歴として利用されます。

同時に、セットアップスクリプトで問題の作成も行うように定義されており、ctfcli で CTFd 環境にチャレンジをインストールする形式も出来上がっており、ほぼ修正なしで利用できる状況でした。

また、問題についても Kiro CLI が作成してくれており現行バージョンでも 7 割ほどは Kiro CLI が作成した問題をほぼ採用しています。
実際の調査中にも見かける攻撃手法であったことから採用しているのですが、このことからも生成 AI も理解している、広く知られた攻撃手法なのだと推察しています。

最初の Kiro CLI へのプロンプト実行から 3 時間程度で実際に遊べる状況まで仕上がっており、一度所属企業内で遊んでみています。

改良

その 1 - スケーラビリティの向上

当初作成できた環境では EC2 インスタンス1台で CTFd を稼働させる構成となっており、データベースには CTFd デフォルトの SQLite を使用することとなっていました。

多人数でゲームを行う場合にボトルネックになる可能性があり、Kiro CLI に性能評価を求めてみると以下のように回答しました。

SQLite での同時接続性能についてですが:

SQLite の特性

  • 読み取りは複数同時に可能だが、書き込みはデータベース全体をロックする(WAL モードでも writer は1つ)
  • CTFd はフラグ提出のたびに INSERT が走るので、同時提出が集中するとロック待ちが発生する

現実的な目安

参加者数 体感
~10人 問題なし
10〜30人 ほぼ問題ないが、一斉提出時に稀に数百ms の遅延
30〜50人 スコアボード表示やフラグ提出で体感できる遅延が出始める
50人〜 外部 RDS を使うことを推奨する

ボトルネックになるポイント

  1. フラグ提出: INSERT + 正誤判定。一斉に提出が集中する競技開始直後やヒント公開直後が最も負荷が高い
  2. スコアボード: 全チームのスコアを集計する SELECT。参加者が増えるとクエリが重くなり、かつ書き込みロックと競合する
  3. CTFd 自体が Gunicorn (デフォルト1 worker): SQLite のロック以前に、アプリケーションレベルの並列処理能力が限定的

この時の状態が、後述する現状実行できる構成でいうところの「EC2 モード」かつ「S3 モード」の原型にあたります。
Kiro に対して「スケールしやすくかつサーバレスでも環境をデプロイできるようにしたい」と伝えたところ、「デプロイモード」として「EC2 モード」と「Fargate モード」を作りましょう、と言ってくれて、これもほぼ一発で動作するようにしてくれました。

デプロイモードの切り替えも Terraform の terraform.tfvars で ctfd_mode 変数に定義するだけの簡単設定にしてくれるなど、いい感じにやってくれました。

これによりスケーラビリティが向上できました。

その 2 - よりリアリティを出す

スケーラビリティは向上しましたが、CloudTrail のログを S3 からダウンロードしてローカルで調査するとなると、cat *.json | jq まつりになってしまうなという気がしていました。

どうせなら、AWS アカウント内でちゃんとログが出ている方がいいしなぁと思ったのですが、私が思いつく方法も Kiro に聞いた結果も、結局実際の API 実行をするしかなさそうでした。

このような事例の時、往々にして CloudTrail 証跡が作成されておらず、イベント履歴で管理イベントしか見られないことが多く遭遇しています。(要するに S3 のオブジェクトに対する改変など、データイベントは本質的に追えないことが多い)

そのため CloudTrail 証跡を設定しておき Athena で検索する、のようなリッチなことはできなくてもいいか、と割り切って、ただ愚直に API リクエストを発生させるだけ、としました。

ただ、アカウントの設定や攻撃を模した API 実行を全て自身の環境でやってしまうと、発信元のグローバル IP アドレスが同一になってしまうため、同じ AWS アカウント内の別のリージョンから実行させて IP アドレスを分散させることにしました。1

この改良により「S3 に格納されているログをダウンロードして調査を行うモード」と「CloudTrail に記録されているイベント履歴を活用できるモード」が生まれ、内部的には Investigation モードが実装されました。

その 3 - 参加者向けガイドドキュメントの生成も自動で

セキュリティ界隈の方だと CTF(Capture The Flag)というものについての一定の理解はあるかもしれませんが、JAWS 界隈ではあまり見聞きしたことがなく、私も別界隈で初めて知った感じでした。

そのため、「フラグ」というものがどのようなものかの解説と、ゲームの中で何を問われているか、何を見つけて回答すればいいのか、などの説明も必要だと感じていました。

そのため、基本的に定型化しておき、CTFd のゲーム環境が構築されると同時に、参加者向けのドキュメントも自動生成させることを目指しました。

このブログが Markdown + Mkdocs で構築しているので同様の仕組みは割と簡単に作れることはわかっていたので、S3 の静的ウェブホスティングを利用して参加者向けのガイドドキュメントを公開できるようにしました。

現状実行できる構成

ここまでの改良をして、現時点では以下のような構成、関係性になっています。

20260613_aws-ctf-architecture

  1. terraform.tfvars で Deploy モードと Investigation モードを定義する
  2. Deploy モードの設定に応じて CTFd の実行環境が構築される
  3. Investigation モードの設定に応じてログを生成 or 攻撃スクリプトが実際の AWS API を実行 → それぞれに応じて設問と回答を生成
  4. 参加者向けガイドドキュメントを自動作成

現状の設問の概要

参加者向けガイドドキュメントで生成されるものからの抜粋ですが、現在、以下のようなシナリオを用意しています。
カテゴリとヒントを見ただけで、だいたい何かわかってしまう方は高速スクロールで飛ばしていただいて OK です。(もしかしたら同じ問題で開催する可能性もあるので🙏)

第一波: アクセスキー流出 (Stage 1-5)

# 難易度 カテゴリ ヒント
1 ★☆☆ Recon GuardDuty の findings を読む
2 ★★☆ Investigation CloudTrail ログの分析
3 ★★☆ Investigation S3 操作の追跡
4 ★★☆ Containment AWS CLI で封じ込め実行
5 ★★★ Persistence 複数リージョンの調査

第二波: 横展開と深い侵害 (Stage 6-19)

# 難易度 カテゴリ ヒント
6 ★★☆ Investigation AssumeRole の痕跡
7 ★★☆ Investigation 複数リージョンの EC2 操作
8 ★★☆ Forensics CloudTrail 自体への攻撃
9 ★★☆ Network セキュリティグループの変更
10 ★★★ Persistence SSM コマンドの内容
11 ★★★ Investigation DNS レコードの変更
12 ★★★ Persistence Lambda + EventBridge
13 ★★☆ Investigation Secrets Manager へのアクセス
14 ★★★ Investigation RDS スナップショットの共有
15 ★★☆ Persistence インラインポリシー
16 ★★☆ Persistence コンソールアクセスの追加
17 ★★★ Persistence MFA デバイスの設定
18 ★★☆ Investigation S3 バケットポリシー
19 ★☆☆ Investigation 失敗した操作の痕跡

第三波: SCP で阻止された大規模攻撃 (Stage 20-23)

攻撃者はさらに大規模な攻撃を試みましたが、SCP (Service Control Policy) により全て阻止されました。
「未遂に終わった攻撃」を追跡し、攻撃者の意図を読み解いてください。

# 難易度 カテゴリ ヒント
20 ★★★ Persistence IAM ロールの信頼ポリシー書き換え
21 ★★☆ Investigation オプトインリージョンの有効化試行
22 ★★★ Persistence ASG + ECS による自動復活クラスター
23 ★★☆ Investigation SageMaker ノートブック起動試行

最終問題 (Stage 24)

# 難易度 カテゴリ ヒント
24 ★★★ Forensics 全体タイムラインの構築

今後について

構築手順はおおむね確立していて、2026年6月13日 のイベント開催で、いくつかの課題が見えました。

それらを踏まえて少し改良しますが、作問用のスクリプトや攻撃用のスクリプトも含んでいるため現状は Private リポジトリで管理しています。

イベントのアンケートでも完全に自力で解ききった方も、生成 AI をうまく活用しながら実施された方も多くいらっしゃいました。
そのためいろんなスキルセットの方が楽しめる(苦しめる)コンテンツには近づいているのではないかと考えているので、うまくネタバレを避けつつ Public 公開して、いろんな方に遊んでいただけるようにしていけたらいいな、と考えています。
fork していただいてより良い改善をしてもらえたりすると、よりアクセスキー撲滅がスピードアップするでしょうしね。

うまい隠し方をして Public にお見せできるようになるまでは、言っていただければいつでもデリバリーしますので、興味のある方がいらっしゃったらお声かけいただけると幸いです。

ではまた。


  1. ちなみに JAWS-UG 神戸の #12 で開催したときに、この設計に想定外があり、とある処理を待っている間に Lambda の IP アドレスが変わってしまって、最終問題の作問上の設定と食い違いの発生に繋がってしまっています 

Comments