‘壹’ HTTPS 抓包原理以及 android 端如何防止抓包
抓包的基本原理就是中间人攻击 HTTPS 的握手过程 。Mac 上可使用 Charles 进行抓包。本质上就是两段 HTTPS 连接,Client <--> Man-In-The-Middle 和 Man-In-The-Middle <--> Server。使用 Charles 进行抓包,需要 Client 端提前将 Charles 的根证书添加在 Client 的信任列表中。
回顾之前的 HTTPS 的握手过程 ,可以知道 SSL 的核心过程就是客户端验证证书链合法性——客户端检查证书链中是否有一个证书或者公钥存在于客户端的可信任列表中。
手机系统中内置了上百份不同的根证书。Certificate Pinning 的原理其实就是 app 中内置需要被信任的特定证书,app 在验证服务器传过来的证书链时,使用这些特定证书来验证的。
证书的主要作用是公钥的载体,但在实践中我们更多是去 pinning 公钥, SubjectPublicKeyInfo(SPKI) 。这是因为很多服务器会去定期旋转证书,但是证书旋转后,证书中的公钥还是相同的公钥。
如果私钥泄露了,那么服务器端就不得不使用新的私钥做出新的证书。客户端为了预防这种情况,可以提前 pinning 这些新的证书。这样,当服务器替换新的证书时,客户端 app 就可以不做任何改动。
从 SDK 24 开始,Android 支持通过 xml 来配置 certificate pinning,见 Network Security Configuration 。
其中 <pin> 节点接受 SubjectPublicKeyInfo 的 hash 值。
OkHttp 从 2.1 开始直接支持 Certificate Pinning 。
我在项目实践中发现有的服务器并不会在 ssl 握手阶段 将完整的证书链传输过来——只会传证书链中的根证书和叶子证书。如果安卓系统中使用 HttpUrlConnection 访问服务器,抛出如下类似异常:
但是浏览器对于这种缺失中间证书的服务器却能验证通过,主要原因是浏览器访问有完整证书链的网站时,如果发现证书链中有浏览器没有内置的中间证书,那么浏览器会将该证书缓存下来,这样浏览器访问其他没有该中间证书的服务器时,就可以使用这个缓存的中间证书来验证证书链。
解决安卓上出现这个问题的方法是将这个中间证书通过 app 添加到信任证书列表中。我们需要将该中间证书加入到 App 运行时所用的 TrustManager 中。
使用 X509TrustManagerExtensions 可以将证书 pinning 到 app 中。 X509TrustManagerExtensions.checkServerTrusted() 允许开发者在系统对证书链验证通过后,再次使用自己的方法验证证书链。
使用方法如下:
‘贰’ 安卓7.0+https抓包新姿势(无需Root)
在平常的安全测试过程中,我们都会拦截应用程序的HTTPS流量。通过向Android添加自定义CA,可以直接完成此操作。但是,从Android 7.0以上开始,应用程序不再信任客户端证书,除非App应用程序自身明确启用此功能。
在下面这篇文章中,介绍一个新的 Magisk模块,通过Magisk模块自动将客户端证书添加到系统范围的信任存储区,这样就可以完成对App应用程序的Https抓包了。
拦截Android上的HTTPS,只需以下几步:
下面这些步骤做完后,就可以查看浏览器与服务器之间发送的HTTPS流量了。
这种方法同样适用于应用程序的Https流量,因为在默认情况下应用程序会信任所有已安装的用户证书。
补充说明
厂商阻止Https抓包的方式:
阻止应用程序流量被截获的一种方法就是为应用程序本身安装专有证书。这就意味着在每个SSL连接上,服务器提供的证书将与本地存储的证书进行比较。只有服务器可以提供正确的标识,SSL连接才会成功。这是一个很好的安全功能,但实现起来是比较麻烦的,
我们知道从Android7.0开始,默认情况下,应用程序已经不再信任用户证书。
在开发阶段,开发人员可以通过更改应用程序中的AndroidManifest.xml文件,来配置networkSecurityConfig属性,选择接受用户证书,即可完成对应用程序的Https抓包分析测试。
还有一种方法是反编译App,修改和重新编译应用程序,如果该App应用程序有加壳,加密,等配置,那反编译的过程将非常困难。可以在warroom.securestate.com上找到App的反编译教程。
还有另一种方法是将用户证书添加到系统存储中。存储目录位于:/system/etc/security/cacerts,包含每个已安装根证书的文件。但这是需要对/system/etc/security/cacerts目录有读、写的权限,正常的手机没有Root,是不具备此项功能的。如果把手机Root,并且这是一项非常危险的操作。
Magisk是一个“通用无系统接口“,可以在不改变系统本身的情况下创建系统的修改掩码。”Magisk不修改/ system分区目录,所以这是一个非常好的抓包解决方式,其中应用程序已经增强了root检测。通过目标应用程序来激活“Magisk Hide”,使Magisk变得完全不可见。
Magisk还支持相当容易创建的自定义模块。为了将任何用户证书识别为系统证书,我们制作了一个简单的Magisk模块,可以在我们的github上找到: https://github.com/NVISO-BE/MagiskTrustUserCerts
该模块的功能如下,非常基础:
安装完后,Magisk模块的内容安装在/magisk/trustusercerts/上。此文件夹包含多个文件,但最重要的是系统目录。此目录自动与real/ system目录合并,实际上不会触及到/system分区目录。因此,/magisk/trusteusercerts/etc/security/中的所有证书都将以/system/etc/ security结尾。
该模块使用如下:
安装后,证书将显示在系统范围的信任存储中,并受应用程序信任:
当然,如果应用程序自身已做了专用SSL连接,仍然无法拦截HTTPS流量,但这个小模块使Android7.0+应用程序的运行方式与Android之前的7.0以下应用程序相同。
英文原版链接: https://blog.nviso.be/2017/12/22/intercepting-https-traffic-from-apps-on-android-7-using-magisk-burp/
‘叁’ 手机抓包软件禁止了怎么解开
首先找到手机里面的设置,点开之后发现很多菜单。往下翻,找到带有“安全”字样的选项。打开安全选项,可以看到里面有“未知来源”这个选项,在选项上面打勾,打勾之后,会有个安全警示,点确定,这个勾就能打上了,否则就打不上勾。
然后就可以去找到之前下载的安装包,也就是以.apk结尾的文件,点一下之后,就可以安装了,之前的禁止安装提示也不会冒出来,就是这么简单。