🦆

「見えないプロンプトインジェクション」ってなに

2025/02/07に公開

なぜ作成したのか

  • 新たな脅威の知見を広めたい

参考

「見えないプロンプトインジェクション」でLLMの出力が操作される手口を解説
https://www.trendmicro.com/ja_jp/research/25/b/invisible-prompt-injection-secure-ai.html

probe for invisible text prompt injections(概念実証)
https://github.com/NVIDIA/garak/pull/397


1. 背景:LLM(大規模言語モデル)のプロンプト構造

現代の言語モデル(ChatGPT など)は、複数の層に分かれたプロンプトをもとに動作しています。一般的には以下のような構成です。

  • システムプロンプト
    → モデル全体の動作や倫理的な制約など、開発者や運営者側が設定する隠れた指示。

  • ユーザープロンプト
    → ユーザーが入力する質問や依頼のテキスト。

  • 補助的な指示や会話履歴
    → 前後の文脈や追加指示など。

この構造により、システムは安全性や品質の高い回答を提供するよう設計されていますが、ユーザー入力とシステムプロンプトが単純に連結される場合、悪意あるユーザーが入力に隠れた指示を含めると、システムプロンプトの上書きや回避が起こる可能性があります。


2. 見えないプロンプトインジェクションとは

見えないプロンプトインジェクションは、攻撃者が「ユーザー入力」の中に人の目に見えない文字やフォーマット(例:ゼロ幅スペース、非表示文字、方向制御文字など)を用いて、本来表示されるべきではない隠れたコマンドや指示を埋め込む手法です。

Unicode の符号位置の悪用

  • Unicodeでタグに分類される符号位置(E0000~E007F)を用いた指示文は、UI上では表示されません。
  • さらにこれらの符号位置を生成することは容易であるほか、ASCII文字で構成された元の文章の内容を保持できることからプロンプトインジェクションの手口に広く用いられています。
  • Unicodeにおいてこれらの文字集合は、主にメタデータのタグ付けやアノテーション(特定のデータに対するメタデータの付与)に用いられるために設計されています。

Tagに分類される Unicode

  • Unicodeにおいてタグ(Tags)に分類される範囲はE0000からE007Fまでです。
  • また、自然言語に用いられるASCII文字(英字、数字、一般句読点)に分類される範囲は0000から007Fまでです。
  • ASCII文字を用いて作成された文章の各文字にそれぞれの符号位置を割り当て、「E0000」を追加することで、タグに分類される「UI上では表示されない符号位置」に変換することができます
  • 例:ASCII文字の「a」は符号位置では「U+0061」 → タグ付けされた「a」の符号位置は「U+E0061」)
  • 従って、E0000を追加するための数行のコードを用いることで、悪意のある指示文をUI上に表示させないようにできることから、簡単に悪用される可能性があります。

攻撃の狙い

  • システムプロンプトの上書き・回避
    攻撃者は、隠れた命令によって、LLMに設定されている安全指示や倫理的制約を無視させることを狙います。
    一部のLLMは、タグ付けされた符号位置を解釈可能なトークン(文章を単語などに区切った単位)に分割する機能を備えています(例:「U+E0061」を「U+E」と「0061」に区切って解釈する)。これらのLLMが十分に訓練されていて、指示文がタグ付けされる前の元の内容を解釈できる場合、目に見えないプロンプトインジェクションに対して脆弱となる(学習した制約を無視する)可能性があります。

  • 意図しない出力の生成
    結果として、攻撃者の望む情報(場合によっては有害な内容)を出力させる、または制御を乗っ取る可能性があります。


3. 見えないプロンプトインジェクションの仕組み(図解)

以下は、攻撃がどのように仕組まれるかを示した概略図です。

flowchart TD
  A[攻撃者による入力作成<br>(例:通常の文章にゼロ幅文字等で隠れた指示を埋め込む)]
  B[ユーザーが入力するテキスト<br>(見た目は普通だが、内部に隠し命令が存在)]
  C[アプリケーション/チャットシステム<br>※ユーザー入力とシステムプロンプトを連結]
  D[統合プロンプト<br>・システムプロンプト:安全指示など<br>・ユーザープロンプト:通常の質問+隠れた命令]
  E[LLM (大規模言語モデル)<br>→ 隠れた命令を解釈し、本来の制約を回避した回答を生成]
  F[出力結果<br>(攻撃者の意図した内容が含まれる)]
  
  A --> B
  B --> C
  C --> D
  D --> E
  E --> F

図の各要素の説明

  1. 攻撃者による入力作成

    • 攻撃者は、見た目上は通常の文章として成立するテキスト内に、ゼロ幅スペースなどの非表示文字を用いて隠し命令を埋め込みます。
  2. ユーザーが入力するテキスト

    • システムや他のユーザーには通常の文章として表示され、隠し命令は見えません。
  3. アプリケーション/チャットシステム

    • 多くのシステムでは、ユーザー入力とシステムプロンプトを単純に連結してLLMに渡す処理が行われています。この段階で、隠し命令がシステムプロンプトと一体化してしまいます。
  4. LLM

    • LLMは連結されたプロンプト全体をそのまま解釈するため、見えない命令も含めた全内容を考慮して回答を生成します。結果として、本来守られるべき安全指示が上書きされる可能性があります。
  5. 出力結果

    • 攻撃者の意図した、通常は発生しないはずの出力や情報が返される場合があります。

4. 防御策と今後の課題

対策として考えられる主な手法は以下の通りです。

  • 入力のサニタイズ/バリデーション

    • ユーザーからの入力に含まれる非表示文字や不審な文字列を検出・除去する。
  • プロンプトの分離

    • システムプロンプトとユーザー入力を厳密に分離し、連結する際の処理方法に注意を払う。
  • ホワイトリスト方式

    • ユーザー入力で許容する文字や形式を限定する。
  • 動的検知・防御システムの導入

    • 入力内容の不正なパターンを検知する仕組みの導入や、モデル出力の後処理でリスクを評価する。

今後の課題として、
攻撃手法自体が日々進化しており、完全な防御は困難です。特に、**「見えない」**という特性ゆえに、人間側からは容易に気づかないという問題もあり、より高度な対策が求められます。


所感

  • 単一のLLMが返す回答のみを正としている限り、人の認知可能性の幅でしか検知できない制限になるのだろうな、と感じる。
  • 生成、評価、検証くらいの、3つの独立したLLMで均衡を作るくらいがちょうどよい気がする
GitHubで編集を提案

Discussion