home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

技術/Android/Emulator(AVD)の証明書ストアに証明書を追加する

技術/Android/Emulator(AVD)の証明書ストアに証明書を追加する

技術 / Android / Emulator(AVD)の証明書ストアに証明書を追加する
id: 969 所有者: msakamoto-sf    作成日: 2011-05-22 21:08:48
カテゴリ: Android 

自己署名、あるいはAndroidにデフォルトでは含まれていないルート証明書で署名された証明書使ったSSLサイトをAndroid Emulatorで閲覧すると、ブラウザがゼロから起動する度に「信頼できない証明書云々」のポップアップが表示される。
少なくとも 2.1 - 2.3 では、ブラウザの機能としてルート証明書を永続的に証明書ストアに追加する事は出来ない。

しかしAndroid SDKのEmulator上であれば、adb(Android Debug Bridge)からroot権限でファイルシステム上の証明書ストアを直接取得・保存することが出来る。
これにより、Androidにデフォルトでは含まれていない証明書をEmulator上に追加することが出来る。

参考:

基本方針としては

/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

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)
                                     ^^^^^^^^^^^^^^^^
...

参考:

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のドキュメントを参照。

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と、提示された証明書のホスト名が異なってしまい、上記の警告が表示されてしまう。

CONNECTリクエストの引数で、普通はホスト名を渡してくるものだが、
QEMUは自身で名前解決を行った後のIPアドレスを渡してくる。

この問題の対処方法として、BurpSuiteの場合、

generate a CA-signed certificate with a specific hostname:

でホスト名を決め打ちで証明書を生成する方法があり得る。

特定のホスト間のHTTPSしかテストしないのであれば、これを使えば問題ないだろう。他のホストへのHTTPSリクエストでは「ホスト名が異なる」警告が表示されてしまうが、テストと割り切って許容する。

もしもBurpのデフォルトのProxy(8080)にこれを設定するのが煩わしければ、別のポート番号を使ってそのホスト名専用のProxyを追加するとよい。対象となるホストのHTTPS通信をテストするときのみ、そのProxyを使ってAVDを起動すれば良い。



プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2011-05-22 21:14:35
md5:c250f281a7d338a5d1421ae66ffdb4d9
sha1:b0be625007565747200aab1d453a9572cad3ccb7
コメント
コメントを投稿するにはログインして下さい。