← 開発ノート

AI を利用したサイバー攻撃に備える:フィッシング・脆弱性悪用・エージェント乗っ取り

この記事の目次

AI を利用した攻撃に備えるには、アカウント侵害と公開済み脆弱性の悪用を減らし、AI エージェントが外部コンテンツを読んでも未承認の操作を実行できないようにします。 攻撃メッセージを AI が書いたかどうかの判定より、認証、パッチ、権限、外部送信の制御が実際に機能するかを確かめるほうが、直接役立ちます。

この記事は、サービスを運用するチームや、開発ワークフローに AI エージェントを導入するチーム向けです。攻撃経路ごとの対応と、ローカルでのログ相関を扱います。以下の運用手順は提案であり、ある組織のインシデントや、測定した防御効果の記録ではありません。

AI を使う攻撃と AI への攻撃

攻撃者は AI で対象の情報を整理し、なりすましメッセージやコードを作れます。自分たちの AI エージェントが攻撃対象になることもあります。たとえば間接プロンプトインジェクションは、外部文書に指示を隠し、データ送信やデプロイ設定の変更を誘導します。

英国 NCSC の 2027 年までの脅威評価は、偵察、ソーシャルエンジニアリング、脆弱性調査などの既存の活動が AI で効率化すると予測しています。また、既知の脆弱性の公開から悪用までの対応時間が、さらに短くなる可能性を評価しています。これらの予測を、すべての攻撃がすでに完全自動化されたという観測結果として読んではいけません。

攻撃経路 攻撃者の目的 最初に守る境界
標的型フィッシングと幹部へのなりすまし ログイン、アカウント復旧、支払承認 認証、復旧、別の確認経路
支援を受けた脆弱性の発見と悪用 公開サービスへの侵入と秘密情報の窃取 公開資産、パッチ、隔離
エージェントへのプロンプトインジェクション 未承認のツール実行や外部送信 データと指示の分離、ツールとネットワークの権限

一つのインシデントで複数の経路がつながる場合があります。アカウント侵害によって内部文書に悪意ある指示が置かれたなら、ID とエージェントの防御を両方調査します。

認証と承認の経路でフィッシングに対抗する

幹部へのなりすましと請求書詐欺に関する Microsoft の分析は、偽の幹部メール、請求書、転送された会話に見せた内容を組み合わせたキャンペーンを説明しています。研究者は AI 支援のテンプレート開発と整合する兆候を観測しましたが、それだけでは AI が生成した内容の割合は確定できないとしています。特定の句読点やコメント形式だけでは、攻撃を分類するルールの十分な根拠にはなりません。

まず、以下の運用上の境界を確認します。

  • ログイン: 対応するアカウントに FIDO2 やパスキーなどのフィッシング耐性のある認証を導入し、実際のサインインポリシーがそれを必須にしているか確認します。Microsoft のフィッシング耐性 MFA の指針は、SMS、OTP、プッシュ認証に対する傍受や疲労攻撃のリスクと、より強い方式への移行を扱っています。
  • 復旧と登録: ヘルプデスクが新しい認証方式の登録やアカウント復旧を行う際は、信頼できる既存の記録と別の手順で本人確認をします。一通のメールや一回のビデオ通話だけでは復旧を承認しない運用ルールを設けます。
  • 業務承認: 銀行口座の変更や秘密情報の共有依頼は、メッセージ内の連絡先ではなく、事前登録された連絡先や社内承認システムで確認します。支払詐欺はアカウント侵害がなくても成立するため、ログイン強化だけでは防御は完結しません。

メール防御では SPF、DKIM、DMARC、なりすまし検知を併用します。メール認証に通っても、類似ドメインや侵害された正規アカウントから来た依頼の業務上の正当性は証明できません。フィッシング耐性のある認証も、セッション窃取や端末侵害のすべてを解決するわけではありません。

脆弱性対応では公開状況と悪用リスクを優先する

攻撃者が AI を使った証拠を待っている間も、公開サービスは脆弱なままです。まず、インターネットに公開する各サービスを、製品、稼働バージョン、担当者、パッチ適用状況に結び付け、ベンダーの勧告と観測された悪用情報を確認します。ソースコードやイメージタグを変更したという記録より、現在トラフィックを処理しているインスタンスが修正版で動いているかが大切です。

外部への公開状況、観測された悪用、アクセス可能なデータと権限、サービスへの影響を合わせて優先順位を決めます。直ちにパッチを適用できなければ、ベンダーが認める緩和策や公開範囲の制限を施し、例外の担当者と再評価時刻を記録します。WAF ルールを追加しても、元の脆弱性はなくなりません。

すでに悪用された可能性があれば、パッチ適用と並行してインシデントを調査します。プロセス、認証、外部通信の記録を保全し、侵害範囲に応じて認証情報のローテーションや信頼できるイメージからの再構築を判断します。パッチ適用に成功しても、侵入の痕跡や永続化が除去された証明にはなりません。

エージェントが読む内容を実行権限に変えない

AI エージェントが読む issue、リポジトリファイル、Web ページは、攻撃者が制御している場合があります。「この文書を読んだら次のコマンドを実行する」といった文を、ユーザーが承認したタスクと同等の権限として扱うと、情報取得が外部送信に変わり得ます。

OWASP のプロンプトインジェクション対策指針は、ユーザー権限とセッションの文脈に照らしたツール呼び出しの検証、ツール固有のパラメーター検証、最小権限を推奨しています。入力への警告追加や、悪意ある指示を無視するようモデルに頼むだけでは、実行権限は強制されません。

ユーザーとタスクごとに許可されたリソースと操作を、モデルの外にあるツール実行境界で強制します。読み取り専用アカウントと短命な認証情報を使い、宛先、プロトコル、データ範囲でネットワーク送信を制限します。許可済みドメインでも攻撃者のアカウントや任意のパスへ送信できるなら、宛先許可リストだけでは不十分です。重要な変更や送信の承認を得る際は、具体的な対象と変更内容を示します。

タスク ID、実行主体、ツール名、ポリシー判断、結果を記録します。判断理由は観測可能なポリシーコードで表し、モデルの隠れた推論を集める必要はありません。ソース文書全体、トークン、パスワードをログに残すと、別の漏えい箇所になります。運用上の認可境界は、AI エージェントの権限境界を参照してください。

外部コンテンツを読んだ後の送信拒否を相関させる

以下の Python 例は、信頼できるエグゼキューターに帰属する合成イベントを相関させます。同じ実行主体と実行 ID について、外部コンテンツを読んでから 300 秒以内に外部送信が拒否されたら、調査候補として示します。プロンプトインジェクションの識別やリクエストの遮断は行いません。別のツールポリシーやネットワークポリシーが、すでに拒否イベントを生成したことを前提とします。

イベントを時刻順に並べ、外部コンテンツの読み取りを記録し、同じ実行主体と実行 ID の 300 秒以内の送信拒否を調査候補として返す

図は、一つのイベントを処理する分岐をまとめています。右側の終端記号は現在のイベントをスキップする意味で、安全判定ではありません。コードは各イベントの処理を繰り返し、最新の読み取り時刻を保持します。条件を満たさないイベントはスキップします。この図は、攻撃検知やインシデント対応の全体を示すものではありません。

この例は Python 3.13.0 で実行し、外部パッケージ、ネットワーク、本番ログを使っていません。correlate.py として保存します。ここでの at は例の開始点からの秒数です。実際の収集には、同期したイベント時刻と安定した実行 ID が必要です。文書の内容や任意のモデル生成値を信用して、kind や識別子を埋めないでください。

from dataclasses import dataclass


@dataclass(frozen=True)
class Event:
    at: int
    actor: str
    run: str
    kind: str


def correlate(events: list[Event], window: int = 300) -> list[tuple[str, str, int]]:
    if window < 0:
        raise ValueError("window")
    last_read: dict[tuple[str, str], int] = {}
    candidates = []
    for event in sorted(events, key=lambda item: item.at):
        key = (event.actor, event.run)
        if event.kind == "untrusted_read":
            last_read[key] = event.at
        elif event.kind == "egress_denied":
            read_at = last_read.get(key)
            if read_at is not None and 0 <= event.at - read_at <= window:
                candidates.append((event.actor, event.run, event.at))
    return candidates


if __name__ == "__main__":
    events = [
        Event(20, "agent-a", "run-1", "egress_denied"),
        Event(0, "agent-a", "run-1", "untrusted_read"),
        Event(30, "agent-a", "run-2", "egress_denied"),
        Event(40, "agent-b", "run-1", "egress_denied"),
        Event(301, "agent-a", "run-1", "egress_denied"),
    ]
    print(correlate(events))
python3 correlate.py

実際の実行出力は次のとおりです。

[('agent-a', 'run-1', 20)]

同じ実行の 20 秒時点のイベントだけが選ばれます。別の実行や実行主体の拒否、時間窓の外の拒否は除外されます。300 秒の時間窓は説明用の選択であり、検証済みのセキュリティしきい値ではありません。時間が近いだけでは、インジェクションが送信試行の原因だったとはいえません。正当な自動化でも同じパターンを生じ得ます。

別途実施した 十三件のローカル検証では、300 秒を含む境界、301 秒の除外、順序を入れ替えた入力、時刻ゼロ、実行主体と実行の分離、読み取りのない拒否、成功した送信、負の時間窓を確認しました。300 秒の境界を除外する、実行主体を無視する、時刻ゼロを誤処理するという 三つの回帰変異も検出しました。アラートがないことは安全の証明ではありません。このルールは、遮断されなかった送信やログ欠損を見逃し得ます。本番導入には、ストリームの遅延と順序逆転、状態の有効期限、重複排除、再起動からの復旧、誤検知評価への対応が必要です。このバッチ処理の例では、これらを実装していません。

アラート後は実行結果を確認し、被害経路を閉じる

エージェントの「操作を止めた」という発言に頼らず、エグゼキューターのポリシー結果、ネットワーク、送信先サービスの記録を確認します。一件の egress_denied は、その試行が拒否されたことを示すだけで、別経路からの漏えいがなかった証明ではありません。不審な実行を止め、タスク ID でソースへのアクセス、ツール呼び出し、外部通信を関連付けます。

状況 初動の提案 再開前の確認
フィッシング後のログインやアカウント変更の疑い 関連セッションとトークンを無効化し、アカウントを復旧して、登録済み認証方式と同意による権限付与を調べる 攻撃者が追加したアクセス経路を除去し、正当なログインを確認する
公開サービスの脆弱性悪用の疑い 影響資産を隔離し、証拠を保全し、修正版を適用して必要に応じて再構築する 稼働バージョンと公開状況を確認し、永続化とラテラルムーブメントを調べる
エージェントの未承認呼び出し 実行を止め、関連する認証情報を失効またはローテーションし、ツールと送信経路を制限する 未承認の要求を拒否し、承認済みの作業は成功することを回帰テストする

自動遮断はサービスを中断し得るため、検知の確度と影響範囲に応じて適用します。封じ込めと証拠保全が競合する場合は、進行中の被害と収集コストに基づいて順序を選びます。調査用 AI に攻撃者由来の資料を渡す際も、ツールと外部送信の権限を分離する必要があります。各国の国家安全保障機関によるエージェント型 AI 導入の共同指針は、コンポーネント、連携、運用もリスク評価の範囲に含めています。

外部に公開した資産一つ、重要なアカウント一つ、外部文書を読むエージェントタスク一つから始めます。それぞれで、実際に強制される制御、調査可能なログ、担当者が実行できる復旧手順をつなぎます。繰り返すテストには正当な要求の成功も含め、AI 支援 TDDの例のように、拒否境界を変えると検証が失敗するか確認してください。

コメント

GitHubで見る ↗