一、导言
随着安全的普及,https通信的应用越来越广泛。但是对https的不熟悉导致开发者频繁错误的使用https,比如最常见的就是https证书验证失败导致的“中间人攻击”,又因为修复方案一直是个坑,导致修复这个问题的时候踩了各种坑。因此,本文简要介绍相关问题。
本文第一节主要描述https的握手过程,第二节主要描述常见的“https中间人攻击”场景,第三节主要介绍证书验证和修复方案。读者可以根据自己的口味浏览。
二。HTTPS握手过程
首先我们来看看https的工作原理。上图大致介绍了https的握手过程。然后,我们来看看每个握手包都通过抢包做了哪些神奇的事情。
注:本文所有内容均基于TLS_RSA_WITH_AES_128_CBC_SHA的加密组件,其他加密组件与TLS版本会有一些差异。比如TLS1。3对移动客户端做了很大的改动,现在的ECDHE等密钥交换算法和RSA作为密钥交换算法完全不同,所以有些地方其实是大家 *** 作的。
1。TCP三次握手
我在官网浏览了支付宝www.alipay.com抓取的数据。
2。客户您好
TLS版本号和随机数random_c:这是用来生成最终加密密钥的因素之一。它包含两部分,时间戳和随机数 session-id:用于标识会话,在第一次握手时为空。如果之前已经建立,可以直接取,避免完全握手。Cipher Suites加密组件列表:浏览器支持的加密算法列表。客户端支持的加密签名算法列表允许服务器进行选择。 扩展字段:如密码交换算法参数、请求主机名称、单ip多域名情况下指定域名。
3。断绝你好
随机数rando_s,是用来生成最终加密密钥的因素之一,包含两部分,时间戳和32字节的随机数 SID,可以避免我们要重新连接到这个站点时的一整套握手过程。 在客户端提供的加密组件中,服务器选择了TLS_RSA_WITH_AES_128_CBC_SHA组件。
4。证书
证书是https中非常重要的一个主体,可以用来鉴别对方是否可信,并与其公钥交换密钥。可以看到证书包含了证书的颁发者、证书的使用者、证书的公钥、颁发者的签名等信息。Issuer Name是颁发此证书的CA的名称,用于指定颁发证书的CA的可识别和唯一的名称(DN,可分辨 Name),并用于证书链的身份验证。这样通过对各级实体证书的验证,可以追溯到链的终点,可以是可信的根CA。如果在您自己的端点信任列表中找不到受信任的CA,则此证书被视为不可信。
在验证证书链时,用上一级的公钥解密证书中的签名,还原相应的摘要值,然后利用证书信息计算证书的摘要值。最后通过比较两个摘要值是否相等,认为该证书不可信;如果是,则认为该级别的证书链是正确的,以此类推验证整个证书链。
二级机构证书。
三。中间人攻击
https握手过程中的证书验证环节是识别证书的有效性和唯一性等。所以严格来说,https下不存在中间人攻击。中间人攻击存在的前提条件是没有严格的证书验证或人为信任来伪造证书。让我们来看看几种常见的https“中间人攻击”场景。
1。证书未经验证
由于客户端不做任何证书验证,此时任何证书都可以用于中间人攻击,burp中的这个模块就可以用于中间人攻击。
通过浏览器查看实际https证书是自签名伪造证书。
2。部分验证
做了一些验证,比如在证书验证的过程中,只检查证书的域名是否匹配,利用burp后面的模块可以生成任意域名的伪造证书进行中间人攻击。
实际证书效果如果只有域名、证书是否过期等,很容易被中间人攻击。(chrome会提示证书不可信任,因为已经做了证书验证)。
3。证书链检查
如果客户端验证证书链,攻击难度就上升一级。这时候就需要人为信任伪造的证书或者安装伪造的CA公钥证书来间接信任伪造的证书。您可以使用burp的以下模块进行中间人攻击。
4。抓取移动客户端的Https数据包
上面提到的第一种和第二种情况就不赘述了。第三种情况是我们经常使用的从手机抓取https包的方法,即将代理工具的公钥证书导入手机,然后抓取https包。导入的手机公钥证书在android平台上称为可信凭证,在ios平台上称为描述文件。可以直接查看我们通过openssl的命令导入到手机客户端的这个PortSwiggerCA.crt。
可以看出是同一个自签名CA公钥证书作为颁发者和主体。另外,通过证书类型也可以知道是公钥证书。crt和der格式的证书不支持存储私钥或证书路径(有兴趣的同学可以找证书的相关信息)。导入CA公钥证书后,参考上面的证书验证流程,不难发现这种方法可以通过证书链验证,从而形成中间人攻击。客户端用代理工具的公钥证书加密随机数,代理工具用私钥解密计算对称加密密钥,然后解密数据包抓取明文数据包。
5。中间人攻击原则
一直在说中间人攻击,那么中间人攻击到底是怎么运作的呢?让我们通过Mitm流行的开源库MITM代理来分析一下中间人攻击的原理。中间人攻击的关键在于https握手过程中的ClientKeyExchange。由于pre 密钥交换是使用服务器证书中的公钥进行加密的,如果使用伪造证书的公钥,中间人可以将密文解锁,得到pre_master_secret计算的对称加密算法中使用的master_key,从而获得客户端发送的数据;然后中间工具的代理用服务器的master_key加密传输给服务器;同一个服务器返回给客户端的数据经过解密,再由中间人加密,这样就形成了一个完整的https中间人攻击流程。一张图胜过千言万语。走吧。
通过阅读Mitmproxy的源代码,发现mitmproxy生成伪造证书的函数如下:
通过上面的函数,一个完美伪造的证书出现了。使用浏览器和mitmproxy作为代理来查看实际伪造的证书。
可以看出,实际证书是由mimtproxy颁发的,其中公钥是mimtproxy自己的公钥,后续加密的数据可以用mimtproxy的私钥解密。如果将mitmproxy的公钥证书导入到客户端,伪造的证书可以完美的通过客户端的证书验证。这也是为什么把代理的CA证书导入到手机客户端就能捕获https的原因。
四。证书验证
通过上面第一部分和第二部分的讲解,相信大家对https有了一个大概的了解。那么问题来了。我们如何防止这些“中间人攻击”?
app证书验证一直是老生常谈的问题,但是市面上还是有很多app没有做证书验证,有的只做了部分验证,比如检查证书的域名是否匹配或者证书是否过期,更多的根本不做任何验证,从而造成中间人攻击。证书验证需要完整完成,只做一部分就会导致中间人攻击。对于安全性要求不是特别高的应用,可以使用以下验证方法:
即使导入了CA公钥证书,这种验证也无法被中间人攻击,但是相应的维护成本会比较高。比如服务器证书过期,更换证书时如果app没有升级就无法使用,那么可以更改生成一对RSA公钥私钥。公钥可以硬编码在app里,私钥可以放在服务器里。 在HTTPS握手之前,可以发送证书信息,如公钥、机制、签名等。,通过服务器。发送的信息由服务器中的私钥签名; 证书信息是通过对app中预置的公钥进行校验签名得到的,并存储在内容中以备后用;发起https连接获取服务器的证书,通过比较两个证书的信息是否一致来验证证书。
这样可以避免强势上涨的问题,但是问题又来了。是不是效率太低了?答案是肯定的,所以对于安全性要求一般的应用可以选择第一种方法,对于一些安全性要求高的金融企业可以选择第二种方法。
说了很多,但该来的问题还是会来!现在的app普遍采用混合开发,很多webveiw会用来直接加载html5页面。上述方法只解决了java层的证书验证问题,不涉及webview中的证书验证。这种情况我们该怎么办?既然问题来了,那就一起来说说解决办法吧。webview加载html5的证书验证方法如下:
当webview创建加载网页的实例时,onPageStart方法返回url地址;使用证书验证码将返回的地址转发给java层进行验证;如果证书验证中有错误,请使用stoploading()方法停止网页加载。如果证书验证通过,将正常加载。
官网签名证书。
不仅是证书链检查,此时还会执行另一个协议,即在线证书状态协议。 该协议是证书状态在线查询协议,一种实时查询证书是否被吊销的方式。客户端发送证书信息并请求查询,服务器返回正常、已撤销或未知状态中的任意一种。此查询地址将附加到证书上,供客户端使用。
5。服务器HelloDone
这是一个零字节消息,用于告诉客户端整个服务器hello进程已经结束。
6。ClientKeyExchange
客户端在验证证书有效后发送ClientKeyExchange消息。在ClientKeyExchange消息中,将设置一个48字节的premaster secret(由于的TLS版本,此处未显示premaster)。用密钥交换算法加密发送premastersecret的值,例如用 RSA公钥加密premastersecret得到加密的 PreMaster并发送给服务器。PreMaster的前两个字节是TLS的版本号,该版本号字段用于防止版本回退攻击。
到目前为止,已经出现了三个随机数(客户端的random_c,服务器的random_s,premastersecret)。利用这三个随机数和一定的算法,可以得到对称加密AES的加密主密钥,主密钥的生成非常微妙。
7。更改密码规范
发送一条未加密的消息,浏览器使用这条消息通知服务器,所有后续的通信都将使用协商好的通信密钥和加密算法进行加密。
8。加密握手消息
验证加密算法的有效性,结合之前所有通信参数的哈希值和其他相关信息生成一段数据,用协商密钥会话秘密和算法加密,然后发送到服务器进行数据和握手验证。验证表明该加密算法是有效的。
9。Change_cipher_spec
加密握手消息验证后,服务器还发送change_cipher_spec通知客户端,后续通信将使用协商好的密钥和算法加密。
10。加密握手消息
同样,服务器将为客户端发送加密的握手消息,以验证加密算法的有效性。
十一。应用程序数据
经过一系列的计算,终于万事俱备。稍后要传输的数据可以用主密钥加密。有关加密数据,请参见图中的“加密应用程序数据”字段数据。至此,一次完整的https握手和加密数据传输终于完成。
https中有很多优化和精妙的设计。例如,为了防止完全HTTPS握手影响性能,sessionid用于防止同一个客户端重复完成握手。但是,由于sessionid的内存消耗较大,新的 会话票证再次出现。如果客户端表示支持Session Ticket,服务器也支持,那么在TLS握手的最后一步,服务器会包含一个“NewSession Ticket”消息,其中包含加密通信所需的信息。这些数据是用只有服务器知道的密钥加密的。此会话 票证由客户端存储,可以在后续会话中添加到 ClientHello消息的SessionTicket扩展中。虽然所有的会话信息都只存储在客户端,但是由于密钥只有服务器知道,所以会话 票仍然是安全的,这样既避免了性能消耗又保证了会话的安全性。
最后,我们可以使用openssl命令直观地查看https握手过程:
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)