ヒーロー背景(区切りなし)
指令

インジェクション - XSS

クロスサイトスクリプティング(XSS)は、別のユーザーが使用するブラウザ上で攻撃者が制御するスクリプトを実行させる、別の種類のインジェクション脆弱性である。XSSはHTML/JavaScriptインジェクション脆弱性とも見なすことができる。

XSS脆弱性の影響は、その存在する文脈に大きく依存します。影響範囲は、スクリプトが実行されるページから情報を抽出する可能性から、ページの状態を変更して被害者としてページ上で操作を実行するまで多岐にわたります。

遭遇する可能性のあるXSSの種類を検証しましょう。

XSSの種類

XSSは、それらを区別しやすくするためにいくつかの区分に分けられます。これらは、ペイロードの配信方法と侵入点の場所に基づいて分類されます。

ペイロード運搬手段(貯蔵型または反射型)

攻撃者はXSSペイロードを2つの方法で提供できます:

  • 保存型XSS: ユーザーが制御するデータ(例:データベースに保存され、他のユーザーに送信されるデータ)を介して発生する
  • 反射型XSS: ユーザーが提供したペイロードが、ユーザーがアクセスしたURLまたはクエリ文字列を介して送信されることで発生する

本質的な違いは、リフレクテッドXSSは通常ユーザーの操作に依存し、悪意のあるペイロードを含むリンクを開いたユーザーにのみ影響を与える点である。一方、ストレージドXSSは、ペイロードを表示する特定のページを開くだけで、1人または複数のユーザーに対して実行される可能性がある。

ペイロード設置位置(DOMまたは非DOM)

ペイロードが注入される位置によって、その脆弱性を「DOM」脆弱性として分類するかどうかが決まります。これは、ペイロードが実行される場所の区別を指します:

  • XSS非DOM型:ペイロードはHTMLとしてレンダリングされ、タグ内でも属性内でも同様である
  • DOM XSS: La charge utile est rendue dans JavaScript, comme une <script>balise `` ou un gestionnaire d'événements tel que `onclick=

XSS - 防御の基礎

このセクションでは、XSS防御の基盤となるプリミティブの原則を検討します。基礎を理解することは重要ですが、実際にはXSSに対する99%の保護はテンプレートライブラリに依存すべきです。

ブラウザで実行されるマークアップやコードとしてレンダリングされるテンプレートを作成する場合、XSS対策の鍵は*エンコーディング*です。この文脈におけるエンコーディングとは、文字列をインタープリタが特定の方法で処理する形式に変換する操作を指します。

ただし、使用する符号化方式の種類は、データが使用される場所や状況によって異なります。

  • À l'intérieur d'une balise, comme `<div>Entrée utilisateur ici</div>` : **Encodage HTML**
  • À l'intérieur d'un attribut, comme `<input placeholder="User input here"></input>` : **Encodage des attributs**
  • Dans Javascript, comme `<script>x = « Entrée utilisateur ici » ;</script>` : **Encodage Javascript **

一部のフレームワークは、主な防御手段としてのエンコーディングを放棄し、代わりにデシネクションを用いて危険な可能性のあるコンテンツから値を削除します。これははるかに複雑なプロセスであり、考慮すべき多くの特殊ケースが存在します。独自のデシネクションルーチンを実装することは推奨されません。

いくつかの言語での例を見てみましょう。実際にどのように機能するのかを確認するためです。

C# - 非セキュア: Razor

`IHTMLContent` オブジェクトが `@` でプレフィックスされている場合、値はエンコードされずに直接テンプレートに配置されます。

<!--- UNSAFE: The htmlSnippet will get interpreted without any escaping --->
@Html .Raw (extrait HTML)

C# - セキュア:Razor

デフォルトでは、Razorテンプレートにおいて「@」で始まる文字列はすべてエスケープされたHTMLコードとして扱われます。

<!--- SAFE: The htmlSnippet will get HTML escaped --->
@htmlSnippet

Java - セキュア:JSP

c:outを使用する場合、デフォルトではXML形式でエスケープされます(これはEscapeXMLプロパティで変更可能です)。これによりHTMLコンテキストではXSSから保護されますが、他のコンテキストでは保護されません。

<div><c:out value="<%= author %>" /></div>

Java - セキュア : (fnxml)

上記と同様に、`fn:EscapeXML`を直接呼び出すことも可能です。これにより、与えられた入力のXMLエスケープが行われます。ただし、これもHTMLコンテキスト内でのみ保護されます。

<div>$ {fn:EscapeXML (auteur)}</div>

JavaScript - 非セキュア: Angular InnerHTML

InnerHTMLプロパティを指定すると、その名前が示す通り、出力エンコーディングが無効化されるため、XSSのリスクに晒されることになります。

<!--- UNSAFE: The htmlSnippet will get interpreted without any encoding --->
<p [innerHTML] ="htmlSnippet"></p>

JavaScript - セキュア:角度補間

Angularが二重中括弧(`{{`と`}}`)を使用してテキストを補間することで、出力時のHTMLエスケープが可能となり、XSSから保護されます。

<!--- SAFE: The htmlSnippet will get encoded and then interpreted --->
<p>{{HtmlSnippet}}</p>

JavaScript - 非セキュア:ReactのDangerousInnerHTML

DangerouslySetInnerHTMLプロパティを指定すると、その名前が示す通り、出力エンコーディングが無効化されるため、XSSのリスクに晒されます。

<!--- UNSAFE: As the name suggests, the dangerouslySetInnerHTML attribute is dangerous as it does not escape the output --->
<div dangerouslySetInnerHTML= {{__html : htmlSnippet}} />;

JavaScript - セキュア:補間されたReact

Reactによるテキストの波括弧(`{` と `}`)を用いた補間は、HTMLを出力時にエスケープし、XSSから保護します。

<!--- SAFE: The htmlSnippet will get encoded and then interpreted --->
<div>{Extrait HTML}</div>

Python - 非セキュア:Django

Djangoモデルで「safe」フィルターを使用すると、出力の自動エスケープが無効化されるため、XSS攻撃に対する保護が失われます。

<!--- UNSAFE: The htmlSnippet will not get HTML encoded --->
<div>{{HtmlSnippet | sécurisé}}</div>

Python - セキュア:Django

Djangoによる二重中括弧(`{{` と `}}`)を用いたテキスト補間は、出力時にHTMLをエスケープするため、XSSから保護します。

<!--- SAFE: The htmlSnippet will HTML encoded --->
<div>{{nom}}</div>