XSS 脆弱性はインジェクションの脆弱性であり、攻撃者が悪意のあるデータの一部をウェブ・アプリケーションに挿入します。悪意を持って注入されたデータはブラウザに拾われ、ブラウザはデータをコードとして解釈します。これにより、攻撃者から注入されたペイロードは正当なアプリケーションコードとして実行され、攻撃者はユーザのブラウザで実行されているアプリケーションを完全に制御することができるようになります。

以下のコード例は、XSS 脆弱性と攻撃の教科書的な例を示しています。

jQuery アプリケーションにおける DOM-XSS 脆弱性

<div id="messageContainer"></div> 以下のように記述します。
<script>
...
$("#messageContainer").append(myMessage)；
...
</script>
JavaScriptペイロードを含む悪意のあるメッセージ

こんにちは、ジョン！<script>alert("かくれんぼしようよ！")</script></script
このデータがページに挿入されると、ブラウザはメッセージ内のスクリプトを実行し、アラートダイアログをトリガーします。この例ではalert()関数を呼び出していますが、これはおそらくXSS攻撃で最も危険度の低いものでしょう。間違えてはいけません。現実には、攻撃者はページから機密データを盗んだり、パスワードやクレジットカード情報を盗むためにユーザ入力を捕捉し たり、正当なアプリケーション自身がリクエストを送信するかのようにサーバにリクエストを送信することさえできます。ひとたび攻撃者が XSS 脆弱性の悪用に成功すると、ブラウザ上のアプリケーションの実行環境全体が侵害されたと考え るべきです。

XSS 攻撃に対する最善の防御は、ブラウザがデータをコードとして決して見ないようにすることです。そのための一般的なアプローチは、文脈依存の出力エンコーディングを適用することです。文脈依存の出力エンコーディングは、データがページ内で終わる文脈に合わせてエンコードされることを保証します。エンコード中、潜在的に危険な文字は無害な文字に変換されます。この変換により、ブラウザはこれらの文字をコードではなくデータと見なし、混乱を回避して攻撃を防ぎます。

以下は、悪意のあるペイロードを含むデータにコンテキスト依存の出力エンコーディングを適用した場合の効果の例です。

JavaScriptのペイロードを含むが、XSSを避けるために適切にエンコードされた悪意のあるメッセージ

こんにちは、ジョン！ &lt;script&gt;alert("Let's play hide and seek!")&lt;/script&gt；
ご覧のように、ブラウザは<と>の文字を表示する&lt;と&gt;のHTMLコードをレンダリングするように指示されます。これは明らかにデータなので、ブラウザはデータとコードを混同することはありません。
An XSS vulnerability is an injection vulnerability, where the attacker inserts a piece of malicious data into a web application. The maliciously injected data will be picked up by the browser, which interprets the data as code. This causes the injected payload from the attacker to be executed as legitimate application code, which gives the attacker full control over the application running in the user’s browser.

The code example below illustrates a textbook example of an XSS vulnerability and attack.

A DOM-XSS vulnerability in a jQuery application

<div id="messageContainer"></div>
<script>
...
$("#messageContainer").append(myMessage);
...
</script>
A malicious message containing a JavaScript payload

Hello John!<script>alert("Let's play hide and seek!")</script>
If this data is inserted into the page, the browser executes the script in the message, triggering the alert dialog. The example here calls the alert() function, which is probably the least dangerous effect of an XSS attack. Make no mistake. In reality, attackers can steal sensitive data from the pages, capture user input to steal passwords or credit card information, and even send requests to servers as if the legitimate application itself sends them. Once an attacker succeeds in exploiting an XSS vulnerability, you should consider the application’s entire execution environment in the browser to be compromised.

The best defense against XSS attacks is to ensure that the browser will never see data as code. A common approach to achieve that is by applying context-sensitive output encoding. Context-sensitive output encoding will ensure that the data is encoded for the context where it ends up in the page. During the encoding, potentially dangerous characters are translated into harmless counterparts. Because of that translation, the browser will see these characters as data instead of code, which avoids the confusion and prevents the attack.

Below is an example of the effect of applying context-sensitive output encoding on data containing a malicious payload.

A malicious message containing a JavaScript payload, but properly encoded to avoid XSS

Hello John!&lt;script&gt;alert("Let's play hide and seek!")&lt;/script&gt;
As you can see, the browser is now instructed to render the &lt; and &gt; HTML codes, which display the < and > characters. Since this is clearly data, the browser will not confuse the data for code.