北京顺义二手房安卓应用通信安全(三)-安卓APP安全测试

安卓应用通信安全(三)-安卓APP安全测试
本文主要介绍 SSL Pinning 相关的知识。文中用到的 vuls 漏洞应用及代码可以在https://github.com/AndroidAppSec/vuls/releases/tag/v2.2 中下载。
三、SSL Pinning
在上一篇中,我们介绍到合抱木装修网,如果在手机中安装 burp 证书的话,就可以使用 burp 来抓取应用的 https 通信鹊桥兄弟们 ,并进行安全测试。推而广之,如果在我们使用恶意 wifi 的过程中,被欺骗安装证书的话,就会遭受 https 的中间人攻击黄艳泽。那么有没有什么办法能够缓解这个风险呢?这就是本文要介绍的技术 SSL Pinning隐世灵医 ,中文翻译叫做证书固定。
1、SSL Pinning 基本介绍
通过前两篇的介绍,我们知道验证一个证书是否合法主要通过两个方面:证书签发CA 和 hostname 校验。这里有几个问题:一是,证书签发 CA 的根证书私钥有可能泄漏,从而导致有人可以伪造 CA;二是,CA 在签发证书的时候可能会出现失误血战太行山,导致为其他机构颁发了本机构的证书;三是, hostname 是可以进行伪造的(还记得自签名证书吧)。其实真正标识一个机构身份的是其持有的证书公私钥。所以石田萌美,目前大部分的SSL Pinning 实现,就是去校验证书的公钥信息张媛琦 ,并且很多库默认提供了校验公钥信息的 API。本文我们也主要介绍校验公钥信息的实现。
这里其实有一个问题,公钥信息是公开的,任何人都可以获取到希普曼,之前你说 hostname 是可以伪造的,那么自签名证书也可以伪造你这个组织的公钥啊。没错育狄差,但是这里的公私钥对是通过非对称加密算法产生的(目前一般为RSA)碓氷拓海 ,伪造者是无法通过公钥信息反推出私钥信息的。没有私钥信息镇沅信息网,就无法解密 SSL 握手过程的加密信息,从而无法实施中间人攻击。
2、如何获取公钥信息
还是以百度官网为例,其证书信息如下:

分为三级,从上到下依次为 CA 根证书、中间证书和叶证书(真正标识百度的证书)。我们做 SSL Pinning 的时候,可以对这三个证书都进行固定,也可以只选取其中的部分进行固定。推荐的做法是固定叶证书和中间证书女子按摩诊所 ,这样既验证了网站所有者信息也验证了证书签发机构信息。
验证公钥信息一般采用对比公钥 hash 之后值是否相同的方式。可以使用以下的脚本获取指定网站证书公钥进行 SHA256 哈希之后再 base64 编码的值。
#!/bin/bash
certs=`openssl s_client -connect $1:443 -showcerts </dev/null 2>/dev/null | sed -n '/Certificate chain/,/Server certificate/p'`
rest=$certs
while [[ "$rest" =~ '-----BEGIN CERTIFICATE-----' ]]
do
cert="${rest%%-----END CERTIFICATE-----*}-----END CERTIFICATE-----"
rest=${rest#*-----END CERTIFICATE-----}
echo `echo "$cert" | grep 's:' | sed 's/.*s:(.*)/1/'`
echo "$cert" | openssl x509 -pubkey -noout |
openssl rsa -pubin -outform der 2>/dev/null |
openssl dgst -sha256 -binary | openssl enc -base64
done
获取百度公钥信息如下(橙色标注为结果):
./certs.sh www.baidu.com
C = CN, ST = beijing, L = beijing, OU = service operation department, O = "Beijing Baidu Netcom Science Technology Co., Ltd", CN = baidu.com
M9Hz16jmJjXzPUkH8FUKG2GZLd/55sT6yCNiQgwfNtk=
C = BE, O = GlobalSign nv-sa, CN = GlobalSign Organization Validation CA - SHA256 - G2
IQBnNBEiFuhj+8x6X8XLgh01V9Ic5/V3IRQLNFFc7v4=
3、编码实现
主要介绍一下目前安卓下很火的网络框架 OKhttp 的 SSL Pinning 实现。
OKHttp提供了一个CertificatePinner类可以方便的设置 SSL Pinning,代码如下:

在 add 方法中增加 pinning 信息:第一个参数为请求的域名,支持 * 通配符;第二个参数为公钥哈希信息,以 / 为分隔符,前半部分指定哈希算法,章吉仁后半部分为公钥哈希之后进行 base64 编码的值。可以通过 add 方法添加多个 pinning 信息猎宝天下,这些信息之间是 or 的关系。
可以创建多个CertificatePinner,上图为叶证书的 pinner,下图我们加入中间证书的 pinner:

然后,就可以通过以下代码来构造并发起请求了:

多个CertificatePinner之间是 and 的关系。这样我们就同时校验了叶证书和中间证书。
对于OKHttp 来说,还可以通过以下的小技巧来获取 pinning 信息东方符斗祭 ,即在代码中写入一个错误的哈希信息,这样运行的时候,OKHttp 会在错误日志中打印出目前请求网站证书的公钥的相关信息伍文忠 ,北京顺义二手房如下图:

4、后记
以上的代码是将 pinning 信息硬编码在代码中,实现代码简单,但是破解难度就相对较低了。安全性较高的做法是,将证书预埋在客户端,然后再从证书中读取相关信息;或者是将 pinning 信息放入原生层山口小夜子,并进行混淆加密。
SSL Pinning 虽然能够提升 ssl 通信的安全性十一抽杀律 ,但是还是无法避免被绕过的命运叶俊英 ,我们会在后续的文章中介绍效果的相关方法和技术陈毅锋。
参考:
https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning
https://medium.com/@appmattus/android-security-ssl-pinning-1db8acb6621e