Host-of-Troubles 多Host歧义攻击 HTTP实现导致的多重Host歧义
今天分析的这篇论文在2016年于CCS会议发表,题目是《Host of Troubles: Multiple Host Ambiguities in HTTP Implementations》,其DOI信息在这里。
这篇文章给我耳目一新的感觉。各厂商在实现通用协议时,为了兼容性或是设计考虑不周,得到的产品往往比协议规定宽泛。在不同产品的宽泛协议实现之间,也许存在着一些非常严重的漏洞。
概述
在HTTP请求中,Host头是一个与安全密切相关的元素。它是执行安全性和缓存策略的基础。虽然目前的规范通常明确了如何解析和解释与主机相关的协议字段,但这篇文章发现这些实现是有问题的。文中测试了大量广泛使用的HTTP实现,并发现了许多不兼容和不一致的主机处理行为。当面对一个精心设计的HTTP请求(例如有多个Host头)时,两种不同的HTTP实现方式通常得到不同的接受、理解结果。文中展示了许多能够引起对HTTP实现之间主机不一致的解释的技术,以及不一致性如何导致严重的攻击,如HTTP缓存中毒和安全策略旁路。这个问题的普遍存在,突出了互联网协议的规范和实现之间的差距可能带来的负面影响。
HTTP请求
一个HTTP请求包含请求起始行、0或多个请求头与可选的消息正文。请求起始行与请求头指定了HTTP协议字段。在一个请求中,HTTP协议字段的重要作用之一是使接收者能够定位到请求的资源。在HTTP 1.0协议中,唯一一个具有此目的的是请求行中的请求目标。请求目标可以是以“/”开头的、基于主机的路径,或者是一个由模式、主机和路径组成的绝对URI。后者设计的目的在于支持透过代理的资源访问,但是终端系统也会接受请求行中的绝对URI。HTTP 1.1协议引入了Host字段,用于支持多主机环境下的请求路由选择,例如在同一IP地址上部署多个网站。这些网站被不同的域名隔离。
HTTP是一个明确支持中间媒介的C/S协议。文中分析了5类广泛配置的媒介:前向代理、拦截代理(透明缓存)、反向代理、内容分发网络(CDN)与防火墙。文中把发送请求的设备称为下游(downstream),接收请求的设备称为上游(upstream)。
这些中间媒介的一个重要且密切相关的不同点在于它们怎样处理HTTPS流量。前向代理、透明缓存与基于网络的防火墙不能检查基于HTTPS的HTTP信息,除非它们作为TLS/SSL的中间人(man-in-the-middle)。形成对比的是,对于支持HTTPS的反向代理与CDN,HTTPS连接能够终止。
多重Host歧义
一般地,处理HTTP请求可以分为两个阶段:第一是解析文字信息,以识别有效的协议字段,并将识别出的字段翻译为语义结构;第二是用语义结构进行进一步操作。具有无效字段的请求应该在第一阶段拒收,并回复4XX客户端错误信息。
在处理HTTP请求的过程中,重点之一是如何处理主机字段,因为Host是资源定位、请求路由选择、缓存等的重要协议字段。对于一个精心制作的、来自敌方的请求,当两个当事人在对一个HTTP处理链的解析和解释处理不同的时候,出现多重Host歧义。由于其语义上的重要性,两个当事人之间的不一致常常导致灾难性的后果。
文中一共对33个广泛使用的HTTP实现进行了黑盒测试,以观测多重Host歧义问题,其中包括6种服务器、2种透明缓存、3种前向代理、7种反向代理、8个CDN与9种防火墙。有的软件具有多个功能,如Squid可以配置为透明缓存、前向代理与反向代理,文中用名称(类别)进行区分。

通过检测下游-上游对(downstream-upstream pair),文中指出了3种攻击方法。下面分别介绍。
多个Host头
RFC 7230中明确指出,当存在多个Host头时,请求应被拒绝,并回复400 Bad Request。但是在测试的33个实现中,有25个没有遵守这条标准。Apache(服务器,反向代理)将这些Host头隐式地组合成一个无效的主机;OS X(防火墙)似乎也是这样。剩下的22个,除腾讯(CDN)与ESET(防火墙)采用最后一个头外,其余都采用第一个头。
空格包围的Host头
空格包围的Host头可以分为3种:第一个头前具有空格、其它头前具有空格、头后具有空格。对于第1和3种情况,RFC 2616没有明确要求。对于第2种,RFC 2616要求将其看作前一行的折叠,应将其前面的换行符去掉,并与前一行连接。 RFC 7230对于这3种情况均有明确要求。对于第1种,要求拒绝或忽略;对于第2种,虽然废弃了折叠,但为了兼容仍允许代理与服务器按折叠行处理;第3种则被禁止。
绝对URI作为请求目标
RFC 2616与RFC 7230均要求服务器接受绝对URI作为请求目标,并要求优先考虑请求目标而不是Host头。RFC 7230还要求Host头应与绝对URI的主机名相同。但是,不同的实现方式对这个要求有较大差异。除Akamai(CDN)外,所有实现均遵守RFC,优先使用绝对URI。但只有Azure(CDN)做了同一性检查。转送时,除LiteSpeed(反向代理),大多数实现将绝对URI重写为它的路径,并添加Host头。无法识别时,Lighttpd(反向代理)、Varnish(反向代理)与Fastly(CDN)直接转送绝对URI。
##攻击方式
以下介绍两种类型的攻击,每个方式有两个方式。
### HTTP缓存中毒
第一种攻击方式利用了Squid(透明缓存)之间的不一致,以攻击任意未加密网站。攻击者首先与attack.com建立TCP连接,Squid作为中间代理拦截和调整了这个连接。攻击者之后将victim.com作为请求的绝对URI,并指定attack.com作为Host头。Squid识别请求是victim.com,但在检查IP地址时错误地使用了Host头,也就是attack.com。因此,代理将请求发给指定attack.com,但将回复作为victim.com的内容缓存下来。
第二种攻击方式利用了上游与下游的不一致。例如,攻击者注册了Akamai的服务,使用域名为akamai-attack.com,以攻击akamai-victim.com。攻击者生成一个恶意请求,使Squid认为请求属于akamai-victim.com,但Akamai认为属于akamai-attack.com。
过滤绕过
第一种攻击方式影响了防火墙的黑名单规则。例如,ESET的黑名单里有block.com,于是攻击者可以生成一个请求,让ESET认为其访问的是allow.com,但服务器认为是block.com,于是返回block.com的内容。
第二种攻击方式可以绕过多主机环境下的保护。例如,攻击者以域名protectdisabled.com注册CloudFlare与Fastly,以攻击protectenabled.com。protectenabled.com被CDN的安全功能保护。攻击者首先取消对protectdisabled.com的所有保护,之后生成一个具有歧义和攻击负载(如SQL注入)的请求。CloudFlare与Fastly认为请求属于不具有安全保护的protectdisabled.com,但上游认为请求属于protectenabled.com。上游信任来着CDN的请求,于是攻击成功。
总结
标准是人为制定的,难免有疏漏之处;程序是人为编写的,难免有兼容问题。这篇论文对标准的疏漏与不同HTTP实现方式之间的理解歧义进行了研究,方向十分新颖。有一句话说,“最大的漏洞就是人”。或许正是如此吧。
此篇博客是学习陈建军博士的一篇关于<<Host of Troubles: Multiple Host Ambiguities in HTTP Implementations>>的论文,以下是建军博士的论文和 PPT 网址。
论文地址:Host of Troubles: Multiple Host Ambiguities in HTTP Implementations :
Host of Troubles官网:https://hostoftroubles.com/
首先我们回顾下 HTTP协议的请求头部
常用头域:
|
常用头域名称 |
作用描述 |
|
Cache-Control |
缓存控制 |
|
Connection |
HTTP 1.1默认是支持长连接的(Keep-Alive),如果不希望支持长连接则需要在此域中写入close |
|
Date |
表明消息产生的日期和时间 |
|
Pragma |
|
|
Trailer |
|
|
Transfer-Encoding |
告知接收端为了保证报文的可靠传输,对报文采用了什么编码方式 |
|
Upgrade |
给出了发送端可能想要”升级”使用的新版本或协议 |
|
Via |
显示了报文经过的中间节点(代理、网关) |
请求头域:
实体头域:
|
实体头域名称 |
作用描述 |
| Allow | 指明被请求的资源所支持的方法,如GET、HEAD、PUT |
| Content-Encoding | 指明实体内容所采用的编码方式 |
| Content-Language | 指明实体内容使用的语言 |
| Content-Length | 指明请求实体的字节数量 |
| Content-Location | 可以用来为实体提供对应资源的位置 |
| Content-MD5 | 指定实体内容的MD5,用于内容的完整性校验(base64的128位MD5) |
| Content-Range | |
| Content-Type | 指定实体的媒体类型 |
| Expires | 指明实体的过期时间 |
| Last-Modified | 指明实体最后被修改的时间 |

HTTP协议中最关键的字段--Host,如果Host理解出现歧义,后果很严重,以下介绍多种多 Host 造成任意两个链路中歧义的原因.
1、多Host头
发送带有多 Host 的http 请求,downstream 与 upstream 可能理解成不同的 host地址,此情况出现条件较为复杂。

2、Host头增加前后空格
downstream去掉了前置空格,upstream不认识前置空格,直接使用了b.com

3、request uri是绝对路径
upstream认识scheme标识的Host
akamai未遵循


1、任意网站Squid透明缓存污染
针对 squid重灾区,通过request-uri路径标识进行欺骗,首先发送欺骗请求至 attack.comg攻击者自己搭的服务器,squid缓存判断attack.com == 1.1.1.1 记录 cache,cache host被记录为 victim.com,造成之后命中 cache都被定向到 attack 恶意攻击网站.
squid缓存污染可污染任意网站,危害很严重,在小区缓存或校园 cache都可能严重的污染定向问题。

2、Co-hosting透明缓存污染
针对 host 空格的解析出现问题

3、CDN缓存污染

4、防火墙绕过

5、WAF绕过
request URI scheme attack

出现多 host 攻击或者 cache污染之所以严重,难以处理之处也在于 Server根本无法处理,就连察觉是那一路由部分出现问题都不好定位。
- RFC 7230 [ 6 ]明确指定的要求以及多headers must be 拒绝以及给出400错误请求。对于厂商,不同的系统应该完全遵循RFC7230,消除与其他系统之间的歧义
- ISP应该及时更新透明缓存软件
- HTTPS并启用pre load HSTS
- jon postel法则的局限性: be conservative in what you do, B3 liberal you accept from others.
- 给出参考代码,描述遵循标准
- 设计上避免
- 网络框架实现跟上RFC标准
以上资料来源:
http://www.echojb.com/search-engine/2017/01/09/297308.html
https://hostoftroubles.com/index.html
https://cuiyn.github.io/2017/11/06/Multiple-Host-Ambiguities-in-HTTP-Implementations.html
布施恩德可便相知重
微信扫一扫打赏
支付宝扫一扫打赏