HTML Purifierの4.1.1がリリースされました。今回のリリースには1件のSecurity Fixが含まれています。今日はその内容について少し書きます。
IEのCSSのurl()の扱い
以下のようなstyle属性があったとき、ブラウザはどのように解釈するでしょうか?
<span style="background: url('http://host/aaa\'\);color:red;')">111</span>
Firefox、Opera、Safariでは、「http://host/aaa');color:red;
」というURIをもつbackgroundプロパティと解釈します。したがってcolorプロパティが有効になることはありません。これはCSSの仕様から見ても至極妥当な挙動です。
ところがIEだけが違う解釈をします。IEで上記のHTMLを表示させると、backgroundプロパティのURI値は「http://host/aaa\'\
」と解釈されます。そして、その後ろのcolorプロパティが有効となり「111」という文字は赤字で表示されます。
このように、IEはurl()内の文字列リテラルにおいて「\」によるエスケープを解釈しません。HTML Purifierの4.1.1未満にあった脆弱性は、IEのこのような特異な解釈(バグ)を適切にハンドリングできないというものでした。
font-familyプロパティ
font-familyプロパティでも「'」または「"」で括ったリテラルが使用可能です。
こちらはどうなのか以下のHTMLで試してみます。
<span id="s1" style="font-family: 'aaa\';color:red;'">111</span> <script> alert(document.getElementById('s1').style.fontFamily); </script>
このHTMLをIEで表示すると、他のブラウザと同じく「'aaa';color;red;'
」がalertされます。つまり、font-familyについていえば、IEも「\」によるエスケープ構文をサポートしているということになります。
ならばurl()でも「\」エスケープをサポートすればよさそうなものですが、上で説明したようにそうはなっていません。ひょっとしたら、url()では「C:\terada\...」のようなパスが使われる可能性を考慮して、「\」エスケープを解釈しないのかも…と推測していますが、真相はわかりません。
とられた対策
HTML Purifier 4.1.1では以下の対策がとられました。
Rewrite CSS url() and font-family output logic.
The new logic is as follows:
Public Git Hosting - htmlpurifier.git/commit
- Given a URL to insert into url(), check that it is properly URL encoded (in particular, a doublequote and backslash never occurs within it) and then place it as url("http://example.com").
- Given a font name, if it is strictly alphanumeric, it is safe to omit quotes. Otherwise, wrap in double quotes and replace '"' with '\22 ' (note trailing space) and '\' with '\5C ' (ditto).
実はこの対策は私が提案したものがベースになっていたりします(Release Noteにcreditしてくれました。脆弱性自体はMario Heiderich氏が報告したようです)。
IEの挙動が変わらない限り、このようなちょっと面倒な対処をせざるをえないと思います。