たきびAIラボ TAKIBI · AI · LAB
🛡️サイバーセキュリティ ハウツー 公開 2026.06.01

LLMjacking完全防御ガイド

AI API鍵の盗用・コスト爆発を引き起こす外部攻撃者への対策チェックリスト

Sysdigが報告した1日$46,000のコスト爆発事例を起点に、LLMjacking(外部攻撃者によるAI API鍵窃取・悪用)の経路・検知・短命クレデンシャル移行・異常利用アラート実装を実務チェックリスト形式で解説する。

読了 約19分
LLMjacking完全防御ガイド:AI API鍵の盗用・コスト爆発を引き起こす外部攻撃者への対策チェックリスト

ある日、OpenAI の請求ダッシュボードを開いたらコストが前日比で数十倍に跳ね上がっていた——そんな事態が、LLM API を利用するプロジェクトで現実に起きている。Sysdig の脅威リサーチチームが2024年5月に公表したレポートでは、外部攻撃者が盗んだクラウド認証情報を使って AI API を不正利用する「LLMjacking」と呼ばれる攻撃が観測され、被害者が負わされる推計コストは最大で1日あたり$46,000に達すると報告された。

LLMjacking は、API キーそのものやクラウドのサービスアカウント認証情報を窃取し、攻撃者が自分の目的(大量の推論リクエスト、プロキシ販売、jailbreak試行など)のために被害者のアカウントで課金を踏み倒す攻撃だ。Sysdig の報告では DeepSeek-R1 の公開翌日には盗んだ API キーを利用した悪用が始まっていたことも確認されている。OpenAI・Anthropic・AWS Bedrock・Azure OpenAI・Google Gemini をはじめ、ほぼすべての主要 LLM プロバイダが標的になり得る。

本記事が扱うのは、この外部攻撃者による API 鍵窃取という脅威ベクターへの防御だ。自社ユーザーの利用量制御(ゲートウェイのレート制限・PII 検出など)は LLMアプリのAPIゲートウェイ・セキュリティ設計 で扱っている。本記事では①鍵漏洩の主要経路の把握、②短命クレデンシャルへの移行、③異常利用の検知・アラート、④今すぐ実施できる棚卸しチェックリスト——の4ステップで防御を構築する手順を解説する。


LLMjacking とはどんな攻撃か

LLMjacking は「LLM + hijacking(乗っ取り)」の造語だ。攻撃者が 被害者のクラウド認証情報や API キーを窃取し、その鍵を使って大規模な LLM リクエストを投げる。被害者は課金だけを押しつけられ、攻撃者はコンピューティング資源をタダ乗りする。

Sysdig のレポートが明らかにしたのは、攻撃者が Anthropic・OpenAI・AWS Bedrock・Azure OpenAI・Vertex AI などを横断して複数プロバイダへのアクセスを確認するリバースプロキシツールを使っていた点だ。窃取した認証情報がどのサービスに対応するかを自動探索し、利用可能なモデルとアクセス権限を列挙してから大量の推論リクエストを行う。OWASP LLM Top 10 for LLMs 2025 では LLM10:2025「Unbounded Consumption(無制限の消費)」 として分類されており、クレデンシャル窃取を起点としたコスト爆発がリスクシナリオの一つに明記されている。

なぜ $46,000/日 という被害額になるのか

最新の大型モデルは、大量入出力トークンを処理させると1リクエストあたりのコストが数ドルになることもある。攻撃者が並列で何百・何千リクエストもさばかせれば、日次請求額は数十万円規模にあっという間に達する。加えて、LLM API には多くの場合デフォルトで支出上限が設定されておらず、プロバイダが異常を検知するまでの間、青天井で課金が積み上がる。


ステップ1:API 鍵が漏洩する5つの主要経路を把握する

防御の第一歩は「どこから鍵が漏れるのか」を理解することだ。実際の侵害事例を踏まえると、主な漏洩経路は次の5つに集約される。

経路1:Git リポジトリへの誤コミット

最も頻度が高い。.env ファイルや設定ファイルをそのままコミット、または git history に残ったままにしてしまうケースだ。

対策:

  • .gitignore.env*.pem*_key.json を追加する
  • git-secrets(AWS)または gitleaks をプレコミットフックとして導入し、コミット前にスキャンする
  • CI に trufflehog または gitleaks を組み込み、PRごとにシークレットスキャンを走らせる
  • すでにコミット済みの場合は git filter-repo で履歴から削除し、キーを即時ローテーションする
# gitleaks でリポジトリ全履歴をスキャン
gitleaks detect --source . --verbose

経路2:環境変数の平文保存とプロセスダンプ

export OPENAI_API_KEY=sk-....bashrc や Docker の ENV 命令に直書きすると、プロセス一覧(/proc/<pid>/environ)や Docker inspect から参照できてしまう場合がある。

対策:

  • アプリケーションランタイムには環境変数経由で渡すが、その値はシークレットマネージャから取得する形にする
  • AWS: SecretsManagerParameter Store(SecureString)
  • Azure: Key Vault
  • GCP: Secret Manager
  • Kubernetes: ExternalSecrets Operator で Secret を外部シークレットストアと同期する

経路3:ログへの誤出力

デバッグログに HTTP リクエストヘッダーをそのまま出力すると、Authorization: Bearer sk-... が平文でログストレージに記録される。ログを外部 SaaS(Datadog・Splunk など)に転送していれば、SaaS の認証が弱い場合に二次漏洩につながる。

対策:

  • ロギングライブラリにリダクション設定を入れ、Authorization ヘッダーをマスクする
  • 構造化ログ(JSON)の場合、secretkeytokenpassword を含むフィールド名を自動マスクする
import logging

class SensitiveDataFilter(logging.Filter):
    SENSITIVE_KEYS = {"authorization", "x-api-key", "token", "password"}

    def filter(self, record):
        if isinstance(record.msg, dict):
            for k in self.SENSITIVE_KEYS:
                if k in record.msg:
                    record.msg[k] = "***REDACTED***"
        return True

経路4:依存パッケージ・サプライチェーン経由

悪意のある npm / PyPI パッケージが環境変数を外部サーバに送信するコードを仕込んでいるケースがある。LLM API キーが環境変数に設定されていれば、その値も一緒に送信される。

対策:

  • lockfile(package-lock.jsonpoetry.lock)を使い、依存バージョンを固定する
  • CI で pip-auditnpm audittrivy を実行し、既知の悪意あるパッケージをブロックする
  • 依存パッケージの更新は Dependabot / Renovate で管理し、PRレビューを必須にする

経路5:SSRF 経由のクラウドメタデータ取得

Server-Side Request Forgery(SSRF)脆弱性があるアプリを EC2 や GCE 上で動かしている場合、攻撃者が http://169.254.169.254/latest/meta-data/iam/security-credentials/ にアクセスして一時認証情報(AccessKeyIdSecretAccessKeySessionToken)を取得できる。これで AWS Bedrock などへのアクセス権を得ることが可能だ。

対策:

  • IMDSv2 を強制する(EC2 の場合、HttpTokens=required を設定)
  • アプリのネットワーク層でリンクローカルアドレス(169.254.0.0/16)へのアウトバウンドをブロックする
  • SSRF 対策については WAF ルール(AWS WAF の SSRF マネージドルール等)も活用する

ステップ2:短命クレデンシャル(エフェメラル認証情報)への移行

長期有効な API キーは、一度漏れると無効化するまで攻撃者に使われ続ける。最善策は長期キーを使わない設計に移行することだ。

AWS Bedrock:IAM ロール + AssumeRole

EC2・ECS・Lambda などの AWS 環境であれば、インスタンスプロファイルまたはタスクロールを使うことで、アプリがコードに API キーを持たずに Bedrock へアクセスできる。

import boto3

# 環境にIAMロールが付与されていれば、認証情報は自動取得される
bedrock = boto3.client("bedrock-runtime", region_name="us-east-1")

response = bedrock.invoke_model(
    modelId="anthropic.claude-3-5-sonnet-20241022-v2:0",
    body=json.dumps({"messages": [...], "max_tokens": 1024}),
    contentType="application/json",
)

ポリシーは最小権限で構成する。bedrock:InvokeModel のみを許可し、特定のモデル ARN に絞るとリスクがさらに下がる。

{
  "Effect": "Allow",
  "Action": ["bedrock:InvokeModel"],
  "Resource": "arn:aws:bedrock:us-east-1::foundation-model/anthropic.claude-3-5-sonnet-20241022-v2:0"
}

Azure OpenAI:Managed Identity

Azure 環境では Managed Identity(システム割り当て・ユーザー割り当て)を使うことで、接続文字列に API キーを書かずに Azure OpenAI サービスを呼び出せる。

from azure.identity import DefaultAzureCredential
from openai import AzureOpenAI

credential = DefaultAzureCredential()

client = AzureOpenAI(
    azure_endpoint="https://<your-resource>.openai.azure.com",
    azure_ad_token_provider=lambda: credential.get_token(
        "https://cognitiveservices.azure.com/.default"
    ).token,
    api_version="2024-08-01-preview",
)

Managed Identity にはロールベースのアクセス制御(RBAC)で Cognitive Services OpenAI User ロールを割り当てる。Cognitive Services Contributor 以上の権限は最小権限の観点から避ける。

OpenAI / Anthropic を直接使う場合:シークレットマネージャから都度取得

これらのプロバイダには IAM ロール連携がないため、API キー自体は引き続き必要だが、アプリコードにハードコードせず、シークレットマネージャから起動時に取得し、メモリ内だけに保持する設計にする。

import boto3
import json
import openai

def get_openai_key() -> str:
    client = boto3.client("secretsmanager", region_name="us-east-1")
    secret = client.get_secret_value(SecretId="prod/openai/api_key")
    return json.loads(secret["SecretString"])["api_key"]

openai.api_key = get_openai_key()

キーのローテーションは定期的に(90日以内を目安)実施し、ローテーション前後で両方のキーを一時的に有効にしてから古いキーを削除する。


ステップ3:異常利用の検知とアラート設計

短命クレデンシャルへの移行は重要だが、既存の長期キーがすべて移行完了するまでの間や、万が一の漏洩に備えて異常利用の早期検知が不可欠だ。

AWS:CloudTrail + CloudWatch Alarm

AWS Bedrock のリクエストは CloudTrail に記録される。異常な呼び出しパターンを検知するために CloudWatch Metrics Filter を設定する。

警戒すべき CloudTrail イベント:

イベント名意味
InvokeModelBedrock モデルへのリクエスト(通常操作だが急増は異常)
DeleteModelInvocationLoggingConfigurationログ設定の削除(攻撃者が証跡を消そうとするサイン)
PutModelInvocationLoggingConfigurationログ設定の変更(転送先変更による隠蔽の可能性)
GetFoundationModelAvailability利用可能なモデルのスキャン(初期偵察に使われる)

DeleteModelInvocationLoggingConfiguration が検知された場合はただちにアラートを上げるべきだ。これは攻撃者が証拠を隠滅しようとする特徴的な行動として Sysdig のレポートでも指摘されている。

// CloudWatch Metric Filter の例
{
  "filterPattern": "{ $.eventName = \"DeleteModelInvocationLoggingConfiguration\" }",
  "metricName": "BedrockLoggingConfigDeleted",
  "metricNamespace": "LLMSecurityMonitor",
  "metricValue": "1"
}

コスト急増の検知には AWS Budgets でアラートを設定し、日次・月次の閾値を超えたら SNS 通知を飛ばす。LLM API は1リクエストのコストが大きいため、閾値は余裕を持ちすぎず通常使用の2〜3倍で即時アラートにするのが現実的だ。

Azure:Azure Monitor + Cost Alerts

Azure OpenAI の呼び出しは Azure Monitor の Metrics で追跡できる。TotalTokensSuccessfulRequests の急増をアラートに設定する。

  • Azure Cost Management から「コスト アラート」を設定し、予算の 80% / 100% で通知を飛ばす
  • Microsoft Defender for Cloud(旧 Azure Security Center)の「AI ワークロード保護」を有効にすると、異常なリクエストパターンを自動検知する

Datadog / 汎用 SIEM での横断監視

複数プロバイダを使っている場合は、各プロバイダのログを一元的に Datadog・Splunk・OpenSearch などに集約して横断監視する。

監視ダッシュボードで見るべき指標:

  • 1分あたりのリクエスト数(RPM):通常の3倍以上が10分以上続いたらアラート
  • 1時間あたりのトークン消費量:過去7日間の同時刻比で5倍超でアラート
  • 深夜・休日の高負荷:業務時間外の大量リクエストは特に要注意
  • 地理的に異常なアクセス元 IP:VPN・Tor・海外 IP からのアクセスは追加確認

ステップ4:今すぐ実施できる既存 API キーの棚卸しチェックリスト

理想的な設計への移行には時間がかかる。それまでの間にできる「今すぐやること」を優先順位順に整理した。

緊急(今日中)

  • OpenAI / Anthropic / GCP / AWS / Azure の管理コンソールで 発行済みの API キー一覧を確認し、不要なキーを削除する
  • 各プロバイダの請求・使用量ダッシュボードを開き、過去30日間の異常なスパイクがないか確認する
  • OpenAI は platform.openai.com/usage、Anthropic は console.anthropic.com でリアルタイム使用量を確認できる
  • GitHub / GitLab / Bitbucket でリポジトリに対して trufflehog または GitHub の「シークレットスキャン」機能を有効にする

今週中

  • AWS Budgets または Azure Cost Alerts を設定し、LLM 関連コストが通常の2倍を超えたら Slack / メール通知を受け取る
  • CloudTrail の Bedrock ログ を有効にし(デフォルトは有効だが設定を確認)、DeleteModelInvocationLoggingConfiguration イベントをアラート対象に追加する
  • 開発・ステージング環境で使っているキーが 本番と同じキーになっていないか確認し、環境ごとに別キーを発行する
  • gitleaks または trufflehog を CI パイプラインに追加する

今月中

  • AWS / Azure / GCP 環境は IAM ロール / Managed Identity への移行を計画し、長期キーを段階的に廃止する
  • OpenAI / Anthropic など IAM 連携のないプロバイダのキーを AWS Secrets Manager / Azure Key Vault に移す
  • 全キーに 90日ローテーションポリシーを設定し、手動確認ではなく自動ローテーションを仕組みに組み込む
  • チームメンバーへの API キー共有を禁止し、個人単位でのキー発行(サービスアカウント分離)を原則とする

関連記事


FAQ

LLMjacking 対策 よくある質問

AI API鍵のセキュリティについてよく寄せられる疑問に答える

LLMjacking に気づかないまま数日間放置してしまったらどうなりますか?

プロバイダが異常を検知するか、月次請求のタイミングで初めて気づくケースが多い。数日放置すると請求額が数百万円規模になることもある。OpenAI は異常なトラフィックを検知した場合にアカウントを一時停止することがあるが、その前に青天井で課金が積み上がることもある。検知の仕組み(予算アラート・CloudTrail 監視)を事前に設定しておくことが最も重要だ。

OpenAI / Anthropic の API キーには支出上限を設定できますか?

OpenAI は platform.openai.com のダッシュボードから「Usage limits」で月次のハードリミットを設定できる。上限に達すると API が 429 エラーを返し、サービスは止まるが課金は止まる。Anthropic も Console でソフト・ハードリミットを設定できる。AWS Bedrock は AWS Budgets で通知は出せるが自動停止はできないため、Lambda + EventBridge でキーを無効化する仕組みを別途作る必要がある。

GitHub にコミットしてしまった API キーは削除すれば大丈夫ですか?

大丈夫ではない。GitHub はコミット後数秒以内にシークレットをスキャンするボットが常時稼働しており、コミット履歴から削除しても既にキーが取得されている可能性が高い。ファイルの削除・履歴の書き換えとあわせて、キーを必ず即時無効化(revoke)して新しいキーを再発行することが必須だ。

IAM ロールを使えば API キーは完全に不要になりますか?

AWS Bedrock・Azure OpenAI・Vertex AI(Google)などのクラウドプロバイダが提供する LLM サービスについては、IAM ロール / Managed Identity を使うことで API キーを不要にできる。一方、OpenAI・Anthropic・その他の独立系プロバイダは IAM 連携を提供していないため、引き続き API キーが必要になる。その場合はシークレットマネージャに格納し、短いローテーションサイクルを維持することが次善策となる。

OWASP LLM10:2025「Unbounded Consumption」と LLMjacking はどう違いますか?

OWASP LLM10:2025 は「LLM の資源が過剰に消費されるリスク」全体を定義するカテゴリで、DoS 的なリクエスト洪水・過大な推論コストなど複数のシナリオを含む。LLMjacking はその中の一シナリオ——「外部攻撃者が盗んだ認証情報で LLM API を不正利用する」——に特化した実際の攻撃手法だ。OWASP LLM10 の対策(コスト上限・レート制限・請求アラート)は LLMjacking 防御に直接役立つ。


参考リンク


次に読むおすすめ

記事テーマに合わせて選んだ独自コンテンツです(note)。

【2026年最新】主要AIツール5つに自腹課金して徹底比較!生産性が劇的に変わる「用途別・最強の1つ」の選び方

LLM API の選定から実務活用まで、OpenAI・Anthropic・Google の主要モデルを実際に課金して比較した記事。セキュリティ設計と並行して「どのプロバイダ・モデルを使うか」の判断材料として役立てられる。

noteで続きを読む