2009年夏、はてなブックマーク界隈では「かんたんログイン」が危ういという話題で持ち切りだった。IPアドレス制限をしていても突破できてしまうのではないかという話だった。
これは要するに次のような話だった。
まず、SoftBankの携帯電話で特定のAPN mailwebservice.softbank.ne.jp でネット接続して、所定のProxyサーバ sbwapproxy.softbank.ne.jp:8080 を通してアクセスすると、一般のPCからでも、「Yahoo!ケータイにて利用するIPアドレス帯域」で示されているIPアドレスからのアクセスができるという。これは仕様であろう。
となると、HTMLソースを閲覧できる(これはやむを得ない*1)ほか、任意のケータイIDを送信できてしまうことになり、「かんたんログイン」などのケータイID認証を突破されるとの疑いがもたれた。ただ、User-Agent: ヘッダに載せて渡される端末製造番号は偽装されるかもしれないが、X−JPhone-UID: ヘッダはProxyサーバで付与される(オーバーライドされる)ものなので偽装はされないとの結論に落ち着き、「かんたんログイン」に端末製造番号を使うのはやめようという話になっていた。
しかしここで私は気付いた。ということは、EMOBILEのEMnet経由でアクセスすれば、任意のヘッダを送れてしまうのではないかと。
つまり、PCからEMnetでダイヤルアップ接続して、EMnet用のProxyサーバ wm.internal.emnet.ne.jp:8080 経由でHTTPアクセスするときにどうなるかである。
実際に自分のEMOBILE端末で試してみたところ、EMnetの契約者固有IDを表すヘッダ X-EM-UID: に、ランダムな文字列を載せて送信した場合、これは、接続に使用しているEMOBILE回線の契約に対応したIDに書き換えらてWebサーバに届いた。つまり、契約者固有IDはキャリアのゲートウェイ(Proxyサーバ)でオーバーライドされるようになっている。
では、同じ環境で、他社キャリアの契約者固有IDを送信したらどうなるのか。つまり、EMnetで、X-Up-Subno: や X-JPhone-UID: や X-DCMGUID: を送った場合はどうなるのか。これはオーバーライドされずにWebサーバに届いた。
ということは、EMOBILEを含むキャリア各社の「IPアドレス帯域」*2でIPアドレス制限している「かんたんログイン」に対して、EMnet経由で auなどの契約者固有IDを送信すれば、なりすましログインができてしまう(場合がある)と考えられる。
そこで早速調べたのが、ポケットはてなの「かんたんログイン」機能だった。このときの顛末については、2月21日の日記「はてなのかんたんログインがオッピロゲだった件」に書いた通りで、ポケットはてなはEMOBILEの携帯電話に対応しておらず、イー ・モバイルからのアクセスはPC扱い(PC向け画面にリダイレクトされる)になっていた。
その後、どこかにEMOBILEに対応した「かんたんログイン」はないかと探していたところ、SNSサイト構築ソフトとして広く普及している「OpenPNE」がEMOBILEに対応していることに気づいた。OpenPNEはオープンソースなので、ソースコードを読んでその脆弱性が存在することは明らかだった。
2月22日、OpenPNE開発者の連絡先に「脆弱性について報告したい」とメールを送ったところ、何回かののやり取りの後、テスト環境を用意していただくことができ、そこでこの脆弱性を実証した上、問題の原因と考え方の詳細をお送りした。
そして3月5日、JVNとして脆弱性情報が公表され、OpenPNEプロジェクトから修正版がリリースされた。
これがOpenPNEの脆弱性であって、イー・モバイルの脆弱性ではないのは、次の理由からである。
EMnetのProxyは、偽のX-EM-UID:ヘッダが送信されてもそれを本物に差し替える(オーバーライドする)ようになっているが、偽のX-Up-Subno:や、X-JPhone-UID:、X-DCMGUID:の差し替え等は行わない。これを指して「イー・モバイルの脆弱性」と言えるだろうか。それは無理がある。なぜなら、X-Up-Subno:、X-JPhone-UID:、X-DCMGUID: はその名のとおり(「X-」が付いているとおり)標準化されていない、各社独自の勝手仕様なのであって、他社にとっては知ったこっちゃないからである。
もし仮に、EMnetのProxyが、X-Up-Subno: などのヘッダを削除する処置をとるようになったとすれば、それはイー・モバイルが他社の契約者固有IDにも責任を持つことになる。そうすると、キャリア各社がどんな勝手仕様のヘッダを設けているかを全て把握して、必要な措置を講ずる責任を負うことになり、しかもそれは、継続して永遠に、他社の新機能にキャッチアップしてアップデートしていかないといけないことになる。その方向性は間違っているだろう。
というわけで、これはOpenPNEの脆弱性として取り扱われ、OpenPNEが利用されているWebサイトはそうとうな数にのぼるとみられることから、IPAから注意喚起が出ていた。
「OpenPNE」には、登録した携帯電話以外から、その携帯電話になりすましてアクセスできてしまうセキュリティ上の弱点(脆弱性)があります。この弱点が悪用されると、「OpenPNE」に保存されている個人情報が悪意あるユーザに漏えいしたり、書き換えられる可能性があります。
脆弱性による影響が大きいことと、「OpenPNE」の普及状況から、この影響を受けるソーシャル・ネットワーク・サービスのウェブサイトが国内に広く存在すると判断し、注意喚起を行いました。
同様の事例が他にどのくらいあるのかはわからないが、たとえば、ケータイPHP開発者のコミュニティサイトとして名高い「ke-tai.org」が、「実際に動いてすぐ使える」などと無責任に提供している「PHPによるかんたんログインサンプル」のコードが、これに該当する。
「実際に動いてすぐ使える」というこの解説は、IPアドレス制限について以下のようにしか説明していない。
なお、かんたんログイン機能で最も重要なのは、ケータイからのみアクセスを許可することです。(PCからの接続は不可とする)PCからだと端末ユーザIDはいくらでも詐称できてしまいます。必ずケータイからのみアクセス許可としましょう。
アクセス制限は.htaccess内で行っていますが、簡易版となっています。各キャリアのページや下記のページを参考にして、常に最新のキャリアIPアドレス帯域を指定することをオススメします。
→ ke-tai.org ケータイキャリア・クローラIPアドレス [ke-tai.org]
※追記
可能であるなら上記のアクセス制限に加え、接続元IPアドレスとユーザエージェントを照らし合わせ、同一キャリアであることも確認した方がより良いようです。詳しくはコメント欄をご覧ください。実際に動いてすぐ使える「PHPによるかんたんログインサンプル」を作ってみました, ke-tai.org, 2009年7月31日
ここで参照されている「ke-tai.org ケータイキャリア・クローラIPアドレス」の .htaccessファイルには、EMOBILEのEMnetのIPアドレスも「Carrier」として掲載されている。削って使えという指示はなされていない。
検索エンジンのクローラのIPアドレスまで一緒くたにされており、これをそのまま .htaccessとして使用しているサイトは危険な状態にあるだろう。
また、先日の日記「サイボウズ Officeも匙を投げた「簡単ログイン」」の最後にもちらっと書いたように、セキュアな接続が売り文句の「サイボウズ リモートサービス」で、4月12日に以下のアナウンスが出ており、これは、このサービスにも同様の脆弱性があったことを示しているのではないかと疑われる。
「サイボウズ リモートサービス」のセキュリティ強化について
昨今のモバイル市場が広がる中、接続方法が多様化しております。そのため、「サイボウズ リモートサービス」のセキュリティを強化を目的に次の変更を実施いたします。何卒ご理解のほどよろしくお願い申し上げます。
4、影響範囲
下記端末からリモートケータイ用 URL への接続が出来なくなります。
- iPhone
- Softbank X シリーズ
- イー・モバイル ケータイ
では、アクセス元からEMOBILEのEMnetを外せば大丈夫なのかというと、そうとも言えない。冒頭の記事のように、mailwebservice.softbank.ne.jp のAPNで sbwapproxy.softbank.ne.jp:8080 のProxy経由でアクセスするという、SoftBank経由の方法がある。
実は、OpenPNEの3月5日の修正はバージョンによって修正内容が異なっている。OpenPNEでEMOBILEに対応していたのは、一部のバージョン(OpenPNE 2.13〜2.14系列)だけだった。私が指摘した問題に対して対策が施されたのは、このバージョンだけである。他のバージョンの修正点が何だったかというと、OpenPNEにはIPアドレス制限の機能がプログラムとして搭載されている(各キャリアの「IPアドレス帯域」リストがプログラム中に埋め込まれている)ものの、その機能がデフォルトで無効の設定になっているという別の問題があったため、それがデフォルトで有効に変更された(OpenPNE 3.4系列に対するパッチの最後の部分参照)のであった。
EMOBILEに元々対応していなかったというOpenPNE 3.4系列は、IPアドレス制限さえ有効にしていれば安全と言えるのだろうか。つまり、SoftBank経由での、PCからのアクセスに対してどうなのかである。
OpenPNE 3.4系列(の現時点での最新版)では、「かんたんログイン」の実現方法は、上記の ke-tai.org の方式に類似しており、まず、アクセス元のIPアドレスがキャリアのゲートウェイかを判別して(そうでなければPC用画面へリダイレクトし)、ke-tai.org 同様にPEAR(PHP Extension and Application Repository)の、「Net_UserAgent_Mobile」を使用して、契約者固有IDを取得し、取得した契約者固有IDが「かんたんログイン」利用者として登録されたIDに一致すればログインを許可するという構造になっている。ke-tai.org との違いは、IPアドレス制限が、docomo、au、SoftBank(とWILLCOM)に限定されている点である(ソースコードの該当部分)。
ここで、「PEAR::Net_UserAgent_Mobile」の構造がどうなっているかというと、ソースコードの肝心部分は次のようになっている。*3
Net/UserAgent/Mobile.php 300 function isDoCoMo($userAgent = null) { 302 if (is_null($userAgent)) { 303 $userAgent = @$_SERVER['HTTP_USER_AGENT']; 304 } 306 if (preg_match('!^DoCoMo!', $userAgent)) { 307 return true; 308 } ... 323 function isEZweb($userAgent = null) { 325 if (is_null($userAgent)) { 326 $userAgent = @$_SERVER['HTTP_USER_AGENT']; 327 } 329 if (preg_match('!^KDDI-!', $userAgent)) { 330 return true; 331 } elseif (preg_match('!^UP\.Browser!', $userAgent)) { 332 return true; 333 } ... 137 function &factory($userAgent = null) { 139 if (is_null($userAgent)) { 140 $userAgent = @$_SERVER['HTTP_USER_AGENT']; 141 } 144 if (Net_UserAgent_Mobile::isDoCoMo($userAgent)) { 145 $driver = 'DoCoMo'; 146 } elseif (Net_UserAgent_Mobile::isEZweb($userAgent)) { 147 $driver = 'EZweb'; 148 } elseif (Net_UserAgent_Mobile::isSoftBank($userAgent)) { 149 $driver = 'SoftBank'; 150 } elseif (Net_UserAgent_Mobile::isWillcom($userAgent)) { 151 $driver = 'Willcom'; 152 } else { 153 $driver = 'NonMobile'; 154 } 156 $class = "Net_UserAgent_Mobile_$driver"; ... 171 $instance = new $class($userAgent); ... 185 return $instance; Net/UserAgent/Mobile/DoCoMo.php 828 function getUID() { 830 if (array_key_exists('HTTP_X_DCMGUID', $_SERVER)) { 831 return $_SERVER['HTTP_X_DCMGUID']; 832 } 833 } Net/UserAgent/Mobile/EZweb.php 313 function getUID() { 315 if (array_key_exists('HTTP_X_UP_SUBNO', $_SERVER)) { 316 return $_SERVER['HTTP_X_UP_SUBNO']; 317 } 318 }
つまり、User-Agent: によりキャリア別に場合分けして、そのキャリアを担当するオブジェクトを生成しておき、そのオブジェクトに対する getUID() で、各キャリアの独自仕様に基づいた契約者固有IDの取得が行われるようになっている。
したがって、User-Agent: に auのものを記載し、X-Up-Subno: に auの契約者固有IDを記載してアクセスすれば、そのIDが「かんたんログイン」に使用されると考えられる。
ここで、はたして、mailwebservice.softbank.ne.jp のAPN接続 + sbwapproxy.softbank.ne.jp:8080 のProxy経由で、そのようなHTTPリクエストの送達が可能なのかどうかだ。
実際に試してみたところ、そのような送達はできなかった。元記事「SoftBank Mobileの携帯用GatewayをPCで通る方法のメモ」にも書かれていたように、SoftBank用の User-Agent: を送らないと、Proxyサーバでエラーとなるらしい。
UserAgentはどうやらNokiaかSamsungの端末のもので無いと「お客様の端末からはご利用になれません。(WJ46140E)」とエラーが出てはじかれる。
SoftBank Mobileの携帯用GatewayをPCで通る方法のメモ, Perlとかmemoとか日記とか。, 2009年8月1日
しかし、User-Agent: がSoftBankの所定の名称であれば、追加した X-Up-Subno: は削られることなくそのままWebサーバに送られた。
% telnet sbwapproxy.softbank.ne.jp 8080 Trying 172.24.168.97... Connected to sbwapproxy.softbank.ne.jp. Escape character is '^]'. GET http://taruo.net/e/ HTTP/1.1 User-Agent: SoftBank/1.0/(略) X-Up-Subno: 050010〓〓〓〓_mg.ezweb.ne.jp <TR><TD>HTTP_X_JPHONE_REGION (略)</TD><TD><u><tt>44020</tt></u></TD></TR> (略) <TR><TD>HTTP_X_UP_SUBNO (略)</TD><TD><u><tt>050010〓〓〓〓_mg.ezweb.ne.jp</tt></u></TD></TR>
これは、EMnetのときと同じ理由で、ソフトバンクモバイルの脆弱性ではない。
さらに、User-Agent: にSoftBankの所定の名称を与えた上で、その末尾に「KDDI-...」を付け加えた場合を試してみたところ、このProxyサーバはエラーを出さず、このHTTPリクエストはWebサーバに送られた。
つまり、Webアプリケーション側が、User-Agent: からキャリアを判別する際に、たとえば、「KDDI-」の文字列を含むか否かという方法をとっている場合には、「かんたんログイン」でなりすましを許してしまうということになる。
その点、PEAR::Net_UserAgent_Mobile は、上記のソースコード引用部
329 if (preg_match('!^KDDI-!', $userAgent)) {
のとおり、正規表現により、文字列の先頭が「KDDI-」で始まるときにだけ auと判別するようになっているので、この方法については影響を受けないと思われる。このため、OpenPNE 3.x系列(EMOBILE非対応)は、2.14系列(EMOBILE対応)と同様の修正が加えられることはなかった。
では、「文字列を含むか否か」でキャリアを判別しているWebサイト(ないしソフトウェア製品)は実在するだろうか。サンプルコードだが、次のものがあった。
◇ 会員制携帯サイトにおいて、パスワードの入力を省略できる仕組みのご案内です。
◇ 各会員専用のアドレスと、携帯電話から送信される固有の情報を照合し、本人の携帯であることを確認してログインする仕組みです。ダウンロード
これのソースコードの肝心部分は以下のようになっている。*4
cert.cgi 259 $UA = $ENV{'HTTP_USER_AGENT'}; 260 $SN = $ENV{'HTTP_X_UP_SUBNO'}; 262 if (($UA =~ 'UP.B') && ($SN ne "")) { 264 $ua = "ezweb"; ... 267 $UID = $SN; 268 } elsif ($UA =~ /^DoCoMo\/\d/) { 271 $ua = "imode"; ... 275 } elsif ($UA =~ /^J-PHONE\/\d/) { 278 $ua = "j-sky"; ...
au の判別において「UP.B」の文字列を含むか否かで判別している。このような判別アルゴリズムを用いている場合、SoftBank経由で送信された auの契約者固有IDを受け入れてしまうと考えられる。
こうしたサンプルコードは、かなり多くの開発者らに見られていると思われる。Googleで「簡単ログイン」で検索してみると、以下のように、ke-tai.org の「すぐ使える」も、CGI RESCUEのものも、1ページ目に出てくる。
他にも別のパターンがいろいろ考えられるだろう。たとえば、Googleでさえ次のようなコードを書いているようだ。
先日 Google から正式公開された モバイル向け Google Analytics ですが、
このコードは、User-Agent: を参照しないで、上から順に最初に見つかった契約者固有IDを採用するようになっており、SoftBankよりも上に auやdocomoがあるので、SoftBank経由で送信した、X-Up-Subno: や X-DCMGUID: が採用されてしまうだろう。
このように、Webアプリケーションの「かんたんログイン」実装がどうなっているかしだいで、「IPアドレス帯域制限」が破綻していると考えられる。
じゃあ、どういう実装なら安全と言えるかだが、そんなことは私には言えない。ソフトバンクモバイルのProxyが、User-Agent: を見て遮断しているようだけれども、それが、この問題を防ぐことを意図して正式に実施されているものなのか、それとも、たまたま別の意図でそのようにしたものが、偶然に効いているだけなのか、公表されていないのでわからない。将来もそのように動作するのか、何ら保証がない。遮断する User-Agent: の選別アルゴリズムも不明なままだ。さらに言えば、図4の「?」の部分がどうなっているのかも明らかにされていない。
私は、OpenPNE開発者に脆弱性の詳細情報を通知する際に、こうした考え方をすべて伝えた。いちおうベターな実装方法の案は紹介したけれども、そのときは、以下のように、責任を持てない旨を伝えた。
では、どのように実装すればよいか。
それは本来、携帯電話事業者が公表するべきことであって、私からは「どうすれば安全である」という保証ができません。なぜなら、携帯電話会社のProxyゲートウェイが、どのような方針で設計されているのか不明だからです。
以下は、こうすれば安全であるという意味ではありません。(略)
携帯電話会社各社が仕様と実装方法を明らかにしないのだから、こんなものは早くやめるべきだ。
*1 そもそもHTMLソースを見られないことを前提にサイト構築することが間違っているので。
*2 EMOBILEのEMnetの「IPアドレス帯域」は http://developer.emnet.ne.jp/ipaddress.html に掲載されている。
*3 「{」の位置を改変して引用。
*4 elsif ... { の位置を改変して引用。
携帯電話でいろいろなサイトを見ていると、携帯電話からしか見れないようにしている所が結構あります。 別にそれ自体は構いません。いろいろと商売上の事もあるんでしょうから。 問題なのは、携帯から見てるのに「お使いの端末からはアクセスできません」とかほざくサイト..
高木浩光@自宅の日記 – ここまで破綻しているケータイID認証(簡単ログイン) http://takagi-hiromitsu.jp/diary/20100425.html#p01 携帯サイトの簡単ログイン機能に問題提起されて久しいですね。 今回も、セキュリティの専門な高木さんが指摘されています。 内容..
sato モバイルのかんたんログインがざるな件 http://takagi-hiromitsu.jp/diary/20100425.html
かんたんログインを提供しているサイト運営者の背筋を寒くするエントリ第1弾。SoftBankという存在そのものがもはやセキュリティホール・・・。<br /><br />>SoftBankの携帯電話で特定のAPN mailwebservice.softbank.ne.jp でネット接続して、<br />>所定のProxyサーバ sbwapproxy...
高木浩光@自宅の日記 - ここまで破綻しているケータイID認証(簡単ログイン)
携帯認証 自分の中の知識が陳腐化したので、まとめ中。 認証方式 ガラケー(フィーチャーフォン)では「