
JAWS-UG神戸 #12 CTFにKiroと参戦してみた —事前準備とCloudTrail配信ログのローカル集約が効いた話
はじめに
2026年6月13日に開催された【JAWS-UG神戸 #12】CTF Game大会に、AIエージェントのKiro CLIと一緒にオンライン参加しました。
このCTFは「アクセスキーが流出した『てい』で遊んでみよう」というテーマで、運営のkazzpapa3さんが実際のアクセスキー流出インシデント対応で得た知見をもとに作問されたものです。クレデンシャル漏洩を起点に、攻撃者が何をしたのかを追いかけ、インシデント対応の難しさを体験する構成でした。個人対戦・早い者勝ちで、ヒントを使うと減点される設計です。
私は先日、Security-JAWSの10周年記念CTF「Cloud Vault」にもKiro CLIと参戦しています。今回はその続きという位置づけです。
CTFは再演の可能性が案内されており、運営からも正答・ヒント・考え方やスクリーンショットの公開を控えるようお願いがありました。本記事ではフラグや具体的な解法手順には一切触れず、AIエージェントとの協業や事前準備、そしてAWSセキュリティの学びにフォーカスして書きます。
結果
序盤から中盤にかけてのスコア推移です。ユーザー名と他の参加者はマスクしています。

スコアボード上で確認できた範囲では、序盤から中盤はトップペースで推移し、立ち上がりから10分ほどで一時トップに立ちました。ただし最終課題で足踏みし、最後まで走り切れませんでした。詳細は次の表のとおりです。
| 指標 | 値 |
|---|---|
| 最高スコア | 7,050点 |
| スコア推移 | 立ち上がりから約10分で約7,000点に到達、一時トップ |
| 最終順位 | 10位前後 |
| ヒント使用 | 1回(−100点) |
AIエージェント(Kiro CLI)の活用
序盤は「人間が判断し、Kiro CLIが実行する」という分業体制で臨みました。問題文をKiro CLIに渡し、調査やAWS CLI操作はKiro CLIが担い、人間は方針の決定と結果の解釈に集中する流れです。
CTF開始直後は人間も手元で並行してAWSリソースを確認し、Kiro CLIの出力をクロスチェックしました。傾向がつかめた後は、Kiro CLIに解釈や方針立案も含めて委任する範囲を広げ、問題文を渡すとKiro CLIが調査方針を組み立てて進め、人間は要所の確認に回る形に切り替えました。
事前準備で効いたこと
今回いちばん効いたのは、問題を解くプロンプトそのものではなく、効率よく調べるための仕組みを事前に用意していたことでした。
サービス別の調査ツール
アクセスキー流出を起点としたインシデント調査では、IAM・S3・Lambda・EC2・RDS・Secrets Manager・CloudTrailなど、確認すべきサービスが多岐にわたります。そこで、サービスごとにディレクトリを切り、初動の偵察を定型化した recon.sh を用意しておきました。
たとえば最初に確認したいのは「自分が誰で、何ができるのか」です。配布されたアクセスキーの権限を洗い出すことで、調査すべきサービスの当たりをつけられます。こうした定番の確認を、その場でコマンドを思い出しながら打つのではなく、あらかじめスクリプト化しておくことで初動が速くなりました。
CTF専用のサブエージェント
調査を分担させるため、CTF専用のサブエージェントを複数定義しておきました。各エージェントは担当サービスを調べ、結果を各ディレクトリの findings.md に都度書き出します。さらに、全体を統括するリード役のエージェントが各 findings.md を巡回して progress.md に集約し、次に調べるべき対象とコマンドを提示する役割を担いました。
ヘッドレスで呼び出すためのラッパーを用意し、次のように担当タスクを渡して並行実行できるようにしていました。
./run-agent.sh ctf-recon "全サービスを偵察して findings.md に記録して"
発見した情報を findings.md と progress.md に集約していく運用は、調査の取りこぼしを防ぎ、仮にセッションを切り替えても状況を引き継げる利点がありました。
CloudTrailの配信済みログをローカルへ集約する
今回の調査でもっとも効果を発揮したのが、CloudTrailの配信ログを最初にまとめてローカルへ集約してしまう方法です。
CloudTrailの調査というと、aws cloudtrail lookup-events で必要なイベントを都度引く方法が思い浮かびます。ただし LookupEvents には制約があります。AWS公式ドキュメントによると、取得できるのは管理イベントとInsightsイベントで、1回の応答、つまり1ページあたり最大50件です。NextToken によるページングは可能ですが、レートは1アカウント・1リージョンあたり毎秒2リクエストに制限されています。S3のオブジェクト操作などのデータイベントは対象外です。
そこで今回は、S3に配信済みのCloudTrailログを最初にまとめてローカルへ取得し、以降はローカルのファイルに対して jq で何度でも検索する方針にしました。流れは次の3ステップです。
# 1. 対象プレフィックス配下のCloudTrail配信ログをローカルへ同期
aws s3 sync "s3://<trail-bucket>/AWSLogs/" ./trail-logs/
# 2. gzipを展開
find ./trail-logs -name "*.json.gz" -exec gunzip -f {} \;
# 3. 取得したログ内の全レコードを時系列でソートし1ファイルに統合
find ./trail-logs -name "*.json" -exec cat {} + | \
jq -s '[.[].Records[]] | sort_by(.eventTime)' > all_events.json
統合した all_events.json ができてしまえば、あとはローカルの jq で自在に切り出せます。イベント名の集計、ユーザーやアクセスキーの一覧、エラー(権限不足や試行錯誤の痕跡など)の抽出、送信元IPの一覧、時系列の整形といった定番のクエリをスクリプトにまとめておきました。
この方式には、次のような利点がありました。
- 調査のたびに
LookupEventsを叩かないため、CloudTrail APIのレート制限を受けにくい - Trailで記録されS3に配信されているデータイベントであれば、
LookupEventsでは取れないものも配信ログから解析できる - 取得対象のプレフィックスに複数リージョン分のログが含まれていれば、リージョンをまたいでまとめて検索できる
前回のAthena調査との位置づけ
CloudTrailを LookupEvents で調べていて件数の上限に突き当たり、Athenaへ切り替えた経験を、以前ブログにしています。
今回はその延長で、AthenaやGlueを用意せず、対象プレフィックスに配信済みのログをローカルへ落として jq で調べる別ルートを取りました。
ただし万能な置き換えではありません。今回はCTFという、ログ量と期間が限定された環境だったため、対象ログをまとめて取得するのが現実的でした。本番環境で大容量・長期間のログを扱う場合は、スキャン範囲をパーティションで絞ったAthenaのほうが適しています。ログの規模に応じて使い分けるのがよいと考えています。
モデル選定について
今回はKiro CLIのモデルにSonnet 4.6を指定して臨みました。回答の速度を上げ、安定した出力を得ることを優先した判断です。
また、ツール実行のたびの確認で手が止まらないよう、kiro-cli chat -a(Trust All Tools active, confirmations are off)で起動し、ツール実行時の確認を省略して動かしました。
なお、今回のようにツール実行確認を省略し、Kiro CLIに広めに操作を任せたのは、隔離されたCTF環境に限った判断です。通常のAWS環境では、最小権限・ガードレール・監査を前提にすべきです。
最終課題で足踏みしたこと
結果に書いたとおり、最終課題では回答が受理されず、最後まで走り切れませんでした。提出フォーマット、とくに回答内容の配列の記述あたりが関係しているようにも見えましたが、確たる原因は最後まで特定できていません。
最終的にはヒントを使い、−100点で順位を落としました。AIと組んで速く走れても、提出時のすれ違いは外から原因を切り分けるのが難しい、という体験になりました。ここはAIの有無にかかわらず、悩みやすい場面だったように思います。
AWSセキュリティの学び
攻撃シナリオを追いかけたあとに、守る側として痕跡を追う、という体験を通じて学べた原則を整理します。
| 原則 | CTFで学べたこと |
|---|---|
| 権限管理 | アクセスキー1つの流出が、その後の広い操作につながる |
| シークレット管理 | 認証情報の管理と、漏洩時の影響範囲の把握が要になる |
| データ保護 | データには想定外の持ち出し経路がありうる |
| ログ監査 | CloudTrailは事後の追跡で決定的な役割を果たす |
| AIと最小権限 | AIエージェントにも最小権限と隔離が必要 |
ネットワーク境界だけでなく、IAMによる権限設計とAPIレベルの認可が重要な防御線になることを、あらためて実感しました。そして、攻撃が成立したあとでもCloudTrailにイベントが残っていれば、「どの主体が、いつ、どのAPI操作を行ったか」を追跡する重要な手がかりになります。この追跡可能性の大きさを体験できました。事後にたどれることは、インシデント対応における安心材料です。
まとめ
JAWS-UG神戸 #12のCTFにKiro CLIと参戦しました。スコアボード上で確認できた範囲では、序盤から中盤をトップペースで進められました。その要因は、Kiro CLIによる高速なCLI操作・調査だけでなく、サービス別の調査ツール、CTF専用サブエージェント、CloudTrail配信ログをローカルに集約して jq で調べる仕組みを事前に用意していたことにあります。
一方で、最終課題では回答が通らず、ヒント減点で順位を落としました。AIと組むことで調査の速度は上げられても、提出フォーマットや判定とのすれ違いのような場面では詰まることもある、という両面を持ち帰った形です。
アクセスキー流出を起点に、攻撃と防御の双方を追体験できる、学びの多いCTFでした。再演の機会があれば、ぜひ参加してみてください。







