【技术分享】SSL安全通信杂谈篇

https://p5.ssl.qhimg.com/t015b1085c8a0bc2afe.jpg

SSL安全套接层

SSL安全套接层(Secure Socket Layer)为Netspace所研发,用以保证在Internet上数据传输的完整性和保密性,目前版本为3.0,最新版本为TLS1.2安全传输层协议(Transport Layer Security)。TLS和SSL两者差别极小可以将其理解为SSL的更新版本。


通信过程

SSL介于应用层和网络层之间,位于传输层。应用的数据经过传输层中的SSL进行加密,并增加自己的SSL头,在将加密后的数据传向网络层。

其中具体的通信过程如下:

1. 客户端的浏览器向服务器传送其所支持的SSL协议的版本号,加密算法,随机数,已经其他通讯所需的信息;

2. 服务端根据客户端传送的信息选择双方都支持的SSL协议版本,加密算法等信息和自己的证书传送到客户端(该步骤中可能会存在安全隐患,例如伪造客户端可支持的SSL协议版本过低,可能会导致服务端采取安全等级过低的SSL版本来进行通信);

3. 客户端利用服务器传送过来的信息来验证服务器的合法性,包括证书是否已经过期、证书的颁发机构是否可靠、公钥是否匹配、证书上的域名和服务器端的是否匹配等,如果验证不通过则断开通讯,验证通过则继续通讯;

4. 客户端随机产生一个用于通讯加密的对称密码,通过公钥对其进行加密,然后将加密后的预主密码传给服务器;

5. 服务器通过自己的私钥进行解密来获得通讯加密所使用的预主密码,然后使用一系列算法来产生主通讯密码(客户端也将通过相同的方式来产生相同的主通讯密码);

6. 客户端向服务器发出信息,指明后续的数据通讯将使用加解密的主密码为上以阶段生成的主通讯密码,同时通知服务端客户端的握手过程结束;

7. 服务端同样想客户端指明通讯密码并确认握手过程结束;

8. 握手过程结束。SSL安全通道数据通讯开始,客户端和服务器开始使用相同的对称秘钥进行数据通讯,同时进行通讯完整性校验。


握手过程图解

http://p9.qhimg.com/t015eaad7d49fa92323.png


SSL通讯建立后

从上述通讯过程可以看出,在ssl通讯建立起来之后,不考虑ssl版本上的一些漏洞,通信过程是很安全的,可以有效的防止中间人攻击和运营商劫持等问题,通讯数据的保密性和完整性得到了有效保证。所以针对SSL的相关攻击必须建立在其会话的初始化阶段,例如进行中间人攻击必须在会话建立过程中实现,即在通讯过程中攻击者伪造一个证书,对客户端声称该证书就是服务器证书来骗过客户端,使其信任该证书,并使用该证书来进行通讯,这样用户通讯的信息就会被第三监听,通讯保密性和完整性就被破坏。这种攻击方式也有一定的局限,当使用伪造的证书来建立通讯时,一般攻击者不会获得经过官方机构认证的证书,客户端的浏览器就会发过警告,提醒通信不安全,可以参考访问12306时的浏览器的提示(因为12306使用的是其自建的ca颁发的证书,没有经过官方机构的认证,所以浏览器就默认会认为其证书不安全,并提出告警)。


绕过浏览器校验

尽管通过浏览器去检验证书的合法性会提高攻击的成本,但在某些特殊情况下,还是会绕过浏览器的校验。例如:当我们使用fiddler和Charles这一类的抓包工具时,可以手动将他们的证书添加成为可信证书,所以当我们利用这些工具在本地对相关的系统进行逻辑分析时,并不会收到浏览器的告警。而且浏览器的校验仅仅针对的是web端的应用,对于移动端和其他非web端的应用只能通过其他方式来进行防护,一种比较通用的实现方式是使用SSL Pinning即证书绑定。


SSL Pinning

SSL Pinning可以应用在客户端和服务端的通信是事先约定好的场景中,即服务器的地址和证书是预先知道的,这种场景常见于CS架构的应用中。这样的话,客户端可以事先保存好一份服务器的证书,每次请求与服务器进行通信的时候,将服务器返回的证书与客户端保存的证书进行比对,如果两个证书不匹配,则说明受到了中间人攻击,可以直接中断请求。这样就无法通过伪造证书或者使用第三方证书进行攻击。具体的实现方法大家可以在网上找一下。这里提供iso和安卓的两个示例的网址。

安卓示例:https://developer.android.com/training/articles/security-ssl.html#UnknownCa ;

IOS示例:https://github.com/datatheorem/TrustKit ,大家感兴趣的话可以自己研究一下。


SSL Pinning 代码绕过

通过SSL Pinning可以有效的防止中间人攻击,但是当我们本地做流量代理对相关应用的逻辑进行调试和分析的时候,使用代理工具同样会抓不到数据包,这样会很不方便,不过目前也有解决办法。首先可以通过对应用进行反编译,找到使用SSL Pinning代码的部分对其进行绕过,以安卓为例,通常证书验证逻辑在安卓中的形式为A.B(C),即在A中调用B函数,而B函数会加载C参数。通俗的讲,在客户端启动时,会执行初始化A函数,A函数中会调用一个验证证书的B函数,在A调用B函数的同时,会传个密钥库C参数到B函数,根据B函数的返回结果,A函数决定程序是否继续下去。


绕过方法

所有这里可以有三种方式进行绕过:

1、直接修改A函数逻辑使得无论B函数返回什么A函数都能继续执行;

2、修改B函数使其返回值永远都为真;

3、把C中的证书替换为代理软件的证书。

除了反编译修改代码逻辑外,还可以通过使用插件的方式来绕过SSL Pinning,例如:在安卓系统的手机上获取root权限后,安装xposed框架使用其中的JustTrustMe模块进行绕过;或者在越狱的ios设备上使用SSL Kill Switch等插件进行绕过。

关于SSL相关的知识暂时写到这里,给大家当个参考,请大家多多指正。

(完)