系统证书
概述
Android 系统将 CA 证书分为两种:用户 CA 证书和系统 CA 证书。Android从7.0开始限制CA证书。只有系统证书才会被信任。用户导入的CA证书是不被信任的。相当于可以理解Android系统增加了安全校验。
解决方法一
AndroidManifest 中配置networkSecurityConfig,App 信任用户 CA 证书,让系统对用户 CA 证书的校验给予通过。
在清单文件AndroidManifest.xml中添加以下代码,开启网络安全配置
<?xml version="1.0" encoding="utf-8"?> <manifest ... > <application android:networkSecurityConfig="@xml/network_security_config" ... > ... </application> </manifest>
新建文件res/xml/network_security_config.xml进行网络安全的配置,通过trust-anchors设置信任的证书,代码如下:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <base-config> <trust-anchors> <certificates src="user" /> <certificates src="system"/> </trust-anchors> </base-config> </network-security-config>
其中<certificates src="user" />就是让App信任用户的证书。若为以下配置,说明其在Debug阶段才信任用户的证书,代码如下:
<?xml version="1.0" encoding="utf-8"?> <network-security-config> <debug-overrides> <trust-anchors> <certificates src="user" /> </trust-anchors> </debug-overrides> </network-security-config>
解决方式二
将 CA 证书安装到系统 CA 证书目录中。
导出burp证书,格式为der
使用openssl 将.der格式转换成pem格式,命令如下
openssl x509 -inform DER -in cacert.der -out burp.pem
使用openssl 获取有效的系统证书文件名
openssl x509 -inform PEM -subject_hash_old -in burp.pem
执行完以后将输出有效的系统证书文件名,如下所示
使用openssl 将证书文件转换为有效的系统证书文件,也就是文件名改为上面输出的系统证书文件名加上".0",具体命令如下所示
openssl x509 -inform DER -in burp.der -out 9a5ba575.0
在目录中可看到生成的系统证书文件,最后生成的系统证书文件导入到手机/system/etc/security/cacerts中,低版本安卓执行命令移动到相应目录即可,高版本安卓无法直接改写system
adb push 9a5ba575.0 /sdcard
Magisk在系统启动的时候会自己加载一些文件,即在/data/adb/modules/目录下,增加相同的目录,把文件复制进去,然后重启就可以在系统凭证里看到了
cp /sdcard/9a5ba575.0 /data/adb/modules/hosts/system/etc/security/cacerts
重启手机后执行chmod命令再次重启手机
chmod 644 /system/etc/security/cacerts/9a5ba575.0 adb reboot
设置代理抓包即可
代理检测
网络代理是一种特殊的网络服务,允许一个终端(一般为客户端)通过这个服务与另外一个终端(一般为服务器)进行非直接的连接,代理协议多作用在应用层。
关键代码
System.getProperty("http.proxyHost"); System.getProperty("http.proxyPort");
解决方法
hook对应检测方法
使用基于VPN的Postern
使用基于iptables的ProxyDroid
不走系统代理
设置proxy(Proxy.NO_PROXY)属性禁止使用代理,客户端直接访问服务器,此时中间人的代理无法起效。若此时配置了代理那么burp将无法抓到数据包但app仍能正常使用(这种情况也有可能APP走了tcp等协议)
关键代码
Proxy.NO_PROXY //connection的请求是直连
解决方法
使用基于VPN的Postern
使用基于iptables的ProxyDroid
v*n代理检测
V*N 协议大多是作用在 OSI 的第二层和第三层之间,所以使用 V*N 时,几乎能转发所有的流量,而代理协议多作用在应用层。
常见检测v*n代码
if (networkInterface.isUp() && networkInterface.getInterfaceAddresses().size() != 0 && ("tun0".equals(networkInterface.getName()) || "ppp0".equals(networkInterface.getName())))
return true;
private void isDeviceInV*N() { try { Enumeration<NetworkInterface> networkInterfaces = NetworkInterface.getNetworkInterfaces(); while (networkInterfaces.hasMoreElements()) { String name = networkInterfaces.nextElement().getName(); if (name.equals("tun0") || name.equals("ppp0")) { stop(); } } } catch (SocketException e) { e.printStackTrace(); } }
解决方法
使用基于iptables的ProxyDroid
案例一
使用一个安装了burp证书的测试机(没有导入系统证书),抓包某社交APP提示网络异常
查看APP的network_security_config.xml文件可以看到只信任系统证书
将证书导入系统证书后再次抓包成功获取数据包
案例二
设置wifi代理后抓包,App提示网络环境存在风险。直接搜索关键代码http.proxyHost,hook发现这些方法都不是app真正进行代理检测的方法
通过搜索proxy定位到方法isProxy
可以知道检测WIFI代理是在so层中进行检测
我们直接hook isWifiProxy方法就可以看到当我们设置wifi代理,返回值为true,如果我们修改
将返回值修改为false重新进入app后不会再提示告警,并成功抓取到数据包
但是进入模块时还是会提示网络错误,在绕过证书邦定后成功抓到相关模块数据包,当然这个案例我们也可以直接使用Postern或者ProxyDroid工具进行转发来绕过代理检测。