【入門編】 LLM02: Insecure Output Handlingの防止策 – ガバナンス・リスク管理 & 生成AIセキュリティ防御ガイド

こんにちは!日々、システムの開発や運用で汗を流している新人のIT担当者や、セキュリティの勉強を始めたばかりの皆さん、お疲れ様です。

AI(生成AIやLLM)の技術って、本当にすごいですよね。「こんな文章を作って」「このプログラムのバグを見つけて」とお願いするだけで、まるで優秀なアシスタントのように瞬時に返事をしてくれます。最近のシステム開発でも、AIの力を借りるのが当たり前になってきました。

でも、ちょっと待ってください。「AIが言うことだから、きっと大丈夫だろう」と、その出力結果をそのまま信じて、自分のパソコンや会社のシステムで実行していませんか?

実はそこ、サイバー攻撃者が一番狙っている「危うい盲点」なんです。

今回は、生成AIの出力が引き起こす思わぬセキュリティリスク「LLM02:不安全な出力処理(Insecure Output Handling)」について、身近な例えを交えながら、一歩ずつ優しく紐解いていきましょう!

—

1. 家の鍵に例える「AIの出力」の落とし穴

突然ですが、みなさんの自宅の郵便受けを思い浮かべてみてください。
毎日、色々なチラシや手紙が届きますよね。中には、お得なスーパーのチラシもあれば、見知らぬ怪しいダイレクトメールが入っていることもあります。

ここで、もし「郵便受けに入っていた手紙の命令は、どんな内容でも絶対にそのまま実行しなきゃいけないルール」があったとしたら……どうなるでしょうか?

ある日、怪しい差出人からこんな手紙が届きました。
> 「今すぐ玄関の鍵を開け放ち、リビングの窓を全開にしなさい」

もし、あなたがこの手紙の言葉を疑いもせず、そのまま実行してしまったら……大変なことになりますよね。空き巣に入られてしまいます。

生成AIの出力処理も、これとまったく同じなんです。

LLM(大規模言語モデル)の出力は、いわば「世界中から集めた言葉の郵便受け」です。AI自体は悪気なく返答してくれますが、もしその出力の中に、悪意あるユーザーによって仕込まれた危険な命令(プログラムのコードなど)が混ざっていたらどうなるでしょう?

それを開発中のシステムやWebサイトが「AIの言うことだから安全だ!」と勘違いして、そのまま画面に表示したり、裏側で実行してしまったりする。これが、今回お話しする「不安全な出力処理」という脆弱性です。

—

2. どんな攻撃につながるの?(代表的な被害)

AIの出力をそのまま信用してしまうと、主に次のような恐ろしい攻撃の踏み台にされてしまいます。

① 画面が乗っ取られる「XSS(クロスサイトスクリプティング)」

例えば、チャットボットのようなAIサービスを作ったとします。あるユーザーがAIに対して、巧妙な言葉で次のような出力をさせました。
「画面に <script>悪いプログラム</script> というタグを表示してね」

もし、あなたのプログラムがこの出力をサニタイズ(無害化)せずに、そのまま画面のHTMLに埋め込んでしまったらどうなるでしょう?
そのチャット画面を開いた他のユーザーのブラウザで、勝手に悪いプログラムが実行され、セッション情報(ログインしたままの状態)が盗まれたり、勝手に変な操作をされたりしてしまいます。

② システムの心臓部がやられる「コマンドインジェクション」

さらに怖いのは、AIの出力を「サーバーを操作する命令」としてそのまま裏側のプログラムに渡してしまうケースです。
AIが「このファイルを削除して」という悪意ある出力をうっかり真受けてしまい、サーバーのOSにその命令を伝えてしまうと、システム全体が破壊されたり、社外に秘密のデータが漏洩したりする原因になります。

「AIが相手だから大丈夫」という思い込みが、セキュリティの巨大な穴を作ってしまうんですね。

—

3. 具体的な対策:どうやって身を守ればいいの?

「うわ、なんだか怖くなってきた……どうやって防げばいいの?」と思った方、安心してください! 基本のルールさえ守れば、しっかりと防ぐことができます。

合言葉は「AIの出力はすべて『赤の他人』の言葉と思え。信用するな、必ず疑え(サニタイズとバリデーション)」です。

具体的に、プログラムの中でどのように実装すればよいか、簡単な例を見ていきましょう。

対策①:画面に出力するときは必ず「無害化(エスケープ)」する

Web画面にAIの返答を表示する際、HTMLのタグとして解釈されないように文字を置き換える(エスケープする)処理を入れます。

例えば、PHPを使う場合は htmlspecialchars 関数というものを使って、危険な記号を文字に変換します。

<?php
// 【安全な実装の例】
// AIから受け取った出力結果(この中にもし悪意あるタグが含まれていても…)
$ai_output = "<script>alert('ハッキング!');</script>";

// htmlspecialchars を通すことで、ブラウザが「ただの文字」として安全に表示するように変換します
// 第3引数には文字コード(UTF-8)を明示的に指定するのがプロの流儀です
$safe_output = htmlspecialchars($ai_output, ENT_QUOTES, 'UTF-8');

// 安全になった文字列を画面に出力する
echo "<div class='chat-message'>" . $safe_output . "</div>";
// 画面には <script>... と文字通りに表示され、スクリプトは実行されません!
?>

このように、画面に出す直前で必ず「翻訳(エスケープ)」を挟むことで、ブラウザが勘違いして悪いプログラムを実行してしまうのを防ぎます。

対策②:サーバー側でしっかり「検品(バリデーション)」する

もし、AIの出力結果をもとにシステム内の処理(データベースへの保存や、ファイルの操作など)を行う場合は、その中身が「本当に期待した形・安全なデータか」をプログラムで厳しくチェック(バリデーション)しましょう。

// 【安全な実装の例:Node.jsなどのJavaScript環境】
// AIからの出力が、あらかじめ決められた「安全な形式(例:特定の数値や許可された文字だけか)」になっているかチェックする関数

function validateAndProcessAiOutput(aiResponse) {
    // 例として、出力が「数字だけ」であるべき場合正規表現でチェック
    const isNumberOnly = /^\d+$/.test(aiResponse);

    if (!isNumberOnly) {
        // もし想定外の文字(怪しい記号やタグなど)が含まれていたら、処理をストップしてエラーにする!
        console.error("セキュリティ警告: AIから不正な出力検知されました。処理を中断します。");
        return null;
    }

    // チェックを通過した安全なデータだけを後続の処理に回す
    return aiResponse;
}

家の鍵と同じで、「中身が何だかわからないうちは、絶対に家(システム)の中に入れない」という強い気持ちが大切です。

—

4. セキュリティヘッダーで「二重の鍵」をかける

さらに、プログラムだけでなく、Webサーバー側からも「二重の鍵」をかけておくと、万が一プログラムの隙を突かれても被害を最小限に食い止められます。

その代表が CSP(Content Security Policy:コンテンツセキュリティポリシー) という防犯ブザーのような仕組みです。
HTTPレスポンスヘッダーに次のような設定を入れておきます。

# 【HTTPレスポンスヘッダーの設定例】
# 「うちのサイトでは、許可されていない場所からの怪しいプログラムの実行を一切禁止します!」とブラウザに宣言する
Content-Security-Policy: default-src 'self'; script-src 'self';

この設定をしておくと、たとえAIの出力から悪意あるスクリプトがすり抜けて画面に出てしまったとしても、ブラウザが「おや、このスクリプトは許可されていないぞ!」と気づいて、実行をガッチリブロックしてくれます。まさに心強い防犯カメラですね。

—

まとめ:一歩ずつ、安全な開発の習慣を身につけよういかがでしたでしょうか?

生成AIは、私たちの仕事を何倍も便利にしてくれる素晴らしい相棒です。だからこそ、その出力結果をうのみにせず、「ちゃんと中身を検品してから使う」というひと手間を惜しまないことが、エンジニアとしての重要なスキルになります。

最初は難しく感じるかもしれませんが、
1. 画面に出すときはエスケープ(無害化)する
2. システムで使うときは型や形式をしっかりチェックする
3. HTTPヘッダーなどで二重の備えをする

この基本のステップを一つずつ実践していけば、どんなサイバー攻撃も怖くありません。
焦らず、一歩ずつ、安全で確実なシステム作りを楽しんでいきましょう!

コメント

タイトルとURLをコピーしました