【テクニカル・上級編】CSPのnonceとhashを用いたインラインスクリプトの安全な許可設定 – アプリケーションセキュリティ & 安全な開発防御ガイド

インラインスクリプトの「死角」を封殺する:CSP NonceとHashによる動的防衛の極意

多くのエンジニアが「CSP(Content Security Policy)を入れているから大丈夫」と過信している。だが、現場でインシデントレスポンスを担当する我々から見れば、unsafe-inline を許容したままのCSPなど、ただの気休めに過ぎない。

攻撃者は、アプリケーションの少しの隙間からクロスサイトスクリプティング(XSS)をねじ込み、DOMを書き換え、認証トークンを外部へ送信する。この「実行権限の奪取」を根底から防ぐために、我々アーキテクトが実装すべきは、「誰が書いたコードか」を静的・動的に検証する仕組みだ。

今回は、現代のWebアプリケーションにおいてインラインスクリプトを安全に制御するための「Nonce」と「Hash」のアーキテクチャを深掘りする。

—

1. なぜ「静的なCSP」は敗北するのか

かつては script-src 'self' としていれば十分だった時代もあった。しかし、モダンなフロントエンドフレームワークや、動的にコンテンツを差し込むサードパーティライブラリ、さらには現在猛威を振るう生成AIによるコード生成において、静的なポリシーは柔軟性を欠き、結局 unsafe-inline を解禁する羽目になる。

これが攻撃者の入り口だ。攻撃者は、アプリケーションの脆弱性(DOM-based XSSなど)を突き、許可されたソース以外のスクリプトをブラウザに解釈させる。ブラウザは「何が正当なコードか」を判別できず、攻撃者の注入したスクリプトを実行してしまう。これを防ぐための防衛線が CSP Nonce と Hash である。

—

2. Nonce(Number used once)による即時検証

Nonceは、リクエストごとに生成される暗号論的に強力なランダム値だ。サーバーはHTMLを生成する際、インラインスクリプトのタグにその値を埋め込み、同時にHTTPレスポンスヘッダーにも含める。

サーバーが送信するCSPヘッダー
Content-Security-Policy: script-src ‘nonce-dGhlc2VjcmV0cmFuZG9t’ ‘strict-dynamic’;


アーキテクトの視点:実装上の注意点

ここで最も重要なのは、「Nonce値をキャッシュさせないこと」だ。CDNやプロキシがHTMLをキャッシュしてしまうと、古いNonceが使い回され、攻撃者がその値を特定・悪用できる隙が生まれる。Cache-Control: no-cache の徹底は、単なるWeb最適化の話ではなく、セキュリティの死活問題である。

—

3. Hash(SHA-256)による「書き換え」の無効化

動的なページ生成が難しい環境や、キャッシュを最大限活用したいケースでは、スクリプトの内容そのものをハッシュ化してポリシーに登録する。

スクリプトの内容をSHA-256でハッシュ化して許可
Content-Security-Policy: script-src ‘sha256-Rk45…=’ ‘strict-dynamic’;

この手法の強みは、「スクリプトが1文字でも改ざんされたら実行されない」という堅牢性にある。攻撃者がインラインスクリプトに alert(document.cookie) を1文字追加しただけでハッシュ値は不一致となり、ブラウザは即座にそのブロックを捨てる。

—

4. プロンプトインジェクションと「ガードレイル」の未来

今、我々が直面している最大の変化は、LLM(大規模言語モデル)が生成したコードがアプリケーションに直接組み込まれるケースの増加だ。AIが生成したコードがプロンプトインジェクションによって汚染されていた場合、静的な検査だけでは限界がある。

ここでアーキテクトが考慮すべきは、「実行環境の分離(Sandboxing)」と「CSPの動的生成プロセス」の統合だ。

1. 実行時の検証: AIが生成したコードをそのまま実行せず、中間表現としてサンドボックス内で評価(AST解析)し、安全性が確認されたものにのみ、その場でNonceを付与して出力するパイプラインを構築する。
2. 耐量子暗号への備え: 将来的に量子コンピュータが普及すれば、現在のハッシュアルゴリズムも脅威にさらされる可能性がある。SHA-256からSHA-3への移行や、鍵交換プロセスの見直しをロードマップに含めておく必要がある。

—

結論:防衛とは「疑うこと」から始まる

CSPのNonceとHashは、単なる設定ファイルの一行ではない。それは「信頼の境界線」を定義する宣言である。

現場でインシデントが発生するたびに感じるのは、技術的な欠陥以上に「運用プロセスの崩壊」が致命的であるということだ。どんなに優れたCSPを構築しても、開発者が利便性のために unsafe-inline に逃げれば、すべては水泡に帰す。

我々エンジニアがすべきことは、この堅牢な防衛機構を「いかに開発者の体験を損なわずに透過的に実装するか」というアーキテクチャの戦いだ。

あなたのシステムにおいて、インラインスクリプトはまだ「信頼」されているか? それとも「検証」されているか? 今夜、もう一度CSPヘッダーの構成を確認してほしい。攻撃者は、あなたが「面倒だ」と感じて設定を簡略化したその隙を、正確に狙っている。

コメント

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