説明
外部から制御できる文字列を <script> 要素のJavaScriptソースへ直接挿入すると、攻撃者がページの権限でコードを実行できるおそれがあります。HTMLテキストのエスケープやHTMLサニタイズだけでは、任意のJavaScriptソースを安全にできません。
想定される影響
- スクリプトが読み取れる認証情報を盗まれ、セッションを乗っ取られる可能性があります。
- ユーザーのブラウザーで任意のJavaScriptを実行されるおそれがあります。
- 信頼するページ上のポップアップやフォームでユーザーをだまし、情報を入力させる可能性があります。
対処方法
- 外部入力をJavaScriptソースとして直接使わないでください。
- 必要な処理は固定のコードで実装し、外部の値では許可した識別子に対応する処理だけを選べるようにしてください。
- データをコードから分離し、実際の出力先の文脈に合うシリアライズと処理を行ってください。
例
変更前
javascript
// 入力をスクリプトソースへ挿入
const userInput = req.query.data;
const html = `<script>${userInput}</script>`;
res.send(html);
変更後
javascript
// 固定されたスクリプトを選択
const userInput = req.query.data;
let scriptSource = "alert('prepare')"
if (userInput == "test") {
scriptSource = "alert('test')"
}
const html = `<script>${scriptSource}</script>`;
res.send(html);
解説:
- 変更前: リクエストの
dataをスクリプト本文へ直接挿入しています。 - 変更後: 入力は識別子
testと比較するだけです。応答に含めるスクリプトはアプリケーション内の固定コードであり、入力文字列自体は実行コードになりません。