【AWS re:Invent 2025】GameDayでセキュリティ攻撃を受け、その場で対策を打つ体験をしてきた

【AWS re:Invent 2025】GameDayでセキュリティ攻撃を受け、その場で対策を打つ体験をしてきた

2025.12.14

目次

  1. なぜこのGameDayに参加したのか
  2. 実際に受けた攻撃と対応
  3. まとめ:誰に推奨するか

なぜこのGameDayに参加したのか

AWS re:Invent 2025でSecurity Battle RoyaleというGameDayイベントに参加してきました。

結果は3位でした!!!

スクリーンショット 2025-12-14 085506

GameDayとは

このイベントは、架空の会社「Unicorn.Rentals」の新入社員という設定で、実際に攻撃を受けながらセキュリティ対策を実装する競技です。

ルール

  • アプリケーションが稼働している間はポイントが加算される
  • 他チームへの攻撃が成功するとポイント獲得
  • 攻撃を受けて被害を受けるとポイント減点
  • チーム間でアライアンス(同盟)を結べる
  • ダウンタイムが長引くと減点が続く

チーム構成

各チームは攻撃担当防御担当に分かれて競技に臨みます。私は防御側を担当し、自分たちのシステムを守ることに専念しました。このブログでは、防御側として実際に受けた攻撃と、それに対する対応について記載します。

参加した理由

正直なところ、セキュリティは「知識として知っている」ことと「実際に対応できる」ことの間に大きなギャップがあると感じていました。

  • SQLインジェクションの仕組みは知っているが、実際のコードでどう防ぐのか
  • 「アクセスキーを盗まれた」というインシデントにどう対応するのか
  • S3バケットポリシーの設定ミスで何が起きるのか

このGameDayでは、これらの「実際に手を動かす経験」を得ることができました。

実際に受けた攻撃と対応

イベント中、私たちのチームは8種類の攻撃を受けました。その中でも特に印象に残った攻撃と、実際に実装した対策について書いていきます。

1. SQLインジェクション攻撃

攻撃内容

最初に受けた攻撃がSQLインジェクションでした。ユーザー検索やログイン機能に対して、悪意のある入力が送り込まれてきました。

' OR '1'='1
' UNION SELECT * FROM users --

対応策

すべてのDB操作でパラメータ化クエリを実装しました。


# 修正前(脆弱なコード)
query = f"SELECT * FROM users WHERE id = '{user_id}'"

# 修正後(安全なコード)
query = "SELECT * FROM users WHERE id= %s"
cursor.execute(query, (user_id,))

プレースホルダ(%s)を使用することで、ユーザー入力がSQL文として解釈されることを防止しています。

2. SSRF(Server-Side Request Forgery)攻撃

攻撃内容

プロキシエンドポイントを悪用して、EC2インスタンスのメタデータサービス(169.254.169.254)にアクセスしようとする攻撃がありました。これが成功すると、IAMロールの一時的な認証情報が盗まれてしまいます。

対応策

プロキシエンドポイントに以下の保護機能を実装しました。

def is_safe_url(url):
    # メタデータサービスへのアクセスをブロック
    if '169.254.169.254' in url:
        return False
    # ローカルホストアクセスを拒否
    if 'localhost' in url or '127.0.0.1' in url:
        return False
    return True

この対策により、内部ネットワークへの不正アクセスを防ぐことができました。

3. 認証情報の漏洩

インシデント

イベント中に、開発者のアクセスキーが盗まれたことが分かりました。CloudTrailのログを確認すると、不審なAPIコールが記録されていました。

緊急対応

即座に以下の対応を実施しました。

  1. 盗まれたアクセスキーの無効化

    • Developer1からDeveloper5までの全アクセスキーを確認
    • 5つのキー(AKIA...で始まる)をすべてInactiveに設定
    • 新しいキーを発行して、正規の開発者に配布
  2. IAM権限の制限

    • RestrictedS3WebsitePolicyという新しいポリシーを作成
    • S3への読み取り専用アクセス(GetObject, ListBucket)のみ許可
    • 削除操作を明示的に拒否(DeleteObject, DeleteBucket, PutBucketPolicy)
    • すべての開発者アカウントに適用
{
  "Effect": "Deny",
  "Action": [
    "s3:DeleteObject",
    "s3:DeleteBucket",
    "s3:PutBucketPolicy"
  ],
  "Resource": "*"
}

4. S3バケットへの攻撃

攻撃内容

最も深刻だったのがS3バケットへの攻撃でした。設定ミスのあるバケットポリシーを悪用して、Webサイトのファイルを削除しようとする攻撃がありました。

初期状態の問題点

{
  "Principal": "*",
  "Action": ["s3:GetObject", "s3:ListBucket"]
}

すべてのプリンシパル(*)にアクセスを許可していました。

実施した対策

  1. バケットポリシーの制限

    • CloudFrontのみからのアクセスに制限
    • OAI(Origin Access Identity)を使用
  2. PublicAccessBlockの有効化

    • BlockPublicAcls: True
    • IgnorePublicAcls: True
    • BlockPublicPolicy: True
    • RestrictPublicBuckets: True
  3. バージョニングの有効化

    • 誤削除や改ざんからの復元に対応
    • 侵害時のロールバックが可能に

5. インフラストラクチャのセキュリティ強化

攻撃に対応しながら、同時にインフラ全体のセキュリティも強化していきました。

実施内容

  • IAMロール設定: EC2インスタンスプロファイルを適用し、認証情報のハードコーディングを排除
  • セキュリティグループ設定: EC2 ↔ RDS間の通信を必要最小限に制限
  • Secrets Manager統合: DatabasePasswordSecretからパスワードを動的に取得
import boto3
import json

def get_database_password():
    client = boto3.client('secretsmanager')
    response = client.get_secret_value(SecretId='DatabasePasswordSecret')
    secret = json.loads(response['SecretString'])
    return secret['password']

まとめ:誰に推奨するか

最終結果

144,330ポイント、3位という結果でした。

この経験から得たものは本当に大きかったです。

  • セキュリティは「完璧」を目指すのではなく、「継続的な改善」が重要
  • 失敗から学ぶことの価値
  • チームでのコミュニケーションの重要性

こんな人におすすめ

このGameDayは、以下のような方に特におすすめです。

1. セキュリティエンジニアを目指している方

  • 理論だけでなく、実際の攻撃対応を体験できます
  • インシデント対応のプロセスを学べます
  • 自分の弱点を発見できます

2. 開発者

  • 自分が書いたコードの脆弱性を理解できます
  • セキュアコーディングの実践的なスキルを習得できます
  • セキュリティチームとのコミュニケーション方法を学べます

3. アーキテクト

  • セキュアなアーキテクチャ設計の重要性を実感できます
  • 可用性とセキュリティのバランスを考える機会になります
  • AWSサービスのセキュリティ機能を実践的に理解できます

4. チームでスキルアップしたい方

  • プレッシャー下でのチーム協力を経験できます
  • インシデント対応での役割分担を学べます
  • 楽しみながら学習できます

最後に

AWS re:Invent 2026でも開催されるなら、ぜひ参加してみてください。教科書では学べない、実践的なセキュリティ経験が待っています。

失敗を恐れずに挑戦することで、真のセキュリティスキルが身につきます。このレポートが、皆さんの参加の後押しになれば幸いです。

この記事をシェアする

FacebookHatena blogX

関連記事