Android證書分為“用戶證書”和“系統(tǒng)證書”兩種微宝,在設(shè)置->安全->"查看安全證書"列表中虚缎,可以看到“系統(tǒng)”和“用戶”兩個(gè)Tab蚣旱。用戶通過瀏覽器下載安裝或者通過WLAN高級(jí)設(shè)置安裝的證書均為用戶證書钦购。
安裝為系統(tǒng)證書有什么好處呢?
(1)安裝用戶證書必須要設(shè)置開機(jī)密碼翻翩,而且設(shè)置后就不能取消都许,除非先刪掉所有的用戶證書。如果安裝為系統(tǒng)證書就不需要設(shè)置開機(jī)密碼嫂冻,自動(dòng)化操作時(shí)更方便胶征。
(2)Android 7以上版本APP默認(rèn)不信任用戶證書,只信任系統(tǒng)證書絮吵,安裝為用戶證書弧烤,對APP的HTTPS抓包會(huì)失敗。安裝為全局證書才能被所有APP信任蹬敲,方可進(jìn)行HTTPS抓包暇昂。
怎么將Fiddler或Mitmproxy的證書安裝為安卓系統(tǒng)證書呢?
Android的系統(tǒng)證書的存儲(chǔ)位置是/system/etc/security/cacerts伴嗡,證書文件必須是PEM格式急波,而且文件命名必須符合系統(tǒng)證書規(guī)范。
下面是具體的步驟(注意:設(shè)備必須先ROOT):
view plaincopy to clipboardprint?
#?第一步瘪校,先下載好Fiddler或Mitmproxy的證書文件澄暮,PEM或者DER格式均可。??
#?第二步阱扬,獲取有效的系統(tǒng)證書文件名泣懊。??
#?如果是PEM格式的:??
openssl?x509?-inform?PEM?-subject_hash_old?-in?mitmproxy-ca-cert.pem?-noout??
#?如果是DER格式的:??
openssl?x509?-inform?der?-subject_hash_old?-in?FiddlerRoot.cer??-noout??
#?例如,輸出8bbe0e8d??
#?第三步麻惶,轉(zhuǎn)換證書格式為PEM格式馍刮,并重命名證書為有效的系統(tǒng)證書名。??
#?如果是PEM格式的:??
openssl?x509?-inform?PEM?-in?mitmproxy-ca-cert.pem?-out?8bbe0e8d.0??
#?如果是DER格式的:??
openssl?x509?-inform?der?-in?FiddlerRoot.cer?-out?8bbe0e8d.0??
#?第四步窃蹋,上傳準(zhǔn)備好的證書文件到設(shè)備卡啰,例如??
adb?push8bbe0e8d.0?/sdcard/??
#?第五步??
#?以下進(jìn)入adb?shell后操作??
adb?shell??
#?獲取root權(quán)限??
su??
#?重新掛載系統(tǒng),以可以寫入文件到系統(tǒng)目錄??
mount?-o?rw,remount?/system??
#?復(fù)制證書到Android系統(tǒng)證書目錄??
cp?/sdcard/8bbe0e8d.0?/system/etc/security/cacerts??
#?修改證書權(quán)限??
chmod644?/system/etc/security/cacerts/8bbe0e8d.0??
#?上述可整合為一句??
adb?shell"su?-c?'mount?-o?rw,remount?/system;cp?/sdcard/8bbe0e8d.0?/system/etc/security/cacerts;chmod?644?/system/etc/security/cacerts/8bbe0e8d.0;'"??
#?重啟設(shè)備??
adb?reboot??
操作完成之后警没,我們就能在系統(tǒng)證書列表中看到匈辱,如下圖所示:
上述步驟很繁瑣。下面給出一個(gè)我們APP數(shù)據(jù)采集項(xiàng)目中用到的自動(dòng)化腳本杀迹,能夠自動(dòng)完成系統(tǒng)證書的安裝全過程亡脸。支持PEM和DER兩種格式。
view plaincopy to clipboardprint?
#?coding:?utf-8??
#?install_as_android_system_ca.py??
#?添加證書為證書為安卓系統(tǒng)證書??
#?要求:??
#?(1)本地OpenSSL版本?>?1.0;??
#?(2)目標(biāo)設(shè)備已ROOT;??
#?已測試驗(yàn)證:??
#?Android?5.1測試驗(yàn)證通過;??
#?Android?7.0測試驗(yàn)證通過;??
#?注意:Android?6.0尚未驗(yàn)證通過树酪,原因尚不知;??
import?sys??
import?os??
import?subprocess??
def?install(local_ca_path,?device=None):??
"""安裝證書為安卓系統(tǒng)證書
????local_ca_path?-?證書的本地路徑浅碾,支持CER格式和PEM格式;
????device?-?目標(biāo)設(shè)備序列號(hào),若不指定則為默認(rèn)設(shè)備;
????"""??
#?判斷本地證書是否為PEM格式??
????with?open(local_ca_path)?as?f:??
if?'--BEGIN?CERTIFICATE--'?in?f.read():??
#?PEM格式的??
is_pem?=True??
else:??
#?非PEM格式的??
is_pem?=False??
print?'CA?file?"{}"?is?{}?format.'.format(local_ca_path,?'PEM'?if?is_pem?else?'CER')??
#?獲取有效的系統(tǒng)證書文件名??
print?'Generate?valid?android?system?CA?file?name?for?"{}"...'.format(local_ca_path)??
if?is_pem:??
cmd?='openssl?x509?-inform?PEM?-subject_hash_old?-in?{}?-noout'.format(local_ca_path)??
else:??
cmd?='openssl?x509?-inform?der?-subject_hash_old?-in?{}??-noout'.format(local_ca_path)??
print?cmd??
android_system_ca_name?=?subprocess.check_output(cmd,?shell=True).strip()?+?'.0'??
print?'Android?system?CA?file?name?for?"{}"?is:?{}'.format(local_ca_path,?android_system_ca_name)??
#?準(zhǔn)備傳輸?shù)桨沧肯到y(tǒng)的證書,本地路徑??
android_system_ca_filepath?=?os.path.join(os.path.dirname(sys.argv[0]),?android_system_ca_name)??
#?如果是CER格式嗅回,轉(zhuǎn)為PEM格式??
if?local_ca_path.lower().endswith('.cer'):??
print?'Convert?CER?"{}"?into?PEM?"{}"...'.format(local_ca_path,?android_system_ca_filepath)??
if?is_pem:??
cmd?='openssl?x509?-inform?PEM?-in?{}?-out?{}'.format(local_ca_path,?android_system_ca_filepath)??
else:??
cmd?='openssl?x509?-inform?der?-in?{}?-out?{}'.format(local_ca_path,?android_system_ca_filepath)??
print?cmd??
print?subprocess.check_output(cmd,?shell=True)??
#?上傳到SD卡根路徑??
adb_cmd_prefix?='adb?'?if?not?device?else?'adb?-s?"{}"?'.format(device)??
print?'Push?"{}"?onto?device?/sdcard/...'.format(android_system_ca_filepath)??
cmd?=?adb_cmd_prefix?+'push?"{}"?/sdcard/'.format(android_system_ca_filepath)??
print?cmd??
print?subprocess.check_output(cmd,?shell=True)??
#?將證書復(fù)制到系統(tǒng)證書目錄下??
print?'Move?/sdcard/{}?to?/system/etc/security/cacerts,?and?set?permission.'.format(android_system_ca_name)??
cmd?=?adb_cmd_prefix?+'''''shell?"su?-c?'mount?-o?rw,remount?/system;cp?/sdcard/{}?/system/etc/security/cacerts;chown?root:root?/system/etc/security/cacerts/{};chmod?644?/system/etc/security/cacerts/{};'"'''.format(android_system_ca_name,?android_system_ca_name,?android_system_ca_name)??
print?cmd??
print?subprocess.check_output(cmd,?shell=True)??
#?把剛復(fù)制到安卓系統(tǒng)證書目錄下的證書內(nèi)容打印出來及穗,看看是否復(fù)制成功了??
cmd?=?adb_cmd_prefix?+'shell?cat?/system/etc/security/cacerts/{}'.format(android_system_ca_name)??
if?'--BEGIN?CERTIFICATE--'?in?subprocess.check_output(cmd,?shell=True):??
#?完成,提示重啟設(shè)備??
print?'Successed.?Need?to?reboot?the?device?now!'??
else:??
#?失敗了绵载,應(yīng)該是權(quán)限不足埂陆,目標(biāo)設(shè)備沒ROOT??
print?'Failed.?Please?root?the?device?first!'??
if?__name__?==?'__main__':??
try:??
local_ca_path?=?sys.argv[1]??
except?IndexError:??
print?'Usage:?python?install_as_android_system_ca.py?"Local?ca?path(support?.cer?and?.pem)"?[Device]'??
try:??
device?=?sys.argv[2]??
except?IndexError:??
device?=None??
????install(local_ca_path=local_ca_path,?device=device)??