2014年9月2日火曜日

Android版KindleにおけるSSLサーバ証明書の検証不備の脆弱性CVE-2014-3908

本稿では、Android版KindleにおけるSSLサーバ証明書の検証不備の脆弱性CVE-2014-3908について、発見の経緯と脆弱性の詳細、起こり得る影響などについて報告します。

発見の経緯

奥一穂さんとfacebook上で会話していて、スマホアプリ等でSSLサーバ証明書の検証をする際に、コモンネームを検証していないアプリの可能性について示唆を受けました。その内容は、奥さんのブログ記事として以下にまとめられています。
Kazuho's Weblog: SSL/TLSライブラリの正しい使い方(もしくは、コモンネームの検証について)
詳しくは上記記事をお読みいただくとして、サーバ証明書の検証の要点としては以下となります。
  • 証明書が信頼された認証局の発行したものであること
  • 証明書の有効期限の範囲内であること
  • サーバ証明書のコモンネームが接続しようとしているサーバと一致していること
これらのうち、コモンネームの検証が漏れているアプリが結構あるのではないかという問題意識に至りました。私は奥さんとの会話の後、そのようなアプリがどの程度あるのか確認してみたくなりました。

しかし、一般にMITMモードを備えたPROXY(Burp Suite、Fiddler等)は、発行元が信頼されていないがコモンネームと有効期限は適切な証明書を発行して返します。下図は、Burp Suiteを用いてIPAのサイトに接続した際の証明書の内容です。発行者がPortSwigger CAとなっていますが、それ以外のコモンネーム(CN)と有効期限は適正です。


このため、Burp Suite等はこの実験の目的には適しません。
ネットでしばらく探してみましたが、適当なものが見当たらなかったため、簡易的なPROXYを自作して試すことにしました。

実験環境

実験の環境は、以前のブログ記事で使用した環境をほぼそのまま使い、Burp Suiteの代わりに自作PROXY(下図のMITM PROXY)を使いました。「被害者のAndroid端末」としては、改造していない(ルート化や証明書の追加をしていない)Nexus 7を用いました。


MITM PROXYには固定のサーバ証明書(正規のもの)が導入されていて、どのサーバーへの接続に対しても、端末との接続にはそのサーバ証明書を用います。このため、ブラウザでこのPROXY経由で接続すると、下記のようなエラーとなります。下図はIPAのサイトにSSL接続しようとした際にiPhone上のGoogle Chromeが表示しているエラーメッセージです。


実験の結果

この状態でAndroid版Kindleを使用すると、通常は通信エラーになります。下図は、サインインの際のエラー表示の様子です。


しかし、テストをしているうちに、Kindleパーソナル・ドキュメントサービスに関しては、上記MITM PROXYにて復号可能な状態でSSL通信をしていることがわかりました。PROXYをBurp Suiteに変更すると通信エラーになるため、証明書のチェックのうちコモンネームの検証がもれていると推測しました。
これはすなわち、この実験で求めていた成果が、意外な大物として釣り上げられたことになります。

下記は、Kindleパーソナル・ドキュメントに対するリクエストの例です。
GET /FionaCDEServiceEngine/FSDownloadContent?type=PDOC&key=FIHKZL674JJEWT…
is_archived_items: 1
currentTransportMethod: WIFI
software_rev: 1141637187
X-ADP-Request-Digest: K+yGNDcBY3j61RPAtEhhbFHEME+sH4Tn550gwjE88v6TE6EYRAu…
Range: bytes=0-
Accept-Language: ja-JP
X-ADP-Authentication-Token: {enc:JfYZXcdve5JIhRIk8Ec9AfFN/2doDyBtfpWsYeFA…
x-adp-alg: SHA256WithRSA:1.0
x-adp-token: {enc:JfYZXcdve5JIhRIk8Ec9AfFN/2doDyBtfpWsYeFAMiImkmQgm3PocVq…
x-adp-signature: IZjXKX5fo1LelIUc0FKNRiaiHt9tDI0b7ZRdXcu3j5ClUmnXvOYBUIi3…
User-Agent: Dalvik/1.6.0 (Linux; U; Android 4.4.2; Nexus 7 Build/KOT49H)
Host: cde-ta-g7g.amazon.co.jp
Connection: Keep-Alive
Accept-Encoding: gzip
以下はレスポンスの例です。生のPDFが返されていることがわかります。
HTTP/1.1 206 Partial Content
Server: nginx
Date: Sat, 01 Feb 2014 09:48:27 GMT
Content-Type: application/pdf
Content-Length: 27318
Connection: keep-alive
x-adp-host: HMKP292P91XQM
Accept-Ranges: bytes
content-disposition: attachment; filename=odawara-tokumaru.pdf; filename*=UTF-8''%6f%64%61%77%61%72%61%2d%74%6f%6b%75%6d%61%72%75.pdf
Hint-Sidecar-Download: 0
Content-Range: bytes 0-27317/27318

%PDF-1.5
%粤マモ
1 0 obj
<</Type/Metadata/Subtype/XML/Length 2885>>stream
<?xpacket begin="" id="W5M0MpCehiHzreSzNTczkc9d"?>
<x:xmpmeta xmlns:x="adobe:ns:meta/">
<rdf:RDF xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#">
<rdf:Description rdf:about="" xmlns:dc="http://purl.org/dc/elements/1.1/"><dc:format>application/pdf</dc:format><dc:title><rdf:Alt><rdf:li>odawara-tokumaru</rdf:li></rdf:Alt></dc:title><dc:creator><rdf:Seq><rdf:li>Microsoft アカウント</rdf:li></rdf:Seq></dc:creator></rdf:Description>
<rdf:Description rdf:about="" xmlns:pdf="http://ns.adobe.com/pdf/1.3/"><pdf:Producer>Microsoft® Word 2013</pdf:Producer></rdf:Description>
<rdf:Description rdf:about="" xmlns:xmp="http://ns.adobe.com/xap/1.0/"><xmp:CreateDate>2014-02-01T17:06:14+09:00</xmp:CreateDate><xmp:ModifyDate>2014-02-01T09:46:44Z</xmp:ModifyDate><xmp:CreatorTool>Microsoft® Word 2013</xmp:CreatorTool></rdf:Description>
</rdf:RDF></x:xmpmeta>【以下略】
なお、レスポンスからPDFデータを取り出したところ、元のPDFと目視レベルで一致していることを確認しました。バイナリでは一致していませんが、Kindleパーソナル・ドキュメントサービス側で加工が入ったと推測します。

この問題の影響

この脆弱性による影響を報告します。
まず、HTTPSリクエストには認証に関する情報が入っていますので、この情報からAmazonへのセッションがハイジャックされる可能性があります。実際にハイジャック可能かどうかまでは追いかけていません。
次に、レスポンスのPDFデータですが、Kindleパーソナル・ドキュメントサービスを利用して、Kindle端末(Android)に機密文書をダウンロードしようとして、それが盗聴されると情報漏洩となります。
しかしながら、例えば空港のフリーWi-Fiなど信頼出来ないネットワークを使って機密文書をKindle端末にダウンロードするというシナリオがどの程度あり得るかというと、絶対にないとは断言できないものの、それほどありそうなシチュエーションとは思えません。
このような状況を考慮して、IPAによる脆弱性深刻度は、「CVSS値 4.0、攻撃条件の複雑さ: 高」としたのだと推測します。私はこの深刻度評価を支持します。

対策

Android版Kindleをアップデート(本稿執筆時点の最新版は4.6.0)することにより脆弱性は解消されます。

アプリケーション開発者がこの問題を確認する方法

アプリケーション開発者が実機テストにてこの問題、すなわちアプリケーションがSSLサーバ証明書のコメンネームを検証しているかどうかを確認するためには、試験用サーバに本番とは別のSSLサーバ証明書(正規のものだがコモンネームの異なるもの)を導入した状態でテストを行い、端末側でエラーになることを確認するとよいでしょう。

まとめ

Android版KindleにおけるSSLサーバ証明書の検証不備の脆弱性CVE-2014-3908について報告しました。たまたまKindleの場合、脆弱性の影響はそれほど大きくないと考えますが、外出先等でよく使う機能に当該の問題があると、大きな影響となります。公衆無線LANを使う機会が多いという方は増えていると思いますが、公衆無線LANが偽AP(アクセスポイント)や事前共有鍵を用いた暗号解読(参照)による盗聴の危険性が常にあることを考えると、SSLによる暗号化が情報漏洩を防ぐ上では重要です。
皆様の開発されるアプリケーションにおかれましても、SSLサーバ証明書のコモンネームの検証ができているか確認を推奨いたします。

2 件のコメント:

  1. Burpの場合OptionsのProxy Listenersで「Generate a CA-signed certificate with a specific hostname」を選ぶと、こちらの指定したhostnameのCNを持つ証明書を使ってくれます(多分Free版も)。「Use a custom certificate (PKCS12)」という選択肢もあります。

    返信削除
  2. websec02+google02 さん、大変有益なアドバイスをありがとうございます。コメントに気づくのが今になり、返信が遅れましたこと、お詫びいたします。目的からして「Use a custom certificate (PKCS12)」の方を選択し、所望の結果を得ました。ありがとうございました。

    返信削除

フォロワー