iOS安全系列之二:HTTPS进阶

636 查看

上一篇《iOS安全系列之一:HTTPS》只是介绍了比较偏应用的初级知识,对于想要深入了解HTTPS的同学来说是远远不够的,刚好本人最近工作上也遇到并解决了一些HTTPS相关的问题,以此为契机,决定写这篇更深入介绍HTTPS的文章。

本文分为以下五节:

其中第1节“中间人”是比较常见基础的知识,网上也可以找到相关的资料,如果对中间人攻击已经有了足够的了解,可以跳过。后面几节则是个人在iOS方面的实践总结,除了一些与系统相关的特性外,大部分都是系统无关的通用知识,并且每一章节都比较独立,所以可以直接跳到感兴趣的地方阅读。

1. 中间人攻击

关于HTTPS,我经常会提到的就是中间人攻击,那究竟什么是中间人攻击呢?中间人攻击,即所谓的Main-in-the-middle attack(MITM),顾名思义,就是攻击者插入到原本直接通信的双方,让双方以为还在直接跟对方通讯,但实际上双方的通信对方已变成了中间人,信息已经是被中间人获取或篡改。

当然,本文并不是科普性文章,本节就针对HTTPS攻击,特别是HTTPS在App这一应用场景下的常见的攻击手段进行分析讨论。

由前文我们知道,HTTPS在建立了TCP连接之后,会进行SSL握手(SSL Handshake)来校验证书,协商加密协议和对称加密的密钥,之后就会使用协商好的密钥来进行传输。所以HTTPS攻击一般分为SSL连接建立前的攻击,以及HTTPS传输过程中的攻击;

常见的HTTPS中间人攻击,首先需要结合ARP、DNS欺骗等技术,来对会话进行拦截,

 

1.1 SSL证书欺骗攻击

此类攻击较为简单常见。首先通过ARP欺骗、DNS劫持甚至网关劫持等等,将客户端的访问重定向到攻击者的机器,让客户端机器与攻击者机器建立HTTPS连接(使用伪造证书),而攻击者机器再跟服务端连接。这样用户在客户端看到的是相同域名的网站,但浏览器会提示证书不可信,用户不点击继续浏览就能避免被劫持的。所以这是最简单的攻击方式,也是最容易识别的攻击方式。

此类攻击有个经典的工具:SSLSniff。SSLSniff是大神Moxie Marlinspike开发的工具,该工具一开始是设计用于上一篇文章中提到的Basic Constaints 漏洞的,这类系统级别的漏洞,基本上可以让你不知不觉;现在的操作系统和浏览器基本修复了这一漏洞。但也可以使用SSLSniff来伪造证书实现钓鱼攻击。

防范措施:

钓鱼类攻击,App直接调用系统API创建的HTTPS连接(NSURLConnection)一般不会受到影响,只使用默认的系统校验,只要系统之前没有信任相关的伪造证书,校验就直接失败,不会SSL握手成功;但如果是使用WebView浏览网页,需要在UIWebView中加入较强的授权校验,禁止用户在校验失败的情况下继续访问。

 

1.2 SSL剥离攻击(SSLStrip

SSL剥离,即将HTTPS连接降级到HTTP连接。假如客户端直接访问HTTPS的URL,攻击者是没办法直接进行降级的,因为HTTPS与HTTP虽然都是TCP连接,但HTTPS在传输HTTP数据之前,需要在进行了SSL握手,并协商传输密钥用来后续的加密传输;假如客户端与攻击者进行SSL握手,而攻击者无法提供可信任的证书来让客户端验证通过进行连接,所以客户端的系统会判断为SSL握手失败,断开连接。

该攻击方式主要是利用用户并不会每次都直接在浏览器上输入https://xxx.xxx.com来访问网站,或者有些网站并非全网HTTPS,而是只在需要进行敏感数据传输时才使用HTTPS的漏洞。中间人攻击者在劫持了客户端与服务端的HTTP会话后,将HTTP页面里面所有的https://超链接都换成http://,用户在点击相应的链接时,是使用HTTP协议来进行访问;这样,就算服务器对相应的URL只支持HTTPS链接,但中间人一样可以和服务建立HTTPS连接之后,将数据使用HTTP协议转发给客户端,实现会话劫持。

这种攻击手段更让人难以提防,因为它使用HTTP,不会让浏览器出现HTTPS证书不可信的警告,而且用户很少会去看浏览器上的URL是https://还是http://。特别是App的WebView中,应用一般会把URL隐藏掉,用户根本无法直接查看到URL出现异常。

防范措施:

该种攻击方式同样无法劫持App内的HTTPS连接会话,因为App中传入请求的URL参数是固定带有https://的;但在WebView中打开网页同样需要注意,在非全网HTTPS的网站,建议对WebView中打开的URL做检查,检查应该使用https://的URL是否被篡改为http://;也建议服务端在配置HTTPS服务时,加上“HTTP Strict Transport Security”配置项。

参考:【流量劫持】躲避HSTS的HTTPS劫持

 

1.3 针对SSL算法进行攻击

上述两种方式,技术含量较低,而且一般只能影响 WebApp,而很难攻击到 Native App , 所以高阶的 Hacker,会直接针对SSL算法相关漏洞进行攻击,期间会使用很多的密码学相关手段。由于本人非专业安全相关人员,没有多少相关实践经验,所以本节不会深入讲解相关的攻击原理和手段,有兴趣的同学可以查看以下拓展阅读:

 

防范措施:

这类攻击手段是利用SSL算法的相关漏洞,所以最好的防范措施就是对服务端 SSL/TLS 的配置进行升级:

  • 只支持尽量高版本的TLS(最低TLSv1);
  • 禁用一些已爆出安全隐患的加密方法;
  • 使用2048位的数字证书;

 

1.4 模拟最简单的攻击

经过上述几种攻击方式的说明之后,我们来模拟下最简单的中间人攻击。

中间人攻击步骤方式的上文已经说过了,流量劫持相关操作不是本文重点,可以参考流量劫持是如何产生的?, 本例直接使用Charles来做代理,对流量进行劫持。并使用SSL代理来模拟下对iPhone设备HTTPS请求的中间人攻击,让大家在思考理解中间人攻击方式的同时,了解在开发中如何防范类似的攻击。

 

1) Charles设置代理

在Charles中开启并设置HTTP代理和SSL代理,Menu -> Proxy -> Proxy Setting,设置如图:

HTTP代理设置,注意记住端口号为:8888

SSL代理设置,在Locations上可以设置想要进行SSL代理的域名,这里以百度的百付宝*.baifubao.com为模拟对象。

2) 在iPhone端设置HTTP代理

在Mac上获取当前机器的IP地址:

ifconfig en0:

还有一个简单的方法,按住option+点击顶部菜单栏的WiFi网络图标:

可以看到当前电脑的IP地址为:192.168.199.249

将iPhone连接到与电脑相同的WiFi,在iPhone设置中:无线局域网 -> 已连接WiFi右边的Info详情图标 -> HTTP代理 -> 手动 -> 设置HTTP代理:

设置完成之后,打开Safari随便访问一个网页,初次设置代理的话,Charles会弹出一个iPhone请求代理的确认框,点击Allow即可。然后在Charles上就可以看到iPhone上的HTTP请求了。为了避免Mac上的请求过多影响对被代理iPhone上HTTP请求的查看和调试,可以在Charles取消Mac的代理:Menu -> Proxy -> 取消勾选Mac OS X Proxy 即可。

假如你访问的是被代理的目标 URL http://www.baifubao.com 则打不开网页。因为iPhone的HTTPS请求已经被Charles拦截,但iPhone无法信任Charles的证书,所以SSL Handshake失败,无法建立HTTPS连接。

3) 伪造证书欺骗

在被代理的iPhone上打开Safari,访问http://www.charlesproxy.com/getssl,会弹出安装描述符文件的界面,该描述文件包含了Charles根证书:

注意:这个Charles证书是内置在Charles中的,可以在菜单Help -> SSL Proxying可以直接保存和安装证书。安装后的描述文件可以在iPhone设备的设置 -> 通用 -> 描述文件进行查看和管理。

“安装”完成之后,就会将Charles根证书加入系统可信任证书列表中,使用该证书签发的子证书也会被系统信任。Charles会为之前SSL代理设置中配置的域名生成对应的SSL证书,这样伪造证书的证书就实现了欺骗。可以使用Mac SSL代理查看下:

4) 结果验证

下载百度App,然后登录账号,在我 -> 我的钱包,就会访问百付宝:

看到已成功获取到HTTPS请求包的内容。从这里,我们可以猜测出该App是使用系统默认的校验方式:系统信任了这个中间人服务器返回的SSL证书,App就信任了这一校验,SSL握手成功;而没有对服务器证书进行本地对比校验。这是当下非常多App存在的安全隐患。

这个简单的SSL代理模拟了简单钓鱼式的中间人攻击,大家应该都基本明白了这种攻击方式的所针对的漏洞,以及防范这种攻击方法的措施:

  • 不要随意连入公共场合内的WiFi,或者使用未知代理服务器
  • 不要安装不可信或突然出现的描述文件,信任伪造的证书;
  • App内部需对服务器证书进行单独的对比校验,确认证书不是伪造的;

2. 校验证书的正确姿势

上一节对中间人攻击进行了简单介绍,本节就上一节我们遇到的安全隐患问题,来讨论下在App中,应该怎么校验服务器返回的SSL证书,来保证HTTPS通信的安全。上一篇文章《iOS安全系列之一:HTTPS》有对基本校验过程相关代码进行讲解,本文不会赘述这些细节,而是主要讨论校验证书中几个重要的点:

 

2.1 域名验证

前不久,iOS上最知名的网络开源库AFNetworking爆出HTTPS校验漏洞,该漏洞是因为其校验策略模块 AFSecurityPolicy 内的参数 validatesDomainName 默认为NO,这会导致校验证书的时候不会校验这个证书对应的域名。即请求返回的服务器证书,只要是可信任CA机构签发的,都会校验通过,这是非常严重的漏洞。该漏洞已在v2.5.2版本中修复,对应Git版本号3e631b203dd95bb82dfbcc2c47a2d84b59d1eeb4

这个漏洞以及AFNetworking的相关源码会让很多人以为系统的默认校验是不校验证书对应域名的,实际上并非如此。这里AFNetworking确有画蛇添足之嫌。首先我们查看下系统的默认校验策略:

打印默认校验策略信息:

从打印信息来看,系统的默认校验策略中已包含了域名校验。然后再看AFSecurityPolicy中相关源码:

这其实也是很多开发者在处理异常与默认逻辑分支时会犯的错误,这段逻辑推荐实现方式是: