Microsoft Anti-Cross Site Scripting Library

ha.ckers.orgの12/3のブログ記事 Microsoft XSS Library is Pretty Goodに、Microsoft Anti-Cross Site Scripting Libraryに関する記事が載っていた。

早速、以下のページを参考に、インストールして使ってみた。
MSDN - Anti-Cross Site Scripting Library
MSDN - Microsoft Anti-Cross Site Scripting Library V1.5: Protecting the Contoso Bookmark Page

ライブラリの概要

このライブラリは、その名前の通り、XSS脆弱性が生じることを防ぐためのライブラリで、ASP.NETアプリケーションで使用できる。

コンセプト

以下を基本的なコンセプトとしている。

This library differs from most encoding libraries in that it uses the "principle of inclusions" technique to provide protection against XSS attacks. This approach works by first defining a valid or allowable set of characters, and encodes anything outside this set (invalid characters or potential attacks).
MSDN - Anti-Cross Site Scripting Library

要は、従来の、<>"&など一部の「危険な文字」をエスケープする方法とは違い、英数文字など確実に「安全な文字」以外は、全てエスケープするもののようだ。

メソッド

ライブラリには以下のエスケープ用メソッドが用意されている。

  1. HtmlEncode
  2. HtmlAttributeEncode
  3. JavaScriptEncode
  4. UrlEncode
  5. VisualBasicScriptEncode
  6. XmlEncode
  7. XmlAttributeEncode

このうち、私が試したのは1〜3の3つ。以下に、1〜3の各メソッドの概要を記述する。

1.HtmlEncode
<p>hogehoge</p>のように、テキスト部分に変数を入れたい場合に使う。
SPACE , - . 0-9 A-Z _ a-z 以外は文字参照化(例:&#10;、&#12354;)する。

2.HtmlAttributeEncode
<a name="hogehoge">のように、属性値に変数を入れたい場合に使う。
, - . 0-9 A-Z _ a-z 以外は文字参照化。SPACEも文字参照化する点で1と異なっている。「"」等で括っていない属性値に対応できるように、SPACEを文字参照化しているのだと思う。

3.JavaScriptEncode
<script>var x='hogehoge';</script>のように、JavaScriptの文字列型変数値に、動的に値をセットしたい場合に使う。
エスケープする文字範囲は1と同じ。ただし、エスケープ方法が異なっており、このメソッドでは、\x0a; \u3042;のようにバックスラッシュでエスケープする。また、文字列全体を自動的に「'」で括る。

ライブラリの使い道

このライブラリの使い道は何だろうか?

MSDNのページのQ&Aには、以下のように書かれていた(適当に訳したもの)。

  1. 従来の、System.Web.HttpUtility.HtmlEncode("&<>のみエスケープするはず)を使うことは危険ではない。
  2. このライブラリは、「principle of inclusions」に基づくエスケープ処理を利用する選択肢をユーザに与えるもの。

何のこっちゃ。他のMSDNのページを探しても、このライブラリの使い道は示されていない。

仕方ないので自分で考えると、このライブラリを使用するメリットは以下のようなものだろう。

ブラックリスト方式での取りこぼしを減らす

例えば、以下のように、a要素のhref属性に、値を挿入する場合、攻撃者はjavascriptスキーマを使用してXSS攻撃を仕掛けることができる。

bar.Text = "<a href='" & HtmlEncode(lnkFoo.Text) _
           & "'>foo</a>"

ブラックリストアプローチだと、lnkFoo.Textにjavascriptという文字列が含まれていないことをチェックするが、この文字列中にNUL文字が含まれている場合に、チェック漏れ=XSS脆弱性が生じる(IEはNUL文字を無視して処理してしまう)。HtmlAttributeEncodeメソッドを使うと、NUL文字は�に変換されるため、XSS脆弱にならない*1。つまり、このライブラリは、ブラックリストアプローチでの入力値チェックでの変な取りこぼしを、減らしてくれる効果がありそうだ。

JavaScript文字列の扱いを容易にする

次に、JavaScriptEncode。これまでの定石は、一旦HTMLエスケープした値をhiddenに入れてやって、var x=document.forms[0].hoge.value; のようにそれを参照する方法だと思うが、そのような面倒なことが不要になるということだろうか。そうならば便利だ。しかし、多くのメジャーブラウザで、このJavaScriptEncodeメソッドによるエスケープが有効なのかは判らない。

文字エンコーディングの問題回避

レスポンスで文字エンコーディングを指定していない場合、ブラウザが、Webアプリケーション側で想定しているものとは違う文字エンコーディングで、HTMLを解釈する可能性がある。この場合、UTF-7などを使用した攻撃が可能になる。また、ユーザに、ブラウザのエンコーディング設定を変更させるようにする攻撃もある。

このライブラリでの出力では、限られた文字以外は文字参照化されるため、上記のような攻撃が通用しないと考えられる。

デメリット・限界

このライブラリを使うデメリットなどを考えてみる。

データ量の増加

判りやすいデメリットは、データ量が増えること。マルチバイト文字を使う場合は特にそうで、通常のエスケープに比べて2〜3倍のバイト数になってしまう。

代替の解決方法が存在する

デメリットではないが、このライブラリで解決できる問題の多くは、他の方法によっても解決できるということが挙げられる。先に、<a href="java○script:...">(○はNUL文字)のケースでは、このライブラリが有効になると書いた。しかし、このケースでは、外部から受け取った文字列が、正当なURLであることを確認し(「http(s)://」からはじまり、URLで許可されている文字以外が使用されていない)、あとは従来のHtmlEncodeでエスケープすれば問題は生じないので、わざわざこのライブラリを使わなくても事足りる。

このライブラリを使用することによって、レスポンスHTMLの文字エンコーディング解釈をめぐって生じうるXSSを防ぐことができるが、これについても、レスポンスヘッダやMETAタグできちんとエンコーディング指定をすることで十分対処できる。

ライブラリの限界

このライブラリでは解決できない問題もある。例えば、WebAppSec - IEのexpressionとurlの、インラインスタイルシート内に全角文字を使ったケースなどだ。

感想

上述したように、このライブラリを使う必然性があるケースが理解できなかった。Microsoft自身も、上記したQ&Aの文章の中で、明確な使い道を示せないでいる*2。あえて使い道を探せば、NUL文字などの脆弱性があって、とにかく暫定的に対処したい、というような場面だろうか。

また、このライブラリの、HTMLの仕様上エスケープが不要な文字までエスケープすることでXSSを避ける、というアプローチが、理論的に正しいのかという疑問がある。さらに、このライブラリで対処可能な問題であっても、そもそもそれはWebブラウザ(主にIE)が対処すべきじゃないかというha.ckers.orgの指摘(下記)に、私もうなずいてしまう。

Although I’m pretty impressed by the variety of tests that this succeeds in stopping, I’m still not certain that this is the right place to be fixing this particular issue. To me this has always felt like a browser issue more than an application issue to solve, because there are lots of different ways to execute this type of issue, beyond server side code that a developer produces, including web server vulnerabilities and DOM based XSS, et al.
ha.ckers.org - Microsoft XSS Library is Pretty Good

*1:ha.ckers.orgの記事の中でも、ブラウザのNUL文字問題の多くが、このライブラリで解消されると書いている。

*2:自社のブラウザの特異な仕様を、ことさらに取り上げたくないという事情もあるかもしれない。