发表日期:2016-12 文章编辑:小灯 浏览次数:2793
在讲解本篇文章之前可以先简单了解一下关于Https、TLS/SSL和CA证书的基础知识
在Android设备中,一般由系统校验服务端数字证书的合法性,用可信CA签发的数字证书的网站才可以正常访问,私有签发的数字证书的网站无法访问(需要手动安装证书并信任)。这种作法不能抵御在用户设备上安装证书(将中间人服务器的证书放到设备的信任列表中,如charles的对https抓包的做法)进行中间人攻击。如果客户端没有做任何主动性的防御,很可能被不法分子利用伪造CA证书进行中间人攻击。受信任的CA(证书颁发机构)有好几百个,任何一家受信任的CA都可以签发任意网站的证书,这些证书在客户端看来都是合法的。如果客户端使用证书锁,它会强制校验服务端的证书,一旦发现不匹配就会禁止通信。
** 1、Certificate Pinning**
其实Certificate Pinning是OkHttp 实现的一个类似于HPKP的技术,目的是为了使客户端可以有主动的信任CA的权利,它的工作原理就是使用预先设置的证书指纹和服务器传过来的证书链中的证书指纹进行匹配,只要有任何一对指纹匹配成功,则认为是一次合法的连接,否则禁止本次链接
** 2、预埋证书**
把数字证书以文件或者字符串的形式写在本地,在SSL握手的时候用本地预埋的证书和服务器传过来的证书进行匹配,如果匹配不成功则禁止本次通信
先贴上代码 以OkHttp为例
** 预埋证书的写法**
首先定义一个类实现类实现X509TrustManager接口,实现对客户端证书链的校验方法和服务端证书链的校验方法,不写的话表示不做任何校验,默认信任所有证书链中的证书
读取客户端预埋的证书
配置Client
new OkHttpClient.Builder() .sslSocketFactory(getSSLFactory(),new MyX509TrustManager).build();
妥妥的几行代码搞定
new OkHttpClient.Builder() .certificatePinner(new CertificatePinner.Builder() .add("b.public.com", "sha256/**********") .add("b.public.com", "sha256/**********") .add("b.public.com", "sha256/**********") .build()) .build();
两种做法相比较之下,Certificate Pinning更为简洁,并且也把指纹和hostname 绑定起来,这样做的好处就是对指定的hostname所在服务器发送过来的证书指纹进行校验,在一定程度上既控制了证书信任同时也考虑到了灵活性。而预埋证书的做法要实现相同的功能,仅仅实现上述代码还不够,还需要在Client配置的时候加上hostnameVerifier校验。
** 完整代码的实现**
String hostname = "publicobject.com"; String pinner = "sha256/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; CertificatePinner certificatePinner = new CertificatePinner.Builder() .add(hostname,pinner) .build();OkHttpClient client = OkHttpClient.Builder() .certificatePinner(certificatePinner) .build(); Request request = new Request.Builder() .url("https://" + hostname) .build(); client.newCall(request).execute();
pinner就是证书指纹,sha256表示的是哈希值得一种算法,pinner也可以是 sha1/*********** ,具体pinner要根据购买证书所支持的配置,SSL Labs这个服务通过hostname可以查看的证书指纹。
在SSL握手的时候,会检查配置中的指纹和服务端传过来的证书证的指纹是否相匹配,只要有一个指纹匹配,则进行下一步,否则直接抛出异常,禁止本次连接。相关源代码实现如下:
public void check(String hostname, List<Certificate> peerCertificates) throws SSLPeerUnverifiedException { List<Pin> pins = findMatchingPins(hostname); if (pins.isEmpty()) return;if (certificateChainCleaner != null) { peerCertificates = certificateChainCleaner.clean(peerCertificates, hostname); }for (int c = 0, certsSize = peerCertificates.size(); c < certsSize; c++) { X509Certificate x509Certificate = (X509Certificate) peerCertificates.get(c);// Lazily compute the hashes for each certificate. ByteString sha1 = null; ByteString sha256 = null;for (int p = 0, pinsSize = pins.size(); p < pinsSize; p++) { Pin pin = pins.get(p); if (pin.hashAlgorithm.equals("sha256/")) { if (sha256 == null) sha256 = sha256(x509Certificate); if (pin.hash.equals(sha256)) return; // Success! } else if (pin.hashAlgorithm.equals("sha1/")) { if (sha1 == null) sha1 = sha1(x509Certificate); if (pin.hash.equals(sha1)) return; // Success! } else { throw new AssertionError(); } } }
OkHttpClient验证证书指纹,在CertificatePinner类中有该方法的作用是确认证书中至少有一个和绑定的指纹是否匹配;如果匹配则Okhttp认为TLS握手成功,如果不匹配则失败,并且抛出SSLPerrUnverifiedException异常。(如果没有证书绑定,则OKHttp认为TLS握手成功)。具体调用过程和实现细节可以查看OkHttp的RealConnection这个类。
目前在网络通信中,中间人的存在是无法杜绝的,因为中间人利用的不是漏洞,而是利用网络协议本身的特性。只要是它又能里转发数据包,并且实现相应的网络协议,就可以接入到终端和服务器之间实现中间人攻击。
在HTTPS网络中想做中间人攻击,必须要在握手之前接入到网络中,一旦HTTPS握手过程结束,之后传输的数据完全都是加密的,解密非常的困难。想要破解加密的数据最简单的方法就是知道浏览器和网站协商的那个密码是什么,但是密码还是在握手过程中被RSA,DSA这种非对称加密算法加密的,不知道私钥还没有办法解密,同时浏览器和网站之间到底使用什么加密算法来进行加密还是在握手之间协商的,而这些方法都是保存在发给浏览器的证书中,于是最简单的方法就是伪造一个证书,同时要实现TLS协议,在握手开始前进行中间人攻击。另外,HTTPS握手过程对密码协商的验证是很严格的,中间验证数据的环节一旦有异常,浏览器和网站都会中断连接,因此伪造SSL证书进行中间人攻击目前是对HTTPS网络最好攻击方式,但是伪造的证书无法经过浏览器的受信检查会给出提示。
更多关于各种中间人攻击的相关知识,我推荐这篇文章,里面有各种攻击手段和原理讲解(http://www.cnblogs.com/LittleHann/p/3741907.html)
HTTPS基础知识
TLS/SSL工作原理
TLS/SSL握手过程
CA证书介绍
日期:2018-04 浏览次数:6658
日期:2017-02 浏览次数:3340
日期:2017-09 浏览次数:3537
日期:2017-12 浏览次数:3425
日期:2018-12 浏览次数:4677
日期:2016-12 浏览次数:4468
日期:2017-07 浏览次数:13540
日期:2017-12 浏览次数:3385
日期:2018-06 浏览次数:4162
日期:2018-05 浏览次数:4346
日期:2017-12 浏览次数:3466
日期:2017-06 浏览次数:3889
日期:2018-01 浏览次数:3836
日期:2016-12 浏览次数:3805
日期:2018-08 浏览次数:4331
日期:2017-12 浏览次数:3593
日期:2016-09 浏览次数:6283
日期:2018-07 浏览次数:3107
日期:2016-12 浏览次数:3125
日期:2018-10 浏览次数:3281
日期:2018-10 浏览次数:3370
日期:2018-09 浏览次数:3463
日期:2018-02 浏览次数:3484
日期:2015-05 浏览次数:3415
日期:2018-09 浏览次数:3209
日期:2018-06 浏览次数:3334
日期:2017-02 浏览次数:3778
日期:2018-02 浏览次数:4234
日期:2018-02 浏览次数:4038
日期:2016-12 浏览次数:3481
Copyright ? 2013-2018 Tadeng NetWork Technology Co., LTD. All Rights Reserved.