2012/08/02

location.hrefの盲点

夏ということで、怖い話をします。 Webアプリケーション開発者の皆さん、聞いて下さい。
時間がない人や、他の人に問題を説明するときなどには簡潔にまとめた版をどうぞ。

 これは2011年12月27日にAppleに報告したSafariの問題です。Appleからは修正する予定はないという回答を貰っていましたが、2012年7月25日にリリースされたMacのSafari 6のアドバイザリによるとどうもMacのSafari 6では修正されたようです。

About the security content of Safari 6
http://support.apple.com/kb/HT5400
WebKit
Available for: OS X Lion v10.7.4, OS X Lion Server v10.7.4
Impact: Visiting a maliciously crafted website may lead to a cross-site scripting attack
Description: A canonicalization issue existed in the handling of URLs. This may have lead to cross-site scripting on sites which use the location.href property. This issue is addressed through improved canonicalization of URLs.
CVE-ID CVE-2012-3695 : Masato Kinugawa
 
Windows版Safariで確認した問題でしたが、今のところWindows版のアップデートは出ていません。Windows版が出るまでは書くのを控えるつもりでしたが、MacのSafari 6がリリースされてから1週間経ってもAppleからは出すか出さないかの告知さえ無いので、もう書いてしまいます。

このようなコードがあったとします。


http://vulnerabledoma.in/webkit_locationhref/
<button onclick="location.href=location.href">reload</button>

location.hrefにlocation.hrefを代入するだけの単純なコードです。リロードされると思うのが普通だと思います。しかしながら、Safariではそうならないときがあるのです。以下のようなURLで、example.comへとばされます。

http://example.com%2F@vulnerabledoma.in/webkit_locationhref/

なぜこんなことが起きるかというと、上のページで、document.writeされているlocation.hrefに注目してください。@の前の「%2F」が「/」にデコードされて表示されています。そうです、なんと、Safariのlocation.hrefは、ホストの前の@の前の文字列をパーセントデコードして返すのです。(@がついたURLはあまり目にしませんが、@の前には認証情報を記述することができます。)
これはつまり、location.hrefが自分と同じドメインのURLを返すことを前提に書いているコードは全て、正しく動かない恐れがあるということです。最悪の場合、XSSが起こります。実際にこの挙動によって引き起こされるXSSを、Googleのサービスでいくつかみつけています:






これはほんの一部です。location.hrefを使って取得したURLから新たに通信をしようとした時に、誤ったホストからリソースを読み込んでしまいXSSを起こしてしまうケースが多くみられました。(どれも既に修正されています。ちなみにGoogleはこれをSafariのバグとみなしているので、報酬は報告した数ではなく、この挙動の情報提供として特別に$1,000を貰っています。)

幸いSafariでは、ホストの前に@を含むURLにアクセスしようとすると、設定を変更していなければフィッシングの警告画面が出ます。よって、もしこの問題を利用したXSSのURLを踏まされても、警告が出て不安になって引き返すユーザーが多いかもしれません。しかし、これはあくまでもフィッシング警告(@の前の文字列がホストだと思わせるようにURLが細工されているかもしれないことを警告しているだけ)であり、XSSの警告ではありません。

Safariがバグとして修正したなら、Appleが自分に問題があることを認めたということで、それでよしとしたいところですが、残念なお知らせがあります。Safari Mobile/Androidの標準ブラウザもこの動きをするのです。

Android標準ブラウザで% 00-FFを@の前に配置しalert(location.href)した図。%デコードされているのがわかる。

さらに、Androidの標準ブラウザは@付きURLにアクセスする時に警告も出しません。

今この情報を出した一番の理由として、このモバイルの問題をどうやっても早急に解決できないことがあげられます。モバイル端末のアップデートは機種によりまちまちで、提供されるかもわかりません。そんな現状で、このような潜在的な問題が早く修正されるとは思えません。アプリケーション開発者で対応するしかないでしょう。

@のついたURLでアクセスされることは多くのサービスで普通はないはずなので、location.href周りのコードが動かなくなるだけなら修正するほどではないと思いますが、XSSが起きるとなれば話は別だと思います。今一度、安全ではない方法でlocation.hrefを参照していないか、確認してみてください。