SSL-pinning
反抓包策略
为了防止中间人攻击,可以使用SSL-Pinning的技术来反抓包。 可以发现中间人攻击的要点的伪造了一个假的服务端证书给了客户端,客户端误以为真。解决思路就是,客户端也预置一份服务端的证书,比较一下就知道真假了。
SSL-pinning有两种方式: 证书锁定(Certificate Pinning) 和公钥锁定( Public Key Pinning)。
证书锁定 需要在客户端代码内置仅接受指定域名的证书,而不接受操作系统或浏览器内置的CA根证书对应的任何证书,通过这种授权方式,保障了APP与服务端通信的唯一性和安全性,因此客户端与服务端(例如API网关)之间的通信是可以保证绝对安全。但是CA签发证书都存在有效期问题,缺点是在 证书续期后需要将证书重新内置到APP中。
公钥锁定 提取证书中的公钥并内置到客户端中,通过与服务器对比公钥值来验证连接的正确性。制作证书密钥时,公钥在证书的续期前后都可以保持不变(即密钥对不变),所以可以避免证书有效期问题,一般推荐这种做法。
####
突破SSL-Pinning抓包
在逆向界,一山更比一山高。 思路是这样的:内置证书或者公钥的时候,常常会有对比验证的函数,直接控制这个函数的返回结果让验证通过不就好了吗。 于是就有了一个突破SLL-Pinning的经典操作:采用Xposed+justTrustme模块。 这个方案使用的是JustTrustMe这个Xposed模块,它所做的事情就是将各种已知的的HTTP请求库中用于校验证书的API都进行Hook,使无论是否是可信证书的情况,校验结果返回都为正常状态,从而实现绕过证书检查的效果。
###
APP抓包相对繁琐,越来越多的 APP 在 https 请求和响应时,为了防止中间人攻击(或中间人抓包),会做证书认证,让抓包工具抓不到请求。
证书认证分单向认证和双向认证,双向认证是相较于单向认证而言的,
单向认证
单向认证就是只在 APP 侧做证书校验,单向认证有现成的解决方法,比如用各种 bypass ssl 校验的 hook 脚本既可让单向认证失效,例如:JustTrustMe 。
如果 APP 的网络请求库有混淆,上述 bypass ssl 脚本无效,也有开源作者开发了自适配的 bypass 程序,可以 hook 混淆后的网络库。比如:JustMePlush 。
双向认证
简单说了下单向认证如何解决,开始说双向认证如何解决。 双向认证除了要在 APP 侧做证书校验外, 对方服务端还要做证书校验。对方服务端是要检测证书的,不提交真正的证书给服务端,肯定会请求失败。
双向认证抓包有两种解决方法:
一是:按照搞定证书的思路去想的话,就是要想办法拿到真正的证书。
二是:Hook SSL 对数据解密数据的地方。
双向认证-扣证书
方法一: 因为 APP 能正常跟服务端通信,所以真正的证书肯定是在 APP 里面。所以就是要想办法从 APP 里抠出证书。抠证书有开源的 Frida Hook 脚本。如下地址是开源作者写的 Frida Hook 脚本 https://gist.github.com/ceres- c/cb3b69e53713d5ad9cf6aac9b8e895d2gfgg 可以把证书从内存里读出来保存到本地,并且证书密码也能读出来,非常的方便。
该脚本的原理是: 因为 APP 在向服务端发请求时, APP 肯定会操作证书,所以如果能找到 APP 操作证书的代码地方, Hook 这部分代码,对参数做些输出打印,证书和证书密码就都有了。
大部分情况下,我们不用非常熟悉安卓原理,比如安卓在代码层面是如何操作证书的(当然熟悉更好)。因为资讯发达,一般灵活借助搜索引擎,灵活查阅资料,可以大体知道这些,就可以尝试去写 Hook 脚本去尝试看看。 查阅资料可以知道,安卓操作证书通常是 java.security.KeyStore 这个类,然后再了解下这个类的用法,参数形式。就可以尝试去 Hook 了。上述脚本就是 Hook java.security.KeyStore 这个类的 load 方法,load 方法的形参就是我们需要的证书和密码。 抠出的证书和密码,配置进 fiddler 或 charles 里面,就可以抓到双向认证的包。 PS: 还要注意证书的格式,抠出的证书可能是 jks 或 bks 格式的,fiddler 可能需要 p12 格式的, 所以要找工具先转换一下格式。
双向认证-ssl-logger
方法二: 如果只是想抓包,还有另一种方法,不需要抠证书的方法。虽然 https 在传输过程中是加密的,但在终端显示的时候,必然会解密,不然 APP 上都没法显示了。所以如果能知道安卓解密 SSL 加解密是哪个类, Hook 这个类, 类里相关方法的输入输出肯定就是传输的明文数据。 所以可以查阅资料,看看相关类的用法,就可以尝试去 Hook 打印输出看看情况。也有开源作者开源了该 Hook 脚本, 比如 5alt 老板在google开源的脚本基础上做了修改了的 ssl_logger 。 https://github.com/5alt/ssl_logger 能够 Hook SSL 加解密的地方,它会把传输的数据保存为 pcap 格式。再使用 wireshark 打开该 pcap文件, 在 wireshark 上就可以看到明文的数据了。
如果要模拟向服务器发送请求的话,还是只能使用第一种方法,因为客服端必须要提交正确的证书,服务端才会正确响应。必须得抠出证书,模拟请求时必须带上证书,才能请求到数据。安卓上的证书好多是 jks/bks格式的, 如果使用 Python requests 库的话, 不支持这个格式, 所以要想办法把证书转成 cert 格式的。
上面两种方法都是使用 Frida 进行 Hook ,所以要有 Root 过的手机和明白Frida 怎么使用就能搞定。 对于爬虫来说,搞定抓包和请求参数加密的问题,大部分 Hook ,都可以通过 Hook 安卓系统 API 来找到 APP 代码位置,或直接搞定。其实很少人能很熟悉安卓系统的各种原理,大部分时候能灵活通过各种关键字能查到相关原理的讲解文献,文献里讲的 API 灵活点拿去 Hook 康康线索,就能搞定很多拉。 其实使用双向认证的 APP 还是少数, 对服务器性能多少有影响。
####
####