当前位置:首页  »  整合营销  »  建站方案
我们来一起说说HTTPS中间人攻击与证书校验
时间:2017-03-23来源:AG8娱乐城网络

一、前言

随着平安的普及,http通信应用越发广泛,但是由于对http不熟悉导致开发人员频繁错误的使用http例如最常见的未校验http证书从而导致“中间人攻击”并且由于修复方案也一直是个坑,导致修复这个问题时踩各种坑,故谨以此文简单的介绍相关问题。

本文第一节主要讲述http握手过程,第二节主要讲述罕见的http中间人攻击”场景,第三节主要介绍证书校验修复方案,各位看官可根据自己口味浏览。

二、HTTPS握手过程

首先来看下http工作原理,上图大致介绍了http握手流程,后续我通过抓包看下每个握手包到底干了些什么神奇的事。

注:本文所有内容以TLS_RSA _WITH_A ES_128_CBC_SHA 加密组件作为基础进行说明,其他加密组件以及TLS版本会存在一定差别,例如TLS1.3针对移动客户端有了很大的改动,现在ECDHE等密钥交换算法与RSA 作为密钥交换算法也完全不一样,所以有些地方和大家实际操作会存在一定出入。

1.TCP三次握手

访问的支付宝的官网www.alipay.com抓取的数据。

2.ClientHello

TLS版本号和随机数random_c这个是用来生成最后加密密钥的因子之一,包括两部分,时间戳和随机数 session-id用来标识会话,第一次握手时为空,如果以前建立过,可以直接带过去从而防止完全握手 CipherSuit加密组件列表:浏览器所支持的加密算法的清单客户端支持的加密签名算法的列表,让服务器进行选择 扩展字段:比如密码交换算法的参数、请求主机的名字,用于单ip多域名的情况指定域名。

3.SeverHello

随机数rando_这个是用来生成最后加密密钥的因子之一,包括两部分,时间戳和随机数 32字节的SID想要重新连接到该站点的时候可以防止一整套握手过程。客户端提供的加密组件中,服务器选择了TLS_RSA _WITH_A ES_128_CBC_SHA 组件。

4.Certificate

证书是http里非常重要的主体,可用来识别对方是否可信,以及用其公钥做密钥交换。可以看见证书里面包括证书的颁发者,证书的使用者,证书的公钥,颁发者的签名等信息。其中IssuerName签发此证书的CA 名称,用来指定签发证书的CA 可识别的唯一名称(DNDistinguishName用于证书链的认证,这样通过各级实体证书的验证,逐渐上溯到链的终止点,即可信任的根CA 如果到达终点在自己的信任列表内未发现可信任的CA 则认为此证书不可信。

验证证书链的时候,用上一级的公钥对证书里的签名进行解密,还原对应的摘要值,再使用证书信息计算证书的摘要值,最后通过对比两个摘要值是否相等,如果不相等则认为该证书不可信,如果相等则认为该级证书链正确,以此类推对整个证书链进行校验。

二级机构的证书。

三、中间人攻击

http握手过程的证书校验环节就是为了识别证书的有效性唯一性等等,所以严格意义上来说http下不存在中间人攻击,存在中间人攻击的前提条件是没有严格的对证书进行校验,或者人为的信任伪造证书,下面一起看下几种常见的http中间人攻击”场景。

1.证书未校验

由于客户端没有做任何的证书校验,所以此时随意一张证书都可以进行中间人攻击,可以使用burp里的这个模块进行中间人攻击。

通过浏览器检查实际的http证书,一个自签名的伪造证书。

2.局部校验

做了局部校验,例如在证书校验过程中只做了证书域名是否匹配的校验,可以使用burp如下模块生成任意域名的伪造证书进行中间人攻击。

实际生成的证书效果,如果只做了域名、证书是否过期等校验可轻松进行中间人攻击(由于chrome做了证书校验的所以会提示证书不可信任)

3.证书链校验

如果客户端对证书链做了校验,那么攻击难度就会上升一个层次,此时需要人为的信任伪造的证书或者装置伪造的CA 公钥证书从而间接信任伪造的证书,可以使用burp如下模块进行中间人攻击。

4.手机客户端Http数据包抓取

上述第一、二种情况不多加赘述,第三种情况就是经常使用的抓手机应用http数据包的方法,即导入代理工具的公钥证书到手机里,再进行http数据包的抓取。导入手机的公钥证书在android平台上称之为受信任的凭据,io平台上称之为描述文件,可以通过openssl命令直接检查我导入到手机客户端里的这个PortSwiggerCA .crt

可以看见是Issuer和Subject一样的自签名CA 公钥证书,另外我也可以通过证书类型就可以知道此为公钥证书,crtder格式的证书不支持存储私钥或证书路径(有兴趣的同学可查找证书相关信息)导入CA 公钥证书之后,参考上文的证书校验过程不难发现通过此方式能通过证书链校验,从而形成中间人攻击,客户端使用代理工具的公钥证书加密随机数,代理工具使用私钥解密并计算得到对称加密密钥,再对数据包进行解密即可抓取明文数据包。

5.中间人攻击原理

一直在说中间人攻击,那么中间人攻击到底是怎么进行的呢,下面我通过一个流行的MITM开源库mitmproxi来分析中间人攻击的原理。中间人攻击的关键在于http握手过程的ClientKeyExchang由于prekei交换的时候是使用服务器证书里的公钥进行加密,如果用的伪造证书的公钥,那么中间人就可以解开该密文得到pre_master_secret计算出用于对称加密算法的master_kei从而获取到客户端发送的数据;然后中间人代理工具再使用其和服务端的master_kei加密传输给服务端;同样的服务器返回给客户端的数据也是经过中间人解密再加密,于是完整的http中间人攻击过程就形成了一图胜千言,来吧。

通过读Mitmproxi源码发现mitmproxi生成伪造证书的函数如下:

通过上述函数一张完美伪造的证书就出现了使用浏览器通过mitmproxi做代理看下实际伪造进去的证书。

可以看到实际的证书是由mimtproxi颁发的其中的公钥就是mimtproxi自己的公钥,后续的加密数据就可以使用mimtproxi私钥进行解密了如果导入了mitmproxi公钥证书到客户端,那么该伪造的证书就可以完美的通过客户端的证书校验了这就是平时为什么导入代理的CA 证书到手机客户端能抓取http原因。

四、证书校验

通过上文第一和第二部分的说明,相信大家已经对http有个大概的解了那么问题来了怎样才干防止这些“中间人攻击”呢?

app证书校验已经是一个老生常谈的问题了但是市场上还是有很多的app未做好证书校验,有些只做了局部校验,例如检查证书域名是否匹配证书是否过期,更多数的根本就不做校验,于是就造成了中间人攻击。做证书校验需要做完全,只做一局部都会导致中间人攻击,对于平安要求并不是特别高的app可使用如下校验方式:

检查证书是否过期

服务器证书上的域名是否和服务器的实际域名相匹配

校验证书链

可参考http://drops.wooyun.org/tips/3296此类校验方式虽然在导入CA 公钥证书到客户端之后会造成中间人攻击,但是攻击门槛已相对较高,所以对于平安要求不是特别高的app可采用此方法进行防御。对于平安有较高要求一些app例如金融)上述方法或许还未达到要求,那么此时可以使用如下更安全的校验方式,将服务端证书打包放到app里,再建立http链接时使用外地证书和网络下发证书进行一致性校验。

此类校验即便导入CA 公钥证书也无法进行中间人攻击,但是相应的维护利息会相对升高,例如服务器证书过期,证书更换时如果app不升级就无法使用,那么可以改一下,生成一对RSA 公私钥,公钥可硬编码在app私钥放服务器。http握手前可通过服务器下发证书信息,例如公钥、方法机构、签名等,该下发的信息使用服务器里的私钥进行签名;通过app里预置的公钥验签得到证书信息并存在内容中供后续使用;发起http连接获取服务器的证书,通过对比两个证书信息是否一致进行证书校验。

这样即可防止强升的问题,但是问题又来了这样效率是不是低太多了?答案是肯定的所以对于平安要求一般的应用使用第一种方法即可,对于一些平安要求较高的例如金融企业可选择第二种方法。

说了挺多,但是该来的问题还是会来啊!现在app一般采用混合开发,会使用很多webveiw直接加载html5页面,上面的方法只解决了java层证书校验的问题,并没有涉及到webview里面的证书校验,对于这种情况怎么办呢?既然问题来了那么就一起说说解决方案,对于webview加载html5进行证书校验的方法如下:

webview创建实例加载网页时通过onPageStart方法返回url地址;将返回的地址转发到java层使用上述的证书校验代码进行进行校验;如果证书校验出错则使用stopload方法停止网页加载,证书校验通过则正常加载。

支付宝官网签名证书。

不只仅进行证书链的校验,此时还会进行另一个协议即OnlineCertifStatuProtocol该协议为证书状态在线查询协议,一个实时查询证书是否吊销的方式,客户端发送证书的信息并请求查询,服务器返回正常、吊销或未知中的任何一个状态,这个查询地址会附在证书中供客户端使用。

5.ServerHelloDone

这是一个零字节信息,用于告诉客户端整个serverhello过程已经结束。

6.ClientKeyExchange

客户端在验证证书有效之后发送ClientKeyExchang消息,ClientKeyExchang消息中,会设置 48字节的premastsecret因为的TLS版本的原因,这里没有显示premast通过密钥交换算法加密发送premastsecret值,例如通过 RSA 公钥加密premastsecret得到EncryptPreMast传给服务端。PreMast前两个字节是TLS版本号,该版本号字段是用来防止版本回退攻击的

从握手包到目前为止,已经呈现了三个随机数(客户端的random_c服务端的random_premastsecret使用这三个随机数以及一定的算法即可获得对称加密AES加密主密钥Master-kei主密钥的生成非常的精妙。

7.ChangCipherSpec

发送一个不加密的信息,浏览器使用该信息通知服务器后续的通信都采用协商的通信密钥和加密算法进行加密通信。

8.EncryptHandshakMessage

验证加密算法的有效性,结合之前所有通信参数的hash值与其它相关信息生成一段数据,采用协商密钥 sessionsecret与算法进行加密,然后发送给服务器用于数据与握手验证,通过验证说明加密算法有效。

9.Change_cipher_spec

EncryptHandshakMessag通过验证之后,服务器同样发送 change_cipher_spec以通知客户端后续的通信都采用协商的密钥与算法进行加密通信。

10.EncryptHandshakMessage

同样的服务端也会发送一个EncryptHandshakMessag供客户端验证加密算法有效性。

11.A pplicatData

经过一大串的计算之后,终于一切就绪,后续传输的数据可通过主密钥masterkei进行加密传输,加密数据检查图中的EncryptApploicatData字段数据,至此http一次完整握手以及数据加密传输终于完成。

http里还有很多可优化并且很多精妙的设计,例如为了防止经常进行完整的http握手影响性能,于是通过sessionid来防止同一个客户端重复完成握手,但是又由于sessionid消耗的内存性能比较大,于是又出现了newsessionticket如果客户端表明它支持SessionTicket并且服务端也支持,那么在TLS握手的最后一步服务器将包含一个“NewSessionTicket信息,其中包括了一个加密通信所需要的信息,这些数据采用一个只有服务器知道的密钥进行加密。这个SessionTicket由客户端进行存储,并可以在随后的一次会话中添加到ClientHello消息的SessionTicket扩展中。虽然所有的会话信息都只存储在客户端上,但是由于密钥只有服务器知道,所以SessionTicket仍然是平安的因此这不仅避免了性能消耗还保证了会话的平安性。

联系我们

你可以通过以下方式和我们取得联系。

  • 点击这里给我发消息
    点击这里给我发消息
  • 15874854112
    13755097459

  • 微信公众号

  • copyright 2016 长沙AG8娱乐城网络. All Rights Reserved.湘ICP备11009444号-2长沙AG8娱乐城网络技术有限公司营业执照代码:914301025595242199
    ×
    在线留言
    姓名:
    *
    手机号:
    *
    咨询内容:
    验证码:
    *