説明
ユーザー入力を適切にエンコードせずHTMLテンプレート文字列へ挿入すると、クロスサイトスクリプティング(XSS)が発生するおそれがあります。攻撃者が指定したHTMLやスクリプトが他のユーザーのブラウザーで動作し、情報漏えいやセッションの乗っ取りにつながる可能性があります。
想定される影響
- スクリプトが読み取れるCookie、セッショントークン、入力情報が盗まれるおそれがあります。
- 挿入されたHTMLやスクリプトにより、表示や動作を改ざんされたり、フィッシング画面を表示されたりする可能性があります。
対処方法
- HTML本文へテキストを挿入するときは、その文脈に合うHTMLエンコードか、テンプレートの自動エスケープを使ってください。
- マークアップが不要なら、
innerHTMLではなくtextContentを使ってください。setAttributeは固定された非実行属性にだけ使い、URLのスキームと宛先は別途検証してください。 - HTMLマークアップを許可する場合は、DOMPurifyなどのHTMLサニタイザーでタグと属性を制限してください。サニタイズはテキストのエンコードとは異なります。通常のHTMLエスケープをJavaScriptやCSSの文脈に流用しないでください。
例
変更前
javascript
const userInput = '<img src="x" onerror="alert(1)">'; // 悪意のある入力
const message = `<div>${userInput}</div>`;
document.body.innerHTML = message;
変更後
javascript
function escapeHtml(str) {
return str.replace(/[&<>'"]/g, function (c) {
return {
"&": "&",
"<": "<",
">": ">",
"'": "'",
'"': """,
}[c];
});
}
const userInput = '<img src="x" onerror="alert(1)">'; // 悪意のある入力
const message = `<div>${escapeHtml(userInput)}</div>`;
document.body.innerHTML = message;
解説:
- 変更前:
userInputのマークアップをHTMLへ直接挿入するため、ブラウザーで実行されるおそれがあります。 - 変更後: この例のHTML本文に合わせて
escapeHtmlでエンコードし、入力されたタグをテキストとして表示します。