为何Android 7.0 以上Charles和Fiddler无法抓取HTTPS包?

软测小生

共 2519字,需浏览 6分钟

 · 2020-09-15

对于之前的文章:Fiddler对安卓App抓包(逍遥模拟器APP)

但是,升级了 targetSdkVersion 到 28 后发现在 Android 7.0 以上机型 Charles 抓取 https 包时显示找不到证书,但是 Android 6.0 机型还是可以正常抓包。原因是因为从 Android 7.0 开始,默认的网络安全性配置修改了



解决方法如下:

现象:android7.0以上的手机https抓包失败(安装了https证书也不行)

原因:android7.0+的版本新增了证书验证(系统证书),具体如下:

1、Android 6.0(API 23)及更低版本应用的默认网络安全性配置如下:

<base-config cleartextTrafficPermitted="true">    <trust-anchors>                <certificates src="system" />                <certificates src="user" />    trust-anchors>base-config>

2、而在 Android 7.0(API 24)到 Android 8.1(API 27)的默认网络安全性配置如下:

<base-config cleartextTrafficPermitted="true">    <trust-anchors>                <certificates src="system" />    trust-anchors>base-config>

3、而在 Android 9.0(API 28)及更高版本的默认网络安全性配置如下:

<base-config cleartextTrafficPermitted="false">    <trust-anchors>                <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 请求)。


解决办法:

前提:在手机端和电脑端都必须安装https的安全证书
配置
测试包时,项目设置默认信任所有证书(系统+用户,Charles 和 Fiddler)
1. 在工程res-xml目录中创建一个名为 network_security_config.xml的文件,文件内容如下:

<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.在AndroidManifest里的标签中,添加如下代码,在清单文件中指向该文件:

<manifest ... ><application android:networkSecurityConfig="@xml/network_security_config"... >        ...application>manifest>


重新打包项目,然后抓包,即可成功。

webview抓包失败

上面可以解决android原生抓包问题,但在android7.0以上的手机,开着网络代理访问不了webview,若要抓包webview,
需要在webview的WebViewClient中,将一行代码给注释掉:

super.onReceivedSslError(view, handler, error)


这样是为了忽略掉SSL证书错误,因为开启代理后网络会变得不安全,证书会报错误,webview检测到证书错误之后就不请求任何数据。注释是为了忽略掉父类的处理,默认执行下去。

警告

这样的配置操作是敏感且危险的,只能用于测试环境方便抓包,线上包一定注意要恢复配置,不然APP会面临被他人抓包的风险。


如何只在调试模式下允许抓包呢?

使用即可实现只在android:debuggabletrue时才生效的配置:


<network-security-config> <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 请求,需要在网络安全性配置添加白名单:


<network-security-config> <domain-config cleartextTrafficPermitted="true"> <domain includeSubdomains="true">sample.domaindomain> domain-config> <debug-overrides> <trust-anchors> <certificates src="system" /> <certificates src="user" /> trust-anchors> debug-overrides>network-security-config>

后记
通过查找资料,还有一个方法,通过重载WebViewClient的onReceivedSslError()函数并在其中执行handler.proceed(),即可忽略SSL证书错误,继续加载页面,代码如下:

WebView webview = (WebView) findViewById(R.id.webview);webview.setWebViewClient(new WebViewClient() {@Overridepublic void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {// 不要调用super.onReceivedSslError,因为其包含了一条 handler.cancel(),第一次访问时无法加载,第二次以后可以加载// super.onReceivedSslError(view, handler, error);// 忽略SSL证书错误,继续加载页面        handler.proceed();    }}

以上内容参考:流柯 和 JohnnyShieh 的博客

软件(自动化)测试微信交流群

欢迎入群

文章合集

Selenium | Appium  | Jenkins  |  Jmeter 

软件测试方法汇总 Postman接口参数化 | 测试用例设计

视频教程

Selenium | Appium | Jenkins | Jmeter


AWS与Docker

如何使用AWS EC2+Docker+JMeter构建分布式负载测试基础架构
Docker容器数据持久化和容器网桥连接
Docker删除image和container
Docker与VM虚拟机的区别以及Docker的特点



END



觉得不错,可以“点赞”和“在看”,或者转发留言


精彩的内容要和朋友分享

浏览 44
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报