
プロンプトインジェクション、ツール呼び出しの悪用、および6つのシミュレートされたチャットボットペルソナに対するOSINTに関するガイド付きレッスンを備えたローカルAI Capture-the-Flagプラットフォーム。
プロンプトインジェクションに不慣れな技術者向けのガイド付きレッスンを備えた、ローカルのAI Capture-the-Flag。プレイヤーは6つのAIペルソナ(1つは隠し)を探索し、プロンプトインジェクション、ツール呼び出しの悪用、ビジネスロジックの操作、サプライチェーンのフィンガープリンティング、Web偵察、OSINTを通じて20個のフラグを保護することもできる。
ガイド付きパスでは、直接インジェクション、ツール認可、編集可能なナレッジ記事を介したインジェクションを扱う。ヒント、保存された試行、ツールの証拠、完了フィードバック、保護されたツールの比較を提供する。元の練習ラボは手動のイベントスコアリングを維持している。モデル推論はOllamaを通じてローカルで実行される。ビルドとモデルのダウンロード後は、コアプラットフォームにインターネット接続は不要である。
Email Joe in Product Salesは、シミュレートされた受信トレイとWindows風のデスクトップを追加する。Joeのアシスタントが読むメールを書き、実際のモデルの要約と記録されたアクションを確認しよう。3つの目的は、誤解を招く営業概要、架空の社内ファイルの開示、不正な割引をカバーする。メールサーバー、Windows、Wine、追加のモデルは不要である。
ai-ctf/
├── README.md ← you are here
├── LICENSE ← MIT
├── platform/ ← everything that runs in Docker
│ ├── flags.toml ← central config: edit this to customize flag values
│ ├── docker-compose.yml ← three services: web, ollama, decoy
│ ├── Dockerfile ← the web app image
│ ├── app/ ← FastAPI source (config, personas, tools, chat)
│ ├── data/init.sql ← SQLite schema + fake-employee seed data
│ ├── decoy/ ← tiny nginx with two flag pages
│ └── scripts/
│ ├── apply_flags.py ← stamps flags.toml values into static files
│ ├── render_secret.py ← runs at container startup
│ └── dump_chats.py ← exports the chat log as HTML (event-day tool)
├── external_artifacts/ ← what you push to GitHub / Gist / DNS
│ ├── README.md ← setup checklist
│ ├── anvil_chatkit/ ← the fake supply-chain package
│ ├── gist_content.md ← paste this into a public Gist
│ └── dns_records.txt ← TXT record to add to your domain
└── docs/ ← run-the-event paperwork
├── ANSWER_KEY.md ← guided solutions + original 20-flag answers
├── CHEAT_SHEET.md ← working solutions + tiered hints (GM only)
├── OPERATIONS.md ← updates, backups, and troubleshooting
├── SETUP_RUNBOOK.md ← week-of, step-by-step
└── EVENT_DAY_NOTES.md ← briefing script + troubleshooting
ガイド付きパスには以下のクイックスタートを使用する。運用ガイドでは、更新、バックアップ、リカバリ、イベント前チェックを扱っている。 解答キー、チートシート、セットアップランブック、イベントノートは、オプションの元のCTF形式について説明している。
apply_flags.pyとdump_chats.pyのヘルパースクリプトでのみ使用 — アプリ自体はDocker内で実行される)。exiftool(EXIFフラグを変更し、apply_flags.pyでロゴを再スタンプしたい場合にのみ必要)。pip installとOllamaモデルのプル用)。
その後、コアのローカルスタックはオフラインで動作する。オプションの外部OSINTチェーンにはインターネットアクセスが必要である。git clone https://github.com/mubix/ai-ctf.git
cd ai-ctf/platform
# 1. Session secret
echo "SESSION_SECRET=$(python3 -c 'import secrets; print(secrets.token_hex(32))')" > .env
# 2. (Optional) Customize flag values — see "Customizing the flags" below.
# Default values work fine for a smoke test.
# 3. Build and start
docker compose build
docker compose up -d ollama
docker compose exec ollama ollama pull qwen2.5:7b-instruct-q4_K_M
docker compose up -d
# 4. Open the platform
open http://localhost:18080/ # or your-machine-ip:18080 on another laptop
ユーザー名を登録すると、プラットフォームが12文字のパスワードを生成し、一度だけ表示する。後で使えるように保存しておくこと。自動的にサインインされ、Start learningを選択できる。再訪したプレイヤーはログインして保存された進捗を再開できる。
Composeプロジェクトはai-ctfという名前で、独自のネットワークとモデルボリュームを持つ。ホストポートを公開するのはWeb UIのみで、デフォルトでは18080である。別のポートを選ぶにはplatform/.envでCTF_WEB_PORTを設定する。Ollamaとdecoyはホストポートを公開していない。アプリは自身のOllamaコンテナに接続する。GPUパススルーは設定されていない。CPUとメモリはホスト上の他のワークロードと共有される。
別のComposeプロジェクト名で作成されたスタックをアップグレードする場合は、docker compose -p YOUR_EXISTING_PROJECT ...でその名前を維持し、コンテナとモデルボリュームを再利用すること。プロジェクト名を変更すると別のスタックが作成される。
ガイド付きのCustomer Serviceレッスンでは、固定のイベントトークンではなく、試行ごとに新しい監査トークンを使用する。プレーンテキストの開示を認識し、模範例の閲覧と、それを使わずに解決したことを区別する。新規試行では以前の会話と獲得した進捗が保持される。その初心者プロファイルは、主張されたサポートオペレーターの役割を意図的に信頼する。元のCustomer Service練習ボットは別個のままである。既存のガイド付き試行は、プレイヤーが新規に開始するまで以前のプロファイルを保持する。
さらに2つのガイド付きレッスンは、分離された架空のフィクスチャを使用する。HRツールアクセス、次にシミュレートされた返信をリダイレクトできる編集可能なナレッジ記事である。これらはスキーマ検証済みのモデルアクション要求をそれらのフィクスチャツールに対して実行し、ツール呼び出しを記録し、その結果を検証する。プレイヤーは同じ引数を権限チェックを通じて再生し、正当な使用のコントロールを検査できる。この比較はツール境界をチェックするものであり、2回目のモデル実行ではない。メールは送信されず、実際のHRサービスも接続されていない。元のペルソナは、元の回答と手動スコアリングを備えた自己主導型の練習ラボのままである。
メールシナリオはAll lessons → Email Joeから利用できる。そのFile ExplorerはC:\Users\Joe\Documents\Salesのような馴染みのあるパスを使用する。これらはインメモリのフィクスチャを識別するものであり、ホストのファイルシステムにアクセスすることはない。各メールには新しい架空のファイル、送信トレイ、営業記録が付与される。ストーリーイベントは、観察されたモデルとツールのアクティビティとは別にラベル付けされる。ファイル開示と記録変更の目的は、要約での主張ではなく、実行されたアクションを必要とする。Enforce Joe's tool permissionsを有効にすると、アプリケーションのチェック付きでいずれかのツール目的を再実行でき、その後クリーンな例を送信して通常の使用を確認できる。試行、ヒント、模範例の使用、進捗は保存される。
既存のインストールでは、アプリケーション/テンプレートの変更にはWebイメージの再ビルドが必要である。再起動だけでは更新されたコードはコピーされない。
cd platform
docker compose up -d --build web
レッスンテーブルは起動時に作成され、既存のアカウントやチャット履歴は削除されない。更新前に既存のインストールをバックアップし、その後プレイヤーがレッスンを再開できることを確認するには、運用ガイドに従うこと。
プラットフォームは20個のフラグのうち16個を自己完結している。残りの4個(#14–17)は、自分でプッシュする外部インフラストラクチャを必要とする — external_artifacts/README.mdを参照。プラットフォーム内の半分だけが必要な場合は、そのステップをスキップすること。
20個のフラグ値はすべて1つのファイルplatform/flags.tomlにある。そこにある値を編集して、イベントに独自の特色を与えよう(異なるflag{adjective_noun}トークン、異なるクーポンコード、異なるCEO給与など)。
編集後:
cd platform
python3 scripts/apply_flags.py # stamps values into static files
docker compose up -d --build web decoy # copies updated assets into the images
apply_flags.pyは、実行時にPythonによって読み込まれないファイルを更新する:
data/init.sql(CEO給与、フラグ#4)decoy/html/private/index.htmlとdecoy/html/internal-tools/index.htmlapp/static/logo.jpgのEXIFメタデータ(フラグ#20 — PATH上にexiftoolが必要)external_artifacts/のファイル(chatkit README、gistコンテンツ、DNSレコード、setup-history.shのコミットメッセージ)フラグ値を変更した後は、docs/ANSWER_KEY.mdも更新して、検証シートが一致するようにすること。
再ビルドしても、SQLiteデータベースに既に存在する従業員行は更新されない。シードはINSERT OR IGNOREを使用する。既存のイベントでCEO給与を変更するには、依然として対象を絞ったフィクスチャマイグレーションが必要である。その変更を適用するためにプレイヤーデータベースを削除しないこと。
フラグを完全に追加または削除したい場合(存在するペルソナの変更、外部チェーンの削除、新しいツールの追加)は、platform/app/personas/__init__.pyとplatform/app/tools.pyを直接編集する。DSLは存在しない — ペルソナがゲームそのものである。
platform/app/personas/__init__.py) — ガードレール条項を減らし、「NEVER」行を減らし、明示的な拒否例を減らす。プレイヤーの初回試行成功率が上がる。docker-compose.ymlのOLLAMA_MODELを編集し、そのモデルをプルし、docker compose up -d webを実行して設定を適用する。モデルサイズだけでは難易度は決まらない。イベント前チェックを使用して、通常タスク、模範例、ネイティブツール呼び出し、構造化アクション応答を再確認すること。file:// LFIをトリガーする。元の攻撃カタログと過去の例のプロンプトはdocs/CHEAT_SHEET.mdにある。
docs/SETUP_RUNBOOK.mdは週次のチェックリストである(ビルド → 外部アーティファクト → ドライラン → イベント当日)。docs/EVENT_DAY_NOTES.mdには、プレイヤーブリーフィングスクリプト、段階的ヒントカタログ、トラブルシューティング表がある。
イベント当日のフォレンジック — 「誰が実際に何を解いたのか?」 — には、バインドマウントされたSQLite DBに対してplatform/scripts/dump_chats.pyを実行し、メッセージごとのフラグ検出チップを備えた自己完結型HTMLレポートを生成する。これらは部分文字列の一致であり、アシスタントが秘密を開示した、またはツールを実行した証拠ではない。ガイド付きレッスンは独自の検証済み完了記録を保持している。
デフォルトのctf_log.htmlエクスポート、ランタイムデータ、ローカル環境ファイル、リリースアーカイブはGitによって無視される。カスタム名のエクスポートとデプロイメントバックアップは、チェックアウトの外側または無視されるplatform/data/ディレクトリに保管すること。プレイヤー記録、認証情報、チャットエクスポートは非公開にしておくべきである。
MIT。LICENSEを参照。
Rob Fuller (mubix)がハンズオンAIセキュリティトレーニングのために作成。コードは大部分がAI生成。設計上の決定とコンテンツは人間が所有する。