AI毛毛的blog

对于Android 7.0以上版本设备的抓包方法

最近在一台Android 8.0设备上用fiddler抓包公司app时发现无法解析包内容,换用charles也是同样的结果,于是稍微研究了一下这背后的原因。

通过查阅Android Developer文档,发现在网络安全性配置一节中,有如下描述:

一般情况下,应用信任所有预装 CA。如果有预装 CA 签发欺诈性证书,则应用将面临被中间人攻击的风险。有些应用通过限制信任的 CA 集或通过证书固定来选择限制其接受的证书集。

An app that does not want to trust all CAs trusted by system can instead specify its own reduced set of CAs to trust. This protects the app from fraudulent certificates issued by any of the other CAs.

于是出于安全性考虑,在面向 Android 7.0(API 级别 24)及更高版本应用的默认安全配置如下所示:

1
2
3
4
5
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
</trust-anchors>
</base-config>

而面向 Android 6.0(API 级别 23)及更低版本应用的默认配置如下所示:

1
2
3
4
5
6
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" />
<certificates src="user" />
</trust-anchors>
</base-config>

通过对比可以看出,在7.0之后的版本里,对证书的信任级别默认是系统级别,从某种意义上来说相当于减小了对于证书信任程度的粒度,app可以选择不信任我们手动安装的的fiddler或者charles证书,这就是问题所在,以至于基于https的通信中,中间人身份不被信任,所以无法解析包内容。

关于解决方法,也是非常简单,可以征求app开发人员的意见,修改app中network_security_config.xml的配置,使应用信任我们所需要的证书,然后在AndroidManifest.xml中添加一个区块,包含network_security_config.xml的路径即可,一般如下所示:

1
2
3
4
5
6
7
<?xml version="1.0" encoding="utf-8"?>
<manifest ... >
<application android:networkSecurityConfig="@xml/network_security_config"
... >
...
</application>
</manifest>

基于实验目的,我简单粗暴反编译了一下app,修改默认配置为Android 6.0的配置,果然可以在7.0之后的设备上正常抓包了。