目录
Web服务从来就不是安全的,即使使用没有任何问题的代码,它仍然面临着很多威胁。这些威胁万网来自于Web服务本身,一方面来自于通信协议的不安全,另一方面来自于Web服务器的部署。长期以来,Web客户端与web服务端一致使用HTTP通信,而这种协议存在很多问题,从而导致中间人欺骗等多种攻击方式的产生。目前HTTP正逐渐被HTTPS所取代。但针对HTTPS的攻击也从未停止过。
1. HTTPS
1.1. 背景
在说https之前,这里有必要先说一下http,因为 HTTP 是 HTTPS 通讯的基础。
HTTP(HyperText Transport Protocol)超文本传输协议,它用于传输客户端和服务器端的数据。
HTTP 使用很简单也很方便,但却存在以下 3 个致命问题:
- 使用明文通讯,内容可以被窃听。
- 不验证通讯方的真实身份,可能会遭到伪装。
- 无法证明报文的完整性,很容易被篡改。
鉴于以上问题,所以现在的系统会使用 HTTPS 来替代 HTTP。
1.2. 介绍
首先来说,HTTPS 并不是一种新的协议,而是在 HTTP 协议的基础上添加了加密机制 SSL(Secure Socket Layer)或 TLS(Transport Layer Security)。
HTTPS = HTTP + 加密 + 认证 + 完整性保护。
SSL 和 TLS
SSL(Secure Socket Layer)最早是由浏览器开发厂商网景公司开发的,此公司开发了 SSL 3.0 及 3.0 之前的版本,之后便将 SSL 交给了 IETF(Internet Engineering Task Force)Internet 工程任务组的手中,IETF 以 SSL 3.0 为基础开发了 TLS 1.0,所以可以认为 TLS 是 SSL 的“新版本”。
1.3. 作用
1.3.1. 解决信任问题
https首先要解决的是信任问题,也就是身份效验的问题,如果不解决信任问题就会存在服务器伪装,也就是“中间人攻击”的问题。
中间人攻击是指:正常情况下客户端直接访问服务器,而中间人会出现在客户端和服务器之间,恶意篡改双方的通信内容,如下图所示
HTTPS 解决信任问题采用的是数字证书的解决方案,也就是服务器在创建之初,会先向一个大家都认可的第三方平台申请一个可靠的数字证书,然后在客户端访问(服务器端)时,服务器端会先给客户端一个数字证书,以证明自己是一个可靠的服务器端,而非“中间人”。
此时浏览器会负责效验和核对数字证书的有效性,如果数字证书有问题,那么客户端会立即停止通讯,如果没问题才会进行后续的流程。有了数字证书之后,就可以验证服务器端的真实身份了,这样就解决了“中间人攻击”的问题,也解决了伪装的问题。
1.3.2. 解决明文传输和完整性问题
HTTPS使用了非对称加密,也使用了对称加密,下面我来讲讲他怎么实现的。
HTTPS 执行流程如下:
- 客户端使用 HTTPS 访问服务器端。服务器端返回数字证书,以及使用非对称加密,生成一个公钥给客户端(私钥服务器端自己保留)。
- 客户端验证数字证书是否有效,如果无效,终止访问,如果有效:
-
- 使用对称加密生成一个共享秘钥;
- 使用对称加密的共享秘钥加密数据;
- 使用非对称加密的公钥加密(对称加密生成的)共享秘钥。
- 发送加密后的秘钥和数据给服务器端。
- 服务器端使用私钥解密出客户端(使用对称加密生成的)共享秘钥,再使用共享秘钥解密出数据的具体内容。
- 客户端和服务器端就可以使用共享秘钥加密的内容进行交互了。
这样,HTTPS 既保证了安全性,同时又保证了高效性。
另外关于完整性,如果是不完整的数据或有多余的数据,那么在解密时会报错,这样就能间接的保证数据的完整性了。
2. 针对HTTPS的攻击
目前已经出现了多种针对SSL的攻击方法。按照实际思路的不同,这些方法大致可以分为3类。
- 针对SSL设计上的缺陷
-
- BEAST(野兽攻击)
BEAST(CVE-2011-3389)通过SSL/TLS加密的会话中获取受害者的COOKIE值(通过进行一次会话劫持攻击),进而通过篡改一个加密算法的CBC(密码块链)的模式攻击目录。其主要针对TLS1.0和更早版本的协议中的对称加密算的CBC模式。
-
- 4.2. CRIME
CRIME(CVE-2012-4929),全称为Compression Ratio Info-leak Made Easy,这是一种因SSL压缩造成的安全隐患,通过它可以窃取启用数据压缩特性的HTTPS传输的私密COOKIE。在成功读取身份验证COOKIE后,攻击者可以实行会话劫持并发动进一次攻击。
- 针对SSL实现上的缺陷
-
- Heartbleed(心脏滴血漏洞)
Heartbleed(CVE-2014-0160)是一个于2014年4月公布的OpenSSL加密库的漏洞。无论是服务器端还是客户端使用了有缺陷的OpenSSL,都可能遭受攻击。这个漏洞是一种缓存区超读漏洞,它可以读取到本不应该读取的数据。
-
- Gotofail漏洞
- 攻击者可利用“GotoFail”漏洞绕过设备与服务器之间的标准“SSL/TLS”安全验证,发动“中间人攻击”。通过这种方法,攻击者可以拦截用户的计算机和网络连接(包括Wi-Fi信号)之间的流动数据。这个漏洞存在于早期的IOS和OS X系统中,它是由于程序编写失误产生的。
- 利用中间人攻击实现HTTPS降级攻击
这是由MoxieMarlinspike提出的,同时它还开发了一款名为SSLStript的工具来实现这个想法。在使用这个工具的时候,攻击者还是充当客户端和Web服务器之间的中间人,一方面中间人冒充服务器与客户使用HTTP通信,已保证能够进行监听,另一方面再冒充客户端与服务器使用HTTPS通信。这样一来,客户端和Web服务器之间的全部通信都是经过中间人转发。
3. HSTS安全策略
3.1. 背景
在讲述HSTS之前,此处先讲一下HTTPS降级攻击。
很多时候用户在访问一个网站的时候,习惯性的都会直接输入域名。例如我们访问淘宝会直接输入taobao.com。而当你这样输入的时候,浏览器发起的其实是http请求。而如果攻击者这个时候监听的是你的80端口发出请求,然后帮你伪造成https请求,再发送到目标服务器。就可以获取到你的请求资源。如图
为了解决HTTPS的降级攻击,国际互联网工程组织发布了一种互联网安全策略HSTS(HTTP Strict Transport Security),采用HSTS策略的Web服务器将保证浏览器之间的连接使用https。
3.2. 原理
全称HTTP Strict Transport Security,简单说就是强制客户端使用 HTTPS 访问页面。大致原理如下
- 在服务器响应头中添加 Strict-Transport-Security,可以设置 max-age
- 用户访问时,服务器种下这个头
- 下次如果使用 http 访问,只要 max-age 未过期,客户端会进行内部跳转,可以看到 307 Redirect Internel 的响应码
- 变成 https 访问源服务器
3.3. 如何使用
这里以Nginx为例,只需要在配置文件中添加以下内容就可以在服务器上实现HSTS机制
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains"
服务器产生的HSTS响应头格式如下
Strict-Transport-Security: max-age=expireTime [; includeSubDomains] [; preload]
- max-age是必选参数,是一个以秒为单位的数值,它代表着HSTS Header的过期时间,通常设置为1年,即31536000秒。
- includeSubDomains是可选参数,如果包含它,则意味着当前域名及其子域名均开启HSTS保护。
- preload是可选参数,一个浏览器内置的使用HTTPS的域名列表。
如何加入到HSTS Preload List?
- 具备一个有效的证书
- 在同一台主机上提供重定向响应,以及接收重定向过来的HTTPS请求
- 所有子域名均使用HTTPS
- 在根域名的HTTP响应头中,加入HSTS Header,并满足下列条件:
-
- 过期时间最短不得少于18周
- 必须包含includeSubDomains参数
- 必须包含preload参数
目前支持HSTS特性的浏览器如下所示
3.4. 注意
- 这个过程有效避免了中间人对 80 端口的劫持。但是这里存在一个问题:如果用户在劫持状态,并且没有访问过源服务器,那么源服务器是没有办法给客户端种下 Strict-Transport-Security 响应头的(都被中间人挡下来了)。
- 假如你设置的 max-age 时长过长。而在这个期间,你网站的证书又过期或者出了问题,就会出现网站无法访问的情况。所以应该一开始不设置太长的时间,然后随着稳定而增长
- 纯 IP 的请求,HSTS 没法处理,比如 http://2.2.2.2 , 即便响应头中设置了 HSTS,浏览器也不会理会
- HSTS 只能在 80 和 443 端口之间切换,如果服务是 8080 端口,即便设置了 HSTS,也无效
P.S:在 Chrome 中打开 chrome://net-internals/#hsts,添加域名之后,可以让浏览器强制对该域名启用 https,所有的 http 请求都会内部转到 https。
4. 针对HSTS的攻击
4.1. 背景
浏览器中预置的Preload HSTS列表并不一定是静态的,因而很容易受到攻击。在大部分浏览器中,这个列表的内容都是动态的,例如在Chrome中,Preloaded HSTS列表中的强制主机配置为1000天,也就是说1000天之后就会失效。目前的主流浏览器中只有Safari浏览器将Preload HSTS列表的内容设置成静态值。
既然Preload HSTS列表中的表项是有生存周期的,只要这个周期内用户都没有访问目标Web服务器,也就是不会更新,那么在生命周期结束后,这个表项就会失效。针对这一点,黑客设计了一个针对系统时间的攻击方案。
目前操作系统的时间大豆采用网络同步的方式来校验。也就是计算机会每隔一段时间就去网络上的时间服务器来校准时间。目前NTP是最常用的时间同步协议,黑客只需要拦截并篡改目标发出的NTP协议数据包,从而实现针对目标操作系统时间的篡改。
4.2. 攻击工具
有人开发了一款Delorean的工具,可以在Github上下载。关于Delorean有四种工作模式
- 自动模式:默认情况下使用的就是这种,Delorean可以在未来1000天之后找到一个与当前工作容器的月日和星期相同的日期。这样用户很难发现自己的系统时间被篡改了。
- 步进模式(-s):使用此模式,你可以选择跳转到未来的秒数,小时数,天数等。基准日期和时间是运行Delorean的主机的本地日期和时间
- 日期模式(-d):你可以选择套跳转到未来的确切日期和时间
- 随机模式(-r):这种模式使Delorean在每次应答时使用不通的日期和时间,用于测试NTP实现中的整数溢出和其他类似问题
4.3. 不同系统的时间同步机制
此处说明一下两款使用频率很高的linux系统以及Window系统,时如何同步锁时间的
- Ubuntu Linux,它本身不运行NTP后台进程,但默认情况下它被配置为每次网络接口启动时通过“ntpdate”命令进行同步。它使用没有验证的NTPv4消息,因此很容易受到中间人攻击从而被黑客篡改时间。黑客通常会设法强制目标操作系统的网络接口启动或者关闭。当网络接口启动时,就会进行时间同步操作,从而被Delorean拦截请求并操作。
- Fedora Linux,与Ubuntu不同,Febora运行的是一个名为“chronyd”的NTP后台进程,它每分钟都会同步时间。它使用未经验证的NTPv3消息,因此很容易受到中间人攻击从而被黑客篡改时间。默认的时钟设置使用参数“rtcsync”,在该模式中,系统时间每隔11分钟就会更新。攻击者可以使用Delorean来拦截并操作Fedora Linux的通信,并控制请求中的事件,11分钟之后,新的时间将会应用到系统中。
- Windows是主流操作系统中使用NTP最严格的。它虽然没有使用身份验证,但是它实现了一些附加的安全功能,从而导致攻击Windows更加困难。例如,在默认情况下,Windows每周只在周日02:00同步时间,如果此时计算机没有运行,同步在下一次启动时进行(如果是接下来的3天内)。第二个安全特性是Windows中指定了可调整时钟的最大时间差,任何超过最大时间差的修改都会被自动忽略。在Windows系统(WIN7/WIN8)中这个最大时间差设置成15小时;而在Windows Server2012服务器中,这个最大时间差设置为48小时。因此对默认配置的Windows攻击成功的可能性很小。不过,互联网上有很多人建议操作系统应该频繁地同步时间,例如每小时甚至5分钟进行一次。如果用户修改了自己系统的最大时间差,以便经常性地更新系统时间,那么他的计算机就会任意受到攻击
另外,攻击者可能无法一下子将时间串改为目标时间,但是如果他可以将时间调整到下次同步时间的前几秒范围内,就可以再次篡改时间,这样一来就可以通过多次篡改来跳转到目标时间,而一旦目标系统时间被篡改了,就会导致原本的HSTS机制失效。黑客进一步发起攻击就会被迫使用户的通信从HTTPS降级为HTTP。