Android 7.0 以上 Charles 和 Fiddler 無法抓取 HTTPS 包的解決方式
https://johnnyshieh.me/posts/android-7-capture-https-package/
發表於 2019-05-06 | 分類於 Android | 0 | 閱讀次數
最近升級了 targetSdkVersion 到 28 后發現在 Android 7.0 以上機型 Charles 抓取 https 包時顯示找不到證書,但是 Android 6.0 機型還是可以正常抓包。原因是因為從 Android 7.0 開始,默認的網絡安全性配置修改了,具體請閱讀官方文檔網絡安全性配置。
問題原因
Android 6.0(API 23)及更低版本應用的默認網絡安全性配置如下:
1
2
3
4
5
6
7
8
9
<!-- 默認允許所有明文通信 -->
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<!-- 信任系統預裝 CA 證書 -->
<certificates src="system" />
<!-- 信任用戶添加的 CA 證書,Charles 和 Fiddler 抓包工具安裝的證書屬於此類 -->
<certificates src="user" />
</trust-anchors>
</base-config>
而在 Android 7.0(API 24)到 Android 8.1(API 27)的默認網絡安全性配置如下:
1
2
3
4
5
6
7
<!-- 默認允許所有明文通信 -->
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<!-- 信任系統預裝 CA 證書 -->
<certificates src="system" />
</trust-anchors>
</base-config>
而在 Android 9.0(API 28)及更高版本的默認網絡安全性配置如下:
1
2
3
4
5
6
7
<!-- 默認禁止所有明文通信 -->
<base-config cleartextTrafficPermitted="false">
<trust-anchors>
<!-- 信任系統預裝 CA 證書 -->
<certificates src="system" />
</trust-anchors>
</base-config>
對比很容易發現,在 Android 7.0(API 24)到 Android 8.1(API 27),默認不再信任用戶添加的 CA 證書,所以也就不再信任 Charles 和 Fiddler 抓包工具的證書,所以抓取 HTTPS 包時才會失敗。而且在 Android 9.0(API 28)及更高版本上,不僅默認只系統預裝的 CA 證書,還默認禁止所有明文通信(不允許 http 請求)。
解決方式
所以解決該問題就需要應用信任 Charles 和 Fiddler 抓包工具的證書抓包工具即可。
最簡單的解決方式是使用 Android 6.0 以下的網絡安全性配置:
添加res/xml/network_security_config.xml
:
1
2
3
4
5
6
7
8
9
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</base-config>
</network-security-config>
然后在清單文件中指向該文件:
1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
<application android:networkSecurityConfig="@xml/network_security_config"
... >
...
</application>
</manifest>
這種解決方式有一個安全風險:正式版的應用會有被他人抓包的風險。
如何只在調試模式下允許抓包呢?
使用<debug-overrides>
即可實現只在android:debuggable
為true
時才生效的配置:
1
2
3
4
5
6
7
8
9
10
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!-- 支持 Android 7.0 以上調試時,信任 Charles 和 Fiddler 等用戶信任的證書 -->
<debug-overrides>
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</debug-overrides>
</network-security-config>
網上有些解決方式是將 Charles 和 Fiddler 的證書添加到raw
文件夾下的方式也可以,但是繁瑣了點。
在 Android 9.0(API 28)以上允許部分 http 請求
最佳的解決方式肯定是全部使用 https 請求,安全性更高,如果有些請求或測試環境下還是需要使用 http 請求,需要在網絡安全性配置添加白名單:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<!-- 支持 Android 9.0 以上使用部分域名時使用 http -->
<domain-config cleartextTrafficPermitted="true">
<domain includeSubdomains="true">sample.domain</domain>
</domain-config>
<!-- 支持 Android 7.0 以上調試時,信任 Charles 和 Fiddler 等用戶信任的證書 -->
<debug-overrides>
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</debug-overrides>
</network-security-config>