進行状況の追跡を始めよう
Trailhead のホーム
Trailhead のホーム

クロスサイトスクリプト (XSS) について

学習の目的

この単元を完了すると、次のことができるようになります。
  • クロスサイトスクリプトの脆弱性について説明する。
  • XSS 攻撃の 3 つのタイプを定義する。
  • XSS の内部ユーザに対する 3 つの影響を挙げる。

クロスサイトスクリプトとは?

過去の変化しない静的なページとは異なり、現在の Web アプリケーションは動的で、エンドユーザが実施したアクションに基づいて絶えず更新されます。ボタンをクリックするだけでポップアップウィンドウの作成、フォームの送信、音楽の再生さえも行うことができます。この機能性の向上によってアプリケーションはより使いやすくなりましたが、セキュリティの脆弱性というマイナス面もあります。事実、最も一般的な Web アプリケーションの脆弱性の 1 つであるクロスサイトスクリプト (XSS) によって、攻撃者は拡張された機能を利用し、他のユーザや基盤となるシステムの弱点をついて攻撃できます。

XSS は、攻撃者が不正な JavaScript、VBScript、HTML、またはその他のアクティブコンテンツを Web ページに挿入できる場合に発生する、インジェクションの脆弱性です。他のユーザがページを表示すると、悪意のあるコードが実行され、ユーザを攻撃したり悪影響を与えます。たとえば、悪意のあるスクリプトはユーザのセッションを乗っ取ったり、不正なトランザクションをユーザとして送信したり、機密情報を盗んだり、単にページを改ざんしたりすることができます。

あなたは開発者であり Kingdom Management アプリケーションの防衛担当者であるため、問題を見つけてコードを補強し、XSS を阻止する必要があります。ユーザを保護し、AppExchange 上にリストされるためのセキュリティレビューに合格するには、防止がきわめて重要です。

XSS 攻撃のしくみ

最も簡易な形態では、XSS 攻撃はユーザが行った入力が Web ページの HTML に反映されたときに発生します。コードコンテキストとユーザデータとの分離が不十分であるため、ユーザ入力がコードとして実行されます。

Kingdom Management では、Kingdom でお知らせを投稿するために使用できるスクロールを作成するページを実装しました。アプリケーションでセキュリティの脆弱性を監査するときに、このコンポーネントが XSS に対して脆弱かどうか疑問に思うでしょう。そこで、テストしてみましょう!

  1. Kingdom Management 開発者組織にログインし、[クロスサイトスクリプト (XSS)] アプリケーションを選択します。
  2. [XSS の基本 - デモ] タブをクリックします。
  3. メッセージテキストフィールドに、「Hear ye, hear ye, come one, come all!」などの基本的なメッセージを入力します。
  4. [スクロールの作成] ボタンをクリックします。
  5. ページを更新すると、前の手順で入力したテキストが表示されます。
  6. ページを右クリックし、[ソースを表示] を選択します。
  7. 未加工の HTML でメッセージを検索すると、<i>Hear ye, hear ye, come one, come all!</i> のような HTML が表示されます。

    では、別の方法で試したらどうなるでしょうか? XSS の脆弱性は、ユーザ入力がコードとして実行されるときに発生します。そのため、このメッセージボックスにコードを入力したらどうなるでしょうか? 実行されるでしょうか?

  8. Kingdom Management 開発者組織に戻り、「<u>Testing for underline</u>」と入力してから [スクロールの作成] をクリックします。

    下線効果は起きたでしょうか? それは、次のステップで行います。入力ボックスに入力したテキストは、コードとして解釈されているようです! もっと複雑なことを試したらどうなるでしょうか?

  9. メッセージテキストフィールドに、「<img src=x onerror="alert(\'I said, HEAR YE, HEAR YE, COME ONE, COME ALL!!\');"></img>」と入力します。
  10. [スクロールの作成] をクリックします。小さなウィンドウがポップアップします。
    XSS 概念実証ポップアップ

何が起きているのか、このページのソースコードを詳しく見ていきましょう。

Apex:

if(apexpages.currentpage().getparameters().get('text')!=null && apexpages.currentpage().getparameters().get('text')!='')
basicText=apexpages.currentpage().getparameters().get('text');
outputText = basicText.replace('\r\n','<br/>');

Visualforce:

<apex:page controller="XSS_Basics_Demo" sidebar="false" tabStyle="XSS_Basics_Demo__tab">
    [...]
    <script>
        document.getElementById('{!$Component.textOutput}').innerHTML = 
            '<div style="background-image: url({!$Resource.scroll});
            background-size:100%; height: 320px; width: 400px;"><b><font size="4" style="font-family: \'Alex Brush\', cursive; padding-top: 10px; padding-left: 50px; padding-right: 50px; display: inline-block;" ><i>{!outputText}<i></font></p></div>';
    </script>

なぜこれが起きたのでしょうか? コード (HTML) とユーザデータ (メッセージ) との分離が不十分であるとは、挿入された JavaScript が HTML/JavaScript コードとして処理され、ブラウザで実行されることを意味します。よく見ると、前述のコードは次の重要な行に簡易化できます。

basicText=apexpages.currentpage().getparameters().get('text');
outputText = basicText.replace('\r\n','<br/>');

変数 outputText は URL パラメータテキストから生成されるため、ユーザの制御下にあります。

document.getElementById('{!$Component.textOutput}').innerHTML = '<p>{!outputText}</p>';

Visualforce で、outputText 差し込み項目はコードとして innerHTML に適用されます。ユーザ入力は直接コードに変換されるため、ユーザは URL パラメータを介してページに任意のコードを書き込むことができます。ユーザ入力は「bob」のような簡易なものでも、outputText 差し込み項目の目的を大幅に変更する <img> タグでもかまいません。

XSS 攻撃のタイプ

上記で見てきたコードは、DOM ベース XSS 攻撃と呼ばれる XSS タイプの一例です。実際には 3 つのタイプがあり、それぞれ悪意のあるペイロードが挿入されアプリケーションによって処理される方法が異なります。

  • 蓄積型 XSS: 蓄積型 XSS が発生するのは、悪意のある入力がサーバに永続的に保存され、脆弱な Web アプリケーションでユーザに反射される場合です。これは主に、悪意のある値がデータベースに保存され、メッセージボードへの投稿やユーザプロファイル内のデータなどで取得された場合に発生します。
  • 反射型 XSS: 反射型 XSS が発生するのは、悪意のある入力がサーバに送信され、応答ページでユーザに反射される場合です。

    反射型 XSS 攻撃を成功させるには、攻撃者は次のような悪意のある入力を含むリンクをクリックするようユーザを納得させる必要があります: https://vulnerablesite.com?param=<script>document.cookie()</script>。これは、知識と経験のあるユーザをだますことはできないかもしれませんが、十分に経験のある白馬の騎士でも、元の URL を分かりにくくするリンク短縮などのサービスを使用することでだまされてしまうことがあります。

  • DOM ベース XSS: DOM ベース XSS が発生するのは、攻撃の犠牲となるユーザのブラウザで Web ページのドキュメントオブジェクトモデル (DOM) を変更した結果、攻撃ペイロードが実行される場合です。Web ページそのものは変更されませんが、これらの DOM が変更されたために、クライアント側のコードが悪意のある方法で実行されます。このケースでは、Web アプリケーションのサーバまたはデータベースは巻き込まれません。これは重要な違いです。悪意のある入力がサーバに届かない場合、多くのセキュリティ製品はこの種の攻撃をキャッチできないためです。

XSS の影響

上記で説明した XSS 攻撃はまったく問題ありませんでしたが、XSS は広範囲に影響を及ぼす可能性があります。何かをポップアップさせたり色を変えたり、Web ページの周りに画像をバウンスさせたりして、他人をからかうような簡易なものもありますが、より悪質な攻撃にも使用できます。

外部の攻撃者がこの攻撃をどのように利用するかを考えてみましょう。金銭的な動機により、クレジットカード情報や銀行口座情報を漏洩させようとする攻撃者もいます。政治的または社会的な動機により、抗議の一種としてページを改ざんし、会社の評判に影響を与えようとする攻撃者もいます。また、企業スパイの一種としてデータにアクセスすることを目的として、競合他社から雇われてユーザアカウントを標的とする攻撃者もいます。次に、その他の一般的な XSS 攻撃のタイプを示します。

  • 任意のリクエスト: 攻撃者は XSS を使用して、被害者から Web サーバ宛てのように見えるリクエストを送信できます。
  • マルウェアのダウンロード: XSS はユーザにマルウェアをダウンロードするよう促すメッセージを表示できます。メッセージはサイトからの正当なリクエストのように見えるため、ユーザはリクエストを信用して実際にマルウェアをインストールする可能性が高くなります。
  • キーストロークのログ: 攻撃者はキーボード入力を監視し、ユーザ名とパスワードを探して、後日アカウントにアクセスできます。

一般的な XSS の緩和

これまで、XSS がユーザに与える危険性について説明してきました。次にこれらの攻撃からアプリケーションを守るために使用できる武器について説明します。前に説明したように、XSS はコードコンテキスト (実際に基盤となるアプリケーション) とユーザデータ (ユーザが送信した情報) との分離が不十分であるために発生します。攻撃者は悪意のあるコードを送信して、アプリケーションに実行させることができます。防衛を強化するには、これら 2 つのコンポーネントの間の障壁を増強します。

そのために、入力フィルタリングと出力エンコーディングという 2 つの基本的な手法があります。

入力フィルタリング

入力フィルタリングは、悪意のある攻撃はユーザ入力時に最もよく捕らえることができるというアイデアに基づいています。ユーザが「<b>duck</b>」と入力し、ページでコードが削除またはブロックされた場合、不正なコードは実行されません。入力フィルタリングには 2 つのタイプがあります。

  • ブラックリスティング: 特定の「悪い」文字または文字の組み合わせが禁止され、入力または保存することができません。開発者は既知の悪い文字のリスト (HTML またはスクリプトタグなど) を作成し、入力に悪い文字が含まれている場合はエラーが発生します。
  • ホワイトリスティング: 既知のエントリリストの文字または単語のみが許可され、悪意のある入力を防止します。たとえば、電話番号項目に数字のほかに何かを入力した場合、エラーが発生します。

2 つの入力フィルタリング方法のうち、ホワイトリスティングの方がより安全なアプローチであると考えられています。ホワイトリスティングの効果を得るには、予想される入力値を把握するだけで済みますが、ブラックリスティングの場合、開発者は悪意のあるすべてのエントリのリストを維持する必要があり、多くの場合これは不可能な作業です。

出力エンコーディング

入力フィルタリング手法は、システムに悪意のあるデータが入力されるのを防ぐことで機能しますが、出力エンコーディング手法は反対のアプローチをとります。システムにすでに存在する悪意のあるペーロードの実行を阻止します。実際に多くの場合、出力エンコーディングは入力エンコーディングよりも必要であると考えられています。アップストリーム防御やダウンストリーム防御に依拠することがなく、また代替入力経路によって迂回できないためです。

出力エンコーディングでは、サーバは特定のコンテキスト (HTML、JavaScript、URL) で意味のあるすべての文字を取得し、テキストバージョンを表す文字で置き換えます。たとえば、「<」 文字を考えてみます。HTML では、この文字はタグの開始を表しますが (太字の <b> など)、数値演算ではこの文字は「大なり」を意味します。

では、ブラウザはどうやってその違いを区別するのでしょうか? エンコーディングです! エンコーディングにより、意味を取り除く制御された置換によって、意味のある文字をテキストブロックに含めることができます。「<」文字の場合は「&lt;」で置き換えることで、ブラウザは HTML バージョンではなくテキストバージョンの「<」が必要であると理解します。

開発者はこの同じ概念を使用して XSS を緩和できます。コードとして機能できる文字は、コードブロック内では意味のあるバージョンで表されないためです。文字のテキストに相当する部分のみが表示されます。

リソース

Open Web Application Security Project (OWASP) - Cross-Site Scripting (オープン Web アプリケーションセキュリティプロジェクト (OWASP) - クロスサイトスクリプト)

Flower icon used to indicate that the content is for Salesforce Classic

このモジュールは Salesforce Classic 向けです。ハンズオン組織を起動するときには、Salesforce Classic に切り替えてから、この Challenge を実行してください。

retargeting