#navi_header|技術| 自己署名、あるいはAndroidにデフォルトでは含まれていないルート証明書で署名された証明書使ったSSLサイトをAndroid Emulatorで閲覧すると、ブラウザがゼロから起動する度に「信頼できない証明書云々」のポップアップが表示される。 少なくとも 2.1 - 2.3 では、ブラウザの機能としてルート証明書を永続的に証明書ストアに追加する事は出来ない。 しかしAndroid SDKのEmulator上であれば、adb(Android Debug Bridge)からroot権限でファイルシステム上の証明書ストアを直接取得・保存することが出来る。 これにより、Androidにデフォルトでは含まれていない証明書をEmulator上に追加することが出来る。 参考: - AndroidエミュレータでSSL(Https)通信 - papakingの日記 -- http://d.hatena.ne.jp/papaking_ken/20100614/1276496878 - ImportRootCert - CAcert Wiki -- http://wiki.cacert.org/ImportRootCert 基本方針としては /system/etc/security/cacerts.bks これをEmulatorから取り出し、JREのkeytoolを使って証明書を追加してEmulatorに戻す。 検証バージョン: 2.1-update1 (API Level 7) revision 2 2.2 (API Level 8) revision 2 2.3.3 (API Level 10) revision 1 #more|| * 1. system.imgをバックアップ or コピーする。 cacerts.bksは "/system/" 配下にあり、このディレクトリはQEMUをベースとしているEmulatorから見ると "system.img" に含まれている。ここでAndroid SDKに含まれている system.img の「原本」を直接操作すると、Android Virtual Device (AVD)の全てでその証明書が追加されることになる。 操作に失敗した時を想定し、予めsystem.imgのバックアップをしておくとよい。 system.imgは以下のフォルダにある。 (SDK)/platforms/android-(バージョン)/images/system.img ターゲットとなるAVDのバージョンは (HOME)/.android/avd/(AVD名).ini を見ると target=android-7 という設定があるので、そこで知ることが出来る。 もしも特定のAVDでのみ証明書を追加したい場合は、system.imgを (HOME)/.android/avd/(AVD名).avd/ 以下にコピーすればよい。 * 2. "-partition-size"オプションを指定してAVDを起動する。 デフォルトでは "/system" の空き容量が0で起動してしまう。これでは証明書を追加してサイズが増加したcacerts.bksをAVDにアップロードできない。 例: > adb shell df ... /system: 73600K total, 73600K used, 0K available (block size 4096) ^^^^^^^^^^^^ ... この問題を解決するためには emulator コマンドの"-partition-size" オプションを指定する。なおこのオプションはAndroid SDKの公式ドキュメントには記載されていないため、将来も利用出来るかは不明。恐らくqemu自体の機能と思われる。 > emulator -avd AVD名 -partition-size 128 → "/system" が128MBでmountされる。 > adb shell df ... /system: 127104K total, 74636K used, 52468K available (block size 4096) ^^^^^^^^^^^^^^^^ ... 参考: - Using the Android Emulator | Android Developers -- http://developer.android.com/guide/developing/devices/emulator.html * 3. cacerts.bks をホストマシンにダウンロードする。 adbの"pull"コマンドを使ってホストマシンにコピーする。 > adb pull /system/etc/security/cacerts.bks * 4. JREのkeytoolを使って証明書を追加する。 cacerts.bksに追加するためには http://bouncycastle.org/ の提供するjarファイルが必要。 http://bouncycastle.org/download/bcprov-jdk16-141.jar ダウンロードしたjarファイルを (使用するJRE)/lib/ext/ 以下に配置する。 keytoolの使い方についてはJDKのドキュメントを参照。 - JDK の開発ツール > セキュリティーツール > keytool -- http://java.sun.com/javase/ja/6/docs/ja/technotes/tools/index.html#security BurpSuiteの生成するPortSwiggerのルート証明書を追加する例:(事前にWebブラウザ経由などで .crt ファイルを取り出しておくこと) keytool -keystore cacerts.bks -storetype BKS \ -provider org.bouncycastle.jce.provider.BouncyCastleProvider \ -storepass changeit \ -importcert -trustcacerts -alias PortSwiggerCA -file PortSwiggerCA.crt * 5. cacerts.bks をEmulator上のAVDにアップロードする。 デフォルトでは "/system" が書き込み禁止でmountされている。書き込み可能にするためには adb の "remount" コマンドを実行する。 > adb remount 続いて adb の "push" コマンドで cacerts.bks をアップロードする。 > adb push cacerts.bks /system/etc/security/cacerts.bks 以上が任意の証明書を証明書ストアに追加する手順となる。 * おまけ:HTTPSをProxy経由でリクエストするときのAndroid Emulatorの注意点 BurpSuiteの"proxy" > "options" > "proxy listeners" のProxy設定で、 server SSL certificate: -> generate CA-signed per-host certificates となっている(デフォルト)場合に > emulator -avd xxyy -http-proxy 127.0.0.1:8080 などでBurpSuiteのProxyを通していると、HTTPSで「ホスト名が証明書と異なります」という警告が表示される。 これはAndroid EmulatorのベースとなっているQEMUの動作が原因で、ホスト名ではなくIPアドレスをProxyに渡してくる。このためBurp側ではIPアドレスで証明書を生成する。これによりEmulator上のブラウザからみるとリクエストしたURLと、提示された証明書のホスト名が異なってしまい、上記の警告が表示されてしまう。 - AndroidアプリケーションのSSL通信をプロキシで解析する(1) ≪ JUMPERZ.NET Blog -- http://kanatoko.wordpress.com/2011/02/24/android_hook_ssl_by_proxy/ --- "0x06. 余談" 参照 >CONNECTリクエストの引数で、普通はホスト名を渡してくるものだが、 >QEMUは自身で名前解決を行った後のIPアドレスを渡してくる。 この問題の対処方法として、BurpSuiteの場合、 generate a CA-signed certificate with a specific hostname: でホスト名を決め打ちで証明書を生成する方法があり得る。 特定のホスト間のHTTPSしかテストしないのであれば、これを使えば問題ないだろう。他のホストへのHTTPSリクエストでは「ホスト名が異なる」警告が表示されてしまうが、テストと割り切って許容する。 もしもBurpのデフォルトのProxy(8080)にこれを設定するのが煩わしければ、別のポート番号を使ってそのホスト名専用のProxyを追加するとよい。対象となるホストのHTTPS通信をテストするときのみ、そのProxyを使ってAVDを起動すれば良い。 #navi_footer|技術|