過激なエスケープで失敗する珍奇な例

以下のようなHTML断片を含むものをウェブアプリが出力するものとします。charsetとかはきちんとサーバ側で付与します。$userdataの元ネタはユーザが入力したものですので、XSSがイヤなので、出力に当たっては、すべての文字を例外なく文字参照してしまう所謂(過剰な|過激な)エスケープをします。ところがこれでも、$userdataに格納されたscriptが動いてしまったのですが、ハテ?どんな場合でしょうか。

<!-- この辺を意識しない -->
<div>
<p>
$userdata
</p>
</div>
<!-- この辺を意識しない -->

答え。以下のような場合。上のHTML断片で意識していなかったところがポイント。IE6で有効。登場しているimg要素のsrc属性が書き換えられています。IE7からは無効のはずです。試したかった人、ごめんなさい。

<img src="a.jpg" datasrc="#HERE" datafld="p">

<xml id="HERE">
<div>
<p>
&#x6A;&#x61;&#x76;&#x61;&#x73;&#x63;&#x72;&#x69;&#x70;&#x74;&#x3A;&#x61;&#x6C;&#x65;&#x72;&#x74;&#x28;&#x30;&#x29;
</p>
</div>
</xml>

セキュリティ上、要素の中?といえばscript要素やstyle要素の中で文字参照が対策として充分には有効でないことが知られていますがxml要素の中も同様だったんですね。ま、サーバ側ウェブアプリがデータバインディングなんて使わないと思いますし、こんなの無視していても実害は絶無だと思います。

以上、Rsnake氏のXSS Cheat Sheet 上のサンプルを 少し変形たものでした。