Table of Contents
十字サイトスクリプト(XSS)とJavaScript防衛入門
クロスサイトスクリプティング(XSS)は、最も人気の高いWebセキュリティ脆弱性の1つです。OWASPトップ10で一貫してランキングされています。 XSS攻撃により、攻撃者は、他のユーザーによって閲覧されたWebページに悪意のあるクライアントサイドスクリプトを注入することができます。 これらのスクリプトは、セッショントークンを盗むことができ、ユーザーはフィッシングサイト、デファスページ、またはマルウェアを回復することができます。 サーバーサイドのサニタイズ化が重要である一方で、JavaScriptはクライアント側で重要な役割を果たし、これらのスクリプトは、これらのスクリプトがXSSSを攻撃を防止し、これらのアプリケーションを保護するために、これらのアプリケーションを保護します。
XSSの3種類を理解する
予防に潜む前に、XSSの3つの主要なカテゴリを理解することは不可欠です。保存、反映、DOMベースの。それぞれは少し異なる検出と予防アプローチが必要です。
XSS ストア
悪意のある入力がサーバー(データベース、フォーラム投稿、コメントなど)に永続的に保存され、その後、適切な衛生なしでユーザーに配信されると、保存(永続的)XSSが発生します。 攻撃ペイロードは、保存されたコンテンツを表示している人のブラウザで実行されます。
反射XSS
悪意のあるスクリプトが、URL パラメータまたはフォームの送信を介して、Web サーバーを反映したときに反映された XSS が起こります。攻撃者は、攻撃者が、攻撃者を、作成されたリンクをクリックして、注入されたコードがすぐに実行します。保存されていない XSS とは異なり、ペイロードは攻撃者を犯しません。
DOM ベースの XSS
DOM ベースの XSS は、クライアント側脆弱性です。攻撃ペイロードは、被害者のブラウザーで DOM 環境を変更します。悪意のあるコードはサーバーに触れることはありません。それは、ユーザーの入力を安全に処理しないクライアント側の JavaScript から始まります(例えば、 から読み込む、 ] 、または )。
JavaScriptでXSS攻撃を検知
検出は、損傷が発生した前に疑わしい活動を特定することについてです。 JavaScriptは、ユーザーの入力を監視し、DOMの変異を追跡し、エントリポイントでデータを検証することができます。クライアント側の検出は、攻撃者の技術がサーバーに直接要求する場合、すべての攻撃をキャッチすることはできませんが、それは、貴重な防衛の最初の行を提供します。
入力検証とサニタイズ
処理の前に、クライアント側でユーザ入力を検証し、サニタイズします。スクリプトの実行を防止するために、[]の代わりに[[]]を使用します。次の関数は、文字列から危険な文字をストライプします。
function sanitizeInput(input) {
const div = document.createElement('div');
div.textContent = input;
return div.innerHTML;
}
は HTML タグを解釈しないため、この作品は、すべてのものをプレーンテキストとして扱います。 ]]] は、任意の HTML の特殊な文字のエスケープされたバージョン (例えば、 ]]], [[]]]) を含みます。
疑わしい要素に対するDOMの突然変異のモニタリング
攻撃者は、多くの場合、[タグまたはイベントハンドラ([])をDOMに注入します。 []] APIを使用して、予期しない要素のインサートを見ることができる。 基本例:
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
mutation.addedNodes.forEach((node) => {
if (node.nodeType === 1) { // element node
if (node.tagName === 'SCRIPT') {
console.warn('Potential XSS: a script element was injected via DOM.');
node.remove(); // or log and analyze
}
// Check for dangerous attributes
if (node.hasAttribute('onerror') || node.hasAttribute('onload')) {
console.warn('Suspicious event handler attribute detected.');
}
}
});
});
});
observer.observe(document.body, { childList: true, subtree: true });
[]注意:]]] スクリプトを]を介してブロックすることで、重なりの攻撃者によって迂回し、正当な機能が解除される可能性があります。 プライマリ防止機構ではなく、監視ツールとしてこれを使用してください。
URL とハッシュパラメーターの検証
DOM ベースの XSS では、URL コンポーネントを を使用して安全に読み、値を HTML に直接入れることを避けます。実行可能なコードを渡す試みを検知します。
const params = new URLSearchParams(window.location.search);
const userParam = params.get('name');
if (userParam && /[<>"'\/]/.test(userParam)) {
console.warn('Potential XSS in parameter: ' + userParam);
// Do not use this value in the DOM without encoding
}
XSS攻撃をJavaScriptで防止
予防は多層アプローチが必要です。JavaScriptだけではアプリケーションを完全に保護することができませんが、適切なバックエンドのサニタイズと]と組み合わせた場合は、コンテンツセキュリティポリシー(CSP))は、リスクを大幅に低減します。
DOM にインサートする前に、すべてのユーザー管理データをエンコード
黄金のルール: 信頼できないデータを DOM に直接入れないでください。 代わりに、内部HTML の安全な DOM メソッドを使用してください。
[ または [ を使用する
const userInput = getUserInput();
const safeText = document.createTextNode(userInput);
document.getElementById('output').appendChild(safeText);
を使わなければならないときは、図書館にSanitize
HTML(例えば、リッチテキストエディタから)をレンダリングする必要がある場合は、信頼できるサニタイズライブラリ(]]のように頼ります。 DOMPurify。 DOMPurifyは、安全なHTMLを予約しながら、悪意のあるコードを削除した、広く使用されている、戦闘テストライブラリです。
// Example with DOMPurify (install via npm or CDN)
const dirty = '<img src=x onerror="alert(1)">';
const clean = DOMPurify.sanitize(dirty);
document.getElementById('content').innerHTML = clean;
DOMPurifyは、入力を解析し、危険なタグと属性を除去し、許可された要素だけを返すことによって動作します。 []]]] GitHub[でDOMPurifyを表示します。
危険なJavaScript機能を避けます
XSS を有効にするにはJavaScript メソッドとプロパティが気にありません。 回避または厳密に制御:
- ] — ] を使うか、正しくサニタイズする。
- ], ] — 同じルール。
- ] — ユーザ入力で使用しません。
- ] — 任意の入力が汚染されている場合は、悪用することができます。
- / 文字列コード] で、回避; 代わりに関数の参照を使用してください。
- コンストラクタ[ — アナログ→
コンテンツセキュリティポリシー(CSP)をJavaScript経由で実装する? 推奨しない
CSPは、スクリプトが実行できるブラウザの仕組みです。 通常、HTTPヘッダーで設定されますが、タグを使用して設定したり、JavaScript経由で要素を動的に作成することもできます。 ただし、既に一部のコントロールが無効にできる攻撃者がいるため、JavaScriptでCSPを制限することはより少なく安全です。 HTTPヘッダーを常に好みます。 CSP(開発中には、JavaScriptを強制する必要がある場合は、開発中には、初期にロードされます。
const meta = document.createElement('meta');
meta.httpEquiv = 'Content-Security-Policy';
meta.content = "default-src 'self'; script-src 'self' 'unsafe-inline'"; // Be very careful with 'unsafe-inline'
document.head.appendChild(meta);
制作のために、WebサーバーまたはリバースプロキシでCSPを設定してください。 []MDN CSPのドキュメント]は、包括的なガイダンスを提供します。
追加のセキュリティ対策
JavaScript 固有の戦術を超えて、完全な XSS 防止戦略には、これらの重要な対策が含まれます。
- [サーバ側で検証します。[クライアント側検証はバイパスできます。クライアントデータを信頼しないでください。
- ] 適切な HTTP レスポンスヘッダを使用します。[ ], ], 特に [.
- []ユーザデータをレンダリングするたびに出力エンコード。[[] コンテキスト 問題: HTML のエンコード、URL エンコード、JavaScript 文字列エンコーディングなど
- []Keep 依存関係が更新されました。[脆弱な JavaScript ライブラリ(jQuery の古いバージョンなど)は、一般的な XSS ベクトルです。npm 監査または同様のツールを使用してください。
- [] 組み込みXSS保護でフレームワークを使用します。[[]]] React、Angular、Vueはデフォルトで出力を自動的にエスケープします。それでも、または[]で注意してください。
- 厳密なCSP.[ を避けます および ] 可能であれば。 インラインスクリプトのノンスまたはハッシュを使用してください。
実世界例: 安全なコメントレンダリング
ユーザーが他の人に表示されているメッセージを送信するブログコメントシステムを検討してください。 攻撃者は[をインサートしようとするかもしれません。 ここに、バックエンドと統合するJavaScriptのアプローチがあります。
- フロントエンドの送信:]]サーバへの送信前にを使用してSanitize(ただし、サーバーはサニタイズする必要があります)。
- サーバはデータを返す:]]] バックエンドは、コメントテキストを HTML でエンコードするべきである。
- [] クライアントレンダリング:[]]] または安全なテンプレートエンジンを使用します。 未加工ユーザーデータで [ を使用しないでください。
function renderComment(comment) {
const item = document.createElement('div');
item.className = 'comment';
const body = document.createElement('p');
body.textContent = comment.body; // escaped by browser
item.appendChild(body);
document.getElementById('comments').appendChild(item);
}
防衛をテストする
予防を実施した後、自動スキャナーと手動ペイロードを使用してアプリケーションをテストします。一般的なテストベクターには、次のものが含まれます。
- []]
- []]
- []]
- []
- []]
ブラウザ開発者ツールを使用して、DOMを調べ、ペイロードがエスケープされていることを確認します。また、違反レポートのコンソールをチェックすることで、CSPの執行をテストします。
コンテンツ
十字サイトスクリプトは深刻な脅威を残していますが、JavaScriptは検出と予防の両方のための強力なツールを提供しています。入力を検証することにより、DOMの変更を監視し、出力をエスケープし、DOMPurifyのような堅牢なライブラリと統合することで、クライアント側のセキュリティを大幅に強化することができます。クライアント側の対策はシルバーの弾丸ではないことを忘れないでください。サーバー側のサニタイズ、CSPヘッダー、定期的なセキュリティ監査を含む防御インディフュージョンの戦略を補完します。活気のある滞在、ライブラリを保ち、あなたの日付を常に維持します。
更に読むには、[]]OWASP XSSページと[]]OWASP XSS防護シートを参照してください。