MS_XSSCountermeasures - NetDevInfraWGinOSSConsortium/NetDevInfraWiki GitHub Wiki

XSS対策の実装方針

概要

  • XSS はスクリプトをインジェクションする攻撃で

    • 主に Cookie を盗むために使用される。
    • 若しくは、HTML5 以降では、WebStorage の情報を盗むために使用される。
    • ただし、ソレ以外の情報を盗まれたり、フィッシング詐欺へ悪用される可能性もある。
  • ASP.NETでの XSS 対策のサニタイジング方針について纏める。

移行メモ(助詞): 「フィッシング詐欺への悪用される」の助詞を修正した。

補足(本ページは「入力の検証」寄りの整理である): 以下では
ASP.NET の「要求の検証」を軸に整理しているが、
XSS 対策の本筋は **出力時のエスケープ(コンテキストに応じた
エンコード)**である。
入力時のフィルタは補助であり、これだけでは防げない
(下記「補足(現在の対策の考え方)」を参照)。

対応方針の材料

一般的に、どのような対応方法があるか?

要求の検証

要求の検証という機能があり、
クロスサイトスクリプティング(以下、XSS と略す)の
可能性のあるリクエストを識別し例外を発生させる機能がある。

この機能を無効にするには以下の手順に従う。

Web.config

<system.web>
  <httpRuntime requestValidationMode="2.0" />
</system.web>

と指定し(Mode が 4.0 だと全ページで強制 ON になる)、

個別のページで @Page ディレクティブを以下のように設定する必要がある。

<%@ Page validateRequest="false" %>

ただし、無効にした場合は、独自の実装で
XSS を防止するためのサニタイジング処理を実装する必要がある。

移行メモ(構文): 元ページの <@ Page validateRequest="false" %>
開始タグが <%@ の脱字と解して修正した。

コントロール

  • TextBox コントロール
    ASP.NET では最低限、TextBox コントロールが既定でサニタイジング処理を行う。

  • その他のコントロール
    しかし、Label コントロール等は既定でサニタイジングされないので、
    TextBox コントロールの入力をそのまま Label コントロール等に持って行くと、
    XSS が可能な脆弱性のある Web アプリケーションが出来上がる。

補足(正確には TextInnerHtml の違い): Web Forms の
Label.TextHTML としてそのまま出力されるため、
値に <script> が入っていれば実行される。
「TextBox はサニタイジングする」というのは、
TextBox が value 属性へ値を出す際に属性エンコードするからで、
コントロールが安全かどうかは、出力先が
「HTML 本文」か「属性」か
で決まる。
Label に外部由来の値を入れるときは
Server.HtmlEncode(...) を通すか、
Literal コントロールの Mode="Encode" を使う。

「要求の検証」相当

MVC には、Web Forms の「要求の検証」相当の機能がないので、
代替可能な ValidateInput 属性を使用する。

「コントロール」相当

  • MVC には、Web Forms の「コントロール」相当の機能がないので、
    HTML ヘルパを使用する。
  • HTML ヘルパには ≒ Web Forms の「コントロール」で、
    基本的にサニタイジング処理が実装されている。

補足(Razor は既定でエンコードする): MVC 3 以降の Razor では
@モデル.値 は自動的に HTML エンコードされる
(エンコードしたくない場合に明示的に @Html.Raw(...) を書く)。
Web Forms の <%= %>(生出力)と <%: %>(エンコード出力)が
紛らわしかったのに対し、
既定が安全側になったのが大きな違いである。

対応方針の案

案件依存だが・・・。

要求の検証 = ON の場合

要求の検証を ON で、ランタイムエラー表示を回避したい場合、
HttpRequest.Filter で POST の Body を HTML エンコードするなどの方式が考えられる。

Web メソッド(ASP.NET Web Services, WCF, ASP.NET Web API)の Body を
エンコードしないように、HTTP メソッドや URL のファイル拡張子を判別すると良いと考える。

要求の検証 = OFF の場合

要求の検証を OFF にした際の仕様の組み方は、

基本的には、

になると考える。

移行メモ(リンク先): 元ページでは
「カスタムコントロールのカスタマイズ」のリンクが
移行元サイトの絶対 URL(http://techinfoofmicrosofttech.osscons.jp/...)で
書かれていたため、本 Wiki 内の
.NETコントロールのカスタマイズ方法への
リンクに置き換えた。

同様に、ValidateInput 属性か、HTML ヘルパを使用する。

要求の検証 = ON の場合

ValidateInput 属性を true に設定する。

[ValidateInput(true)]

要求の検証 = OFF の場合

  • ValidateInput 属性が false の場合、

    [ValidateInput(false)]
  • HTML ヘルパでサニタイジングする。

判断材料

こちらは、検出されたら基本的に対応する。

  • 攻撃の成功が割と明らかなので、誤検知が少ない。
  • 攻撃されると、Cookie や SessionID が漏洩するので、
    インターネット環境では対策必須。

攻撃対象

一般的に、足がつかない、

  • 匿名アクセス可能なサイトか、
  • フリーメールサービスのアドレスでサインアップ可能なサイト

が多いと考える。

攻撃者

  • 上記のような匿名アクセスが可能なサイトの場合、誰でも攻撃可能。
  • 会員制サイトの場合、そのサイトを利用可能な会員でないと、
    攻撃方法を見い出せない。

移行メモ(誤字): 「会員でしないと」を「会員でないと」に修正した。

攻撃方法・対策方法

SC:脅威

補足(現在の対策の考え方): 本ページの内容は
ASP.NET(.NET Framework)時代の整理である。
現在の標準的な多層防御は次のようになる。

対策
一次(必須) 出力時のコンテキスト別エスケープ(HTML / 属性 / JavaScript / URL / CSS)
二次 Content-Security-Policy(nonce + strict-dynamic
三次 Cookie に HttpOnly / Secure / SameSite を付ける
補助 入力値の検証(形式・長さ)

「要求の検証」のような 入力時のブラックリスト フィルタは
一次対策にならない
(回避手法が多く、正当な入力も弾く)。
なお ASP.NET Core には「要求の検証」機能自体が無く、
Razor の自動エンコードと CSP で守る設計になっている。

また、本ページが「主に Cookie を盗むため」としている点についても、
Cookie に HttpOnly を付けていれば JavaScript からは読めないため、
現在の XSS の主目的は
セッションの乗っ取りより、被害者の権限での操作の実行
(送金、設定変更、トークンの窃取)に移っている。

参考

本 Wiki 内


Tags: テスト

⚠️ **GitHub.com Fallback** ⚠️