Android7.0及以上charles抓包提示证书无效的解决方法

最近在开发百度的百度小程序,进行联调的时候发现只有手机百度APP的https请求不能被抓包,其他应用的https请求都可以被抓包,而且证书也安装正确。一开始怀疑是手百APP的问题,以为APP里面对https证书做了限制,但是和手百的人沟通后发现并没有做限制。后来在搜索这个问题的时候,无意间看见相关搜索中有这么一个词:Android7.0 无法进行https抓包,这才知道原来是Android系统的限制。

在Android7.0及以上的系统中,每个应用可以定义自己的可信CA集。默认情况下,应用只会信任系统预装的CA证书,而不会信任用户安装的CA证书。通过Charles安装的证书恰恰正属于用户安装的CA证书,因此会被视作不安全的证书。

解决方案

方案1:修改APP配置文件

修改APP的android:networkSecurityConfig属性,前提是可以获取到APP的源码。

在AndroidManifest.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>

配置文件:res/xml/network_security_config.xml

1
2
3
4
5
6
7
8
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<certificates src="system" overridePins="true" /> <!--信任系统证书-->
<certificates src="user" overridePins="true" /> <!--信任用户证书-->
</trust-anchors>
</base-config>
</network-security-config>

方案2:将证书安装到系统证书中(需要root)

系统证书的目录是:/system/etc/security/cacerts/

每个证书的命名规则为:<Certificate_Hash>.<Number>

Certificate_Hash表示证书文件的hash值,Number是为了防止证书文件的hash值一致而增加的后缀

证书的hash值可以由命令计算出来,在终端输入openssl x509 -subject_hash_old -in <Certificate_File>,其中Certificate_File为证书路径,将证书重命名为hash.0放入系统证书目录,之后你就可以正常抓包了。

注意事项

小米手机自带root为不完整root,需要进行完整root(即解锁system)。方法如下:

  1. 安装adb工具
1
brew install Caskroom/cask/android-platform-tools # 没有安装homebrew的先安装homebrew
  1. root
1
2
3
adb devices # 测试adb是否安装成功,成功了会出现设备的hash值
adb root
adb disable-verity # 禁用系统验证