Web是一个协作的生态系统。 Web标准的存在,保证了网络的参与者以可预见的方式行事。如果网络参与者偏离了既定标准,就会发生意想不到的结果,本文描述的就是这样一个意想不到的结果。
最近一组研究人员发表在NDSS 2016 的一篇论文 “Forwarding Loop Attacks in the Content Delivery Networks“ (针对内容分发网络的转发环路攻击)[1]中,描述了Web服务如果以不兼容的方式进行交互时会发生什么。他们描述的攻击,恶意用户可以让多个服务提供商相互发送其请求,从而导致无休止的循环。这样的请求循环可以导致服务供应商的资源枯竭和服务拒绝。该论文还展示了,转发环路攻击对大批的CDN是可行的。
针对上述论文提到的攻击,我们已经对CloudFlare的服务做了相应的修改,使之符合于HTTP代理的相关标准。然而要彻底避免上述攻击,所有的代理服务必须都遵循相关标准。如果有一个服务供应商不遵循标准,其他所有遵循标准的服务商,仍然可以被攻击。在本文中,我们将介绍这种新型的攻击,并说明一个供应商如何从问题的一部分,变成解决方案的一部分。
反向代理
CloudFlare 是使用反向代理来工作的。当HTTP(S)请求进入CloudFlare的网络,会发生下面的两种情况之一:一是CloudFlare返回缓存的响应;二是CloudFlare向原始网站发出请求,并转发原始网站返回的相应。CloudFlare可以检查和修改通过其网络的请求,该能力使得许多强大的功能成为可能,如高速缓存、WAF(Web应用防火墙)、RocketLoader等。
另外,在一个网站的前面使用多个反向代理也并不少见。这种做法称为堆叠代理(Stacking proxies),通常被用来提供多个不同的服务特性。例如,可以使用CloudFlare进行缓存,但使用另外一个服务商的WAF。虽然我们更希望客户使用CloudFlare提供的先进的WAF,但使用其他的WAF也是合理的,并且很多客户也是这么做的。多个代理可以在原始服务器的前面被堆叠,但是,如果最后一个代理指向了第一个代理会发生什么?这将得到一个代理循环。
两个代理形成的循环很容易理解。配置第一个反向代理使用第二反向代理作为源网站,同时配置第二个反向代理使用第一个作为它的源网站,如图1所示。
从理论上说,发给该网站的任何请求最终会在两个代理之间被来回发送。每次循环都将导致一个请求被发送,并消耗资源。幸运的是,大多数反向代理都有保护,可以避免这样的简单攻击。
图1
防止简单的循环
HTTP 1.1的作者意识到请求循环的可能性,并在制定标准时,定义了相应的保护。这个环路保护是通过 “Via” 报头来实现的。下面的段落来自 RFC 7230的5.7.1部分:
“Via”头字段,表示在用户代理和服务器之间(请求方向),或者在原始服务器和客户端之间(响应方向),存在中间协议和接收者。这类似于电子邮件的“Received”头字段(RFC5322 的3.6.7)。“Via”头字段可以用来向前追踪消息,从而避免请求循环,并发现请求/响应链中发件者的协议功能。
一个“Via”头字段的多个域值可以被用来表示单个代理或网关。每一个中间人都追加自己的信息,来表述如何接收到该消息,最终结果是,所有转发代理形成了一个排序。一个代理在转发每个消息时, 必须按照以下要求,添加相应的“Via”头字段。一个HTTP到HTTP的网关必须在每个入站请求消息中添加 “Via”头字段,可以在转发的响应消息中添加“Via”头字段。
例如,一个请求消息可以从HTTP / 1.0的用户代理被发送到一个叫“fred”的内部代理,该内部代理使用HTTP / 1.1把请求转发到一个公共代理p.example.net,该公开代理则将请求转发到原始服务器www.example.com, 从而完成了该次请求。www. example.com接收到的请求将有以下的 Via头字段:
Via: 1.0 fred, 1.1 p.example.net
一个发送者,不应该合并“Via” 的多个条目,除非它们属于同一个组织,并且主机信息已经被匿名化了。如果“Via”的多个条目包含了不同的协议值,则绝对不可以被合并。
CloudFlare目前使用了这一机制,以防止请求循环。当一个请求通过CloudFlare的网络时,并且不在缓存中,CloudFlare将创建一个新的请求,发给原始网站。CloudFlare发出请求的“Via” 头字段中, 包含从上一个节点收到请求的HTTP 协议版本,和一个CloudFlare专用值:
Via:1.1 CloudFlare
如果一个请求进入“CloudFlare”网络时,其Via头字段里包含了“cloudflare”这个值,则会返回错误。这可以避免在CloudFlare网络中形成请求循环,如图2所示。
然而,实施这种保护手段,就可以保证CloudFlare不会受到HTTP请求循环的攻击吗?对此不要过快下结论。图2
图3坏消息
并不是所有的反向代理服务都遵循RFC 7230标准。一些代理服务给客户提供过滤或修改HTTP头的能力,包括“Via”头。这其实是RFC不允许的:代理有义务保留其他代理添加的“Via”头字段里的标签。代理只允许修改其自身组织添加的头部分。允许代理修改其他代理添加的“Via”头字段,会导致坏事的发生。
我们用上面的两个代理回路的例子来解释。假设两个代理服务器在发送请求时,都会添加自己的的Via头,并在收到带有自己“Via”头的请求时,返回错误。假设第二个代理会把接收到的请求里的“Via”头过滤掉。当请求从第二代理返回时,第一个代理已经无法确认它已经转发过该请求。然后,该请求会被当正常请求一样处理,被发送给第二个代理。第二个代理如果不做回路检查,则会继续将该请求发送回给第一个代理,如此循环往复,如图3所示。
这种攻击可以造成很大的伤害,耗尽两个服务提供商的资源。它还可能导致自动攻击防御系统的意外行为,从而进一步导致一个服务提供商被另外一个封锁。
对于CloudFlare的客户
有一些Web服务器,如果收到的请求包含“Via”头字段,在缺省情况下,不会压缩返回的响应。这可以导致你的服务器在给CloudFlare发送数据时,浪费不必要的带宽。这时可以咨询CloudFlare的知识库,来学习如何测试所在服务器是否有此行为,以及如何将其禁用。如果不知该如何修改服务器的配置,可以联系CloudFlare的技术支持。
呼吁采取行动
上述NDSS论文的作者们在论文发布之前,联系了受影响的CDN厂家,但可能不是所有的厂家都已经修复了。如果所在组织向公众提供反向代理服务,我们建议实现以下逻辑:一是在任何情况下,都不要让客户删除或修改到达他们网站的请求里的“Via”头字段。二是进行代理时,追加符合RFC 7230标准的 “Via”头字段。三是如果一个请求包含你自己的“Via”头字段,请返回相应的错误。
一个不符合标准的反向代理服务可能会给大家导致不良后果,让我们一起努力,以避免请求循环。
(作者单位:1为CloudFlare;2为Huawei Canada)
参考文献:
[1] Jianjun Chen, Jian Jiang, Xiaofeng Zheng, Haixin Duan, Jinjin Liang, Tao Wan, Kang Li, Vern Paxson, Forwarding-Loop Attacks in Content Delivery Networks, accepted by NDSS 2016 。NDSS是国际网络安全四大会议之一,本文获NDSS 2016年杰出论文(Distinguished Paper)。
[2]论文下载:http://netsec.ccert.edu.cn/duanhx/files/2010/12/cdn_loop-final-cameraready.pdf
[3]原文地址: https://blog.cloudflare.com/preventing-malicious-request-loops/