Websocket为网络安全带来哪些挑战?

通过阅读本文可以了解: 

        1.Origin、Host、Upgrade、Connect字段的使用场景

        2.Websocket数据帧进行掩码的目的

        3.Http2 在发送数据前为什么会先发送一段字符

        4.什么是透明代理投毒、怎么发起IP劫持攻击

摘要——浏览器在网络应用(web application)访问网络时会进行一些限制。通常,网络应用只能使用HTTP进行网络访问,但是HTTP并不能满足一些网络应用的需求,比如即时聊天和在线游戏(这些应用通过socket进行网络访问更合适)。处于对这些功能的期望,Java、Flash Player、HTML5为网络应用提供了Socket APIs,但是我们通过实验证明,应用使用这些APIs与服务器进行通讯时可以对链路中的透明代理(transparent proxies)发起某些网络攻击,每次攻击花费不到1美元(1美元主要是指做广告,做广告为了让用户去点击带有他们实验室脚本的页面,从而检测是否可以成功发起缓存投毒攻击,后面有介绍具体步骤),就可以在某个透明代理中投毒,被代理的浏览器有可能会使用被恶意串改的脚本程序。所以我们向HTML5 WebSocket工作组提出了一些建议,最终他们采用了我们的部分建议,并做了修改。

 


介绍

 Web应用在使用连接(network connection)进行网络通讯时,浏览器会做一些限制。这些限制组成了web安全模型的核心——用户可以访问任意网站,并且在浏览器里执行这些网站的脚本。更通俗的讲,浏览器允许Web应用向任意地址的服务器发送符合规则的HTTP请求,但是会阻止应用读取响应数据(考虑没有ajax接口的情况),除非服务器使用某些机制可以让应用读取响应数据。

 某些插件可以越过这些限制。比如:Java(Applet,如果没有特殊说明之后的Java就是指Java Applet)和Flash Player可以让Web应用打开socket连接。当然,socket连接不受浏览器的限制,这样使得web应用的网络访问变得非常不安全。对于那些依赖IP源地址和通过某些规则控制网络连通性来保证网络安全(防火墙)的某些服务来说,黑客可以通过原始Socket连接来使得某些服务变得非常不可靠。在使用Java和Flash Player的技术中,只有服务器允许的Web应用才能与其建立socket连接,而不是任意的Web应用都可以建立连接。

 Java和Flash Player使用不同的许可协议(consent protocol)。Java使用比较简单的许可规则,字节码从哪个服务器下载的,它就可以与哪个服务器建立socket连接。相比之下Flash需要服务器在某个端口(默认843)提供一个访问策略文件,只有符合策略,才会允许Flash客户端与服务器建立socket连接。尽管这些协议(Java Flash Player)广泛地部署在浏览器中,但这些协议只是经过了少量的安全性的分析。最近,有研究发现,这两种协议比较容易受到DNS重定向[1]的攻击,当策略文件指定的主机为域名而不是IP地址时,攻击者可以使得客户端连接到其他服务器。

 在我们的研究中,现在广泛使用的许可协议(consent protocol)会使得某些网络节点比较容易受到攻击,特别是透明代理(transparent proxies,这个是整个文章的主角,这个并不单指Nginx代理)。不像传统的HTTP代理(客户端都明确知道HTTP代理的存在),透明代理(在默认网关或者网桥中集成转发、缓存功能)会在传输路径中隐式地配置,并且客户端是不知道这个代理的存在。这些代理在流量过滤应用中常见,同样也可以提供流量加速、缓存等功能。虽然叫透明代理,但是他们并不像他们的部署方期待地那样透明地工作,反而叫拦截代理更好。

 这些透明代理经常在不理解服务器许可的具体含义的情况下去进行转发。当服务器提供了允许SWF应用可以连接某个IP的某个端口的Flash策略文件时,Flash Player可以让SWF与目标服务器建立一个socket连接,但是它并不知道其实SWF是与透明代理进行了连接而不是目标服务器。一旦攻击者与透明代理服务器建立了连接,攻击者可以采取的攻击形式由透明代理的表现方式而决定。

Auger [2]描述了攻击者如何利用透明代理连接到其他服务器来发起某些攻击。我们介绍了一种新的攻击形式,这种攻击可以在透明代理中对任何URL的缓存进行投毒,导致代理后面的用户会访问到被篡改的缓存内容,而不是实际内容。实现这种攻击需要的条件相对比较明确。为了检测这种特定的条件是否在现实中成立,我们在互联网上进行了一场实验来检测哪一部分用户比较容易受到这类攻击。我们通过实验发现,51273个页面访问中的3152(6.1%)个用户容易受到基于Java的IP劫持攻击,30045个页面访问中的2109(7%)个用户容易受到基于Flash Player的IP劫持攻击。此外,30045中的53(0.18%)个用户容易受到基于Java的缓存投毒攻击,51273中的108(0.21%)个用户容易受到基于Flash Player的缓存投毒攻击。这种统计方式是比较保守的,因为每次代理缓存投毒攻击之后,被代理的用户(有可能是整个企业)都会受到影响,所以具体的影响范围可能超过我们的最初统计数值。我们的实验证明,每花费0.93美元做广告,就可以成功发起一次透明代理缓存投毒攻击。

 Socket APIs可以让Web应用提供一些使用HTTP APIs很难实现的功能。我们通过调研来探究,是否可以通过设计一个可靠的许可协议(consent protocol)来避免一些透明代理做出一些超出预期的行为,而不是简单地建议把Socket APIs从Web应用中删除。我们决定把HTML5的Socket APIs,也就是WebSockets[3], [4],作为调研的切入点。WebSockets使用带内(in-band,作为对比ftp是out-of-band,简单理解就是管理信息通过另外一个连接传输。)的许可协议(consent protocol)。浏览器在socket中与服务器进行必要的握手之后,会把socket相关的接口暴露给Web应用去使用。我们根据以往经验判断,现在的Websocket版本使用的许可机制很容易使透明代理被投毒。尽管WebSocket握手是基于HTTP(很多网络基础设施都可以处理HTTP协议),但是握手过程中会使用有些网络设施不理解的"Upgrade"[5]请求头。在我们的实验中,有些网络设施并没有很好地实现"Upgrade"机制,这样就会导致在握手成功之后,一些网络设施会错误地处理Socket中传输的数据。

 根据我们的实验分析以及以往经验,我们建议WebSocket协议可以通过在socket中发送的字节中增加一些随机因子来防止攻击者可以控制在socket中发送的字节。使用流密码(stream cipher)和随机数对通过的每一个数据帧都进行加密,这样攻击者就不能利用传输中的某些字节来迷惑传输路径中的某些网络设施(比如,透明代理)。最后,我们建议,中间网络设备在不理解网络协议的情况下还在为后面服务器进行代理转发的情况下,协议设计者应该更多得考虑如何防止攻击者利用代理不理解的网络协议来操纵这些中间网络设备,从而发起某些网络攻击。

贡献(Contributions) 本文的主要贡献大致分为如下俩种:

  • 我们介绍了一种新的攻击方式,攻击者使用Flash player和Java提供的Socket APIs向透明代理中的HTTP缓存投毒,被透明代理所代理的用户都会访问到恶意篡改的脚本程序。我们的实验证明大约7%的互联网用户很容易遭受Auger描述的IP劫持攻击,大约0.2%的互联网用户容易遭受缓存投毒攻击。
  • 我们通过HTML5 WebSocket的APIs证明了缓存投毒攻击。使用流密码(stream cipher)对传输的字节进行加密之后,这些字节对于一些透明的网络设备来讲就比较随机,从而提高WebSocket协议的安全性。最终,WebSocket协议工作组(WebSocket protocol working group)采纳了我们的建议,但是他们没有使用流密码,而是使用了XOR字节掩码的方式对传输字节进行加密。

大纲(Organization) :剩余部分大致分为如下结构。第二部分(Section II)描述了现在浏览器普遍使用的网络访问机制。第三部分(Section III)详细描述了我们使用Flash Player和Java进行攻击的过程。第四部分(Section IV)描述了使用HTML5 WebSocket进行攻击的过程,并提出了我们的一些建议。第五部分(Section V)描述了我们的相关工作。第六部分(Section VI)做出一些总结。

背景:浏览器中的网络访问方式

 在这一章节,我们回顾一下在饱受威胁的网络环境中,现代浏览器为Web应用提供的网络访问机制。考虑现在企业网络普遍使用的网络拓扑结构,企业员工在连接互联网时都会通过某个透明代理(transparent proxy),透明代理会拦截所有的HTTP请求,可能监视员工的网络访问情况,也可能是进行网络加速。

 当用户访问恶意网站的时候,我们希望浏览器可以阻止网站中的脚本能从用户浏览器中与任意的外部服务器进行通讯。我们假设用户访问了恶意网站,浏览器也进行了一些必要的访问限制,并且攻击者也没有直接控制中间的网络设备。那么还是之前的问题,浏览器如何对恶意网站的网络访问进行限制呢?

  1. 同源策略(Same-Origin Policy)

     应对Web攻击的最常见的做法就是浏览器只允许Web应用与它所属的同一个域名的服务器(从哪个服务器加载的或者同属一个域名)进行通讯。这个模型就叫同源策略,被Java Java applets首次引进。Java的设计目标就是一个通用的编程语言,毫无疑问,也提供了比较通用的网络编程API,这些API允许虚拟机可以与任何主机端口建立网络连接。如果虚拟机毫无条件的去完成API所要求的功能,那么这些API将变得非常危险。基于这个原因,Java只允许字节码与它所属的服务器(从哪个服务器下载下来)建立网络连接(如果用户对字节码进行了验签,那么这个字节码程序不受同源策略的规则限制)。这个策略具有先天的安全性,你和自己聊天能有什么危险可言?(这也许就是论文名称的来源)。

     但是,如何确定是否“同源”非常具有挑战性。一个最基本的判断方法就是比较主机名字(host name)是否相等,但是我们无法保证同一个域名下绑定的服务器就一直是我们所认为的那个服务器。如果Java虚拟机自己完成域名解析服务,那么整个系统有可能会遭受DNS重绑定攻击(DNS rebinding attacks)[1], [6]。在这些攻击中,受害者访问攻击者的网站(比如attacker.com),攻击者的域名服务器向受害者返回一个指向攻击者服务器的A记录,这个记录的有效时间很短。用户浏览器下载Java applet,然后与attacker.com所指的服务器建立一个socket连接。因为DNS返回的A记录已经失效,所以Java虚拟机再次对attacker.com进行解析,但是这次攻击者的域名服务器返回一个指向了另一个目标服务器的A记录,这次客户端与目标服务器建立一个socket连接。DNS重定向攻击已经存在很长时间,现在普遍的解决办法就是通过IP做比对而不是域名,或者忽略域名服务器返回的超时时间。

  2. 验证策略(Verified-Origin Policy)

     同源策略太具有局限性,许多Web应用开发者希望与其他网站进行互通以增加额外的功能和内容(包括广告)。允许跨域名通讯通常情况下是不安全的,但是如果浏览器验证目标网站符合通讯规则的话,跨域名访问也是可以进行的。现在有一些实现了验证策略的技术手段[7]:

    • Flash跨主机策略(Flash Cross-Domain Policies):SWF在与目标网站(服务器)建立socket连接之前,Flash Player首先从目标网站获取一份跨主机的策略(cross-domain policy)文件:一个XML文件,描述了谁可以与目标网站建立socket连接[9]。策略文件所在的位置本身就会给它带来很多限制,这样就会给攻击者仿造一个合法的策略文件带来很多困难。比如策略文件如果是从大于1024的端口中下载的,那么它不能授权Web应用去连接小于1024的端口。

       Flash player对于socket与跨域名的HTTP请求都使用相同的策略(验证策略)。与Java一样,Flash Player的许可机制在过去也同样易受DNS重绑定攻击(Flash Player的DNS重绑定攻击在9.0.115.0版本中得到修复)。事实上,一直检测跨域名访问的策略文件是为了防止某些DNS重定向攻击(比如利用time-of-check-time-of-use在解析域名与根据解析结果进行相应操作产生的的竞态条件发起的某类攻击。)。

    • JavaScript跨源通讯(JavaScript Cross-Origin Communication):直到最近,JavaScript应用程序一直只能使用XMLHttpRequest发起HTTP请求,并且浏览器禁止跨源请求[10]。最近,浏览器提供商新增了两个机制可以让Web应用绕过这个限制。

      • CORSCross-Origin Resource Sharing[11]允许Web应用可以向其他源发起HTTP请求。当一个Web应用发起XMLHttpRequest请求时,浏览器会在请求里添加Origin请求头,并且把Web应用所属的源(origin)作为该请求头的值。服务器会在Access-Control-Allow-Origin响应头中添加请求头里Origin的值以允许Web应用读取服务器的响应数据。这种机制弱化了同源策略,以便浏览器中不同的Web应用可以互相通讯。
      • WebSockets:CORS只作用于HTTP请求,WebSocket[4]允许Web应用可以与任何服务器(与Web应用所在服务器不在同一个域内)建立socket连接,并且发送任何数据。这个特性非常有用,特别是在服务器需要向客户端异步发送数据的时候。目前,Web应用都是用一种比较难用的机制来实现异步发送消息,这种机制叫做Comet[12]。和Flash Player、CORS一样,WebSocket使用验证策略(verified-origin)来让目标服务器准许客户端与其建立连接。但是与Flash Player、CORS不同的是,WebSocket的验证是在同一个连接内进行的,这个连接之后也会用来发送数据。浏览器发起握手请求,并且当握手过程完成后,Web应用才能在这个socket连接上发送数据,具体过程在第四部分有描述。

基于Java和Flash socket的攻击

 由来已久的的DNS重新绑定攻击表明,设计一个安全可靠的同源策略或者验证策略非常具有挑战性。之前的协议设计一直具有TOCTOU相关问题(事务相关的,涉及到网络的,基本上都是很难解决的问题)。在这个章节,我们描述了同源策略、验证策略(除了CROS)的另外一类易受攻击的点。通过socket api我们通过HTTP Host字段和目标IP来迷惑中间代理。

watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAVGlnZXLnmoTlrabkuaDov4fnqIs=,size_20,color_FFFFFF,t_70,g_se,x_16图1 

 

  1. 脆弱点(Vulnerabilities)

     假设被透明代理(transparent proxy)代理的用户访问了attacker.com网站,并且“attacker.com”网站中内嵌了被恶意修改的SWF(Flash Player可以执行的程序文件,类似js),之后,攻击者就可以根据透明代理的表现形式发起不同类型的攻击。

    • 根据Host字段路由(Route by Host Header):当使用传统的HTTP代理(Nginx代理)的时候,浏览器一般直接会与代理建立连接,然后向代理发送HTTP请求来告知自己需要的资源。然而,对于透明代理(transparent proxy),当它接收到一个HTTP请求的时候,如何对请求进行路由,它大致有两种选择:
      • 根据HTTP的host字段
      • 目标服务器的IP地址(透明代理可以根据IP路由,但是一般的Nginx代理无法做到根据IP来路由)。

     但是,正如Auger描述的那样,如果基于头部Host字段进行路由的话,攻击者可以欺骗代理,让它把请求转发到任何可以连接到的服务器那里,如图1所示:

    1. 攻击者在"attacker.com"主机的843端口上放置了一个允许任何主机从任何端口,与当前主机(attacker.com指向的主机)建立socket连接的许可文件。

    2. 攻击者的SWF程序请求与attacker.com:80(IP为2.2.2.2)建立socket连接。

    3. Flash Player连接到attacker.com:843,然后下载许可文件。

    4. Flash Player允许SWF与attacker.com:80建立socket连接。

    5. 攻击者的SWF在socket连接上发送伪造的Host请求头:

      GET / HTTP/1.1

      Host: target.com

    6. 透明代理认为这是一个HTTP请求,并且根据Host(不是根据目的IP进行路由)里指定的值进行路由转发。如图描述,透明代理把请求转发到target.com:80(IP地址为1.1.1.1)。

    7. 目标服务器把 Target : Expect More. Pay Less. 指向的文档作为响应数据返回给透明代理,透明代理再把响应转发到发起请求的客户端。

     Flash Player准许攻击者的SWF程序与攻击者的服务器建立socket连接(基于攻击者自己提供的许可文件)。攻击者使用socket API可以让透明代理根据Host字段把请求转发到与实际IP地址不符的其他服务器上,这样就打破了浏览器的安全模型,并且使整个系统变得非常脆弱。或者,攻击者可以使用HTTP的connect方法[13](第五步骤)使透明代理与目标主机建立原始的socket连接。

    CONNECT target.com:80 HTTP/1.1

    Host: target.com:80

     使用透明代理作为跳板,攻击者可以利用用户的IP进行一些非法行为,并且把罪行诬陷给用户。比如,攻击者可以利用用户的IP去点击一些pay-per-click广告来增加自己的广告收益[[14]]。IP劫持攻击同样可以访问某些受保护的网站(这些网站只允许某些IP访问),或者利用用户的IP发送一些垃圾邮件。

     攻击者利用Java socket也同样可以达到以上效果。攻击步骤也是一样,但是Java不需要下载许可文件,因为Java本身允许applet与自己的源服务器(从哪个网站下载的应用,就可以与哪个网站建立连接)建立socket连接。

    • 根据Host字缓存(Cache by Host Header):在之前几个章节介绍了透明代理根据Host字段进行路由而导致的几种攻击。但是并不是所有的透明代理都根据Host字段进行路由,有的透明代理会根据目的IP进行路由,尽管这些透明代理不受IP劫持的攻击,但是我们发现攻击者同样可以利用这些透明代理发起其他的网络攻击。

     有些根据目的IP进行路由的透明代理有可能会根据Host字段进行缓存。和路由差不多,有的透明代理既可能根据目的IP进行缓存,也有可能根据Host字段进行缓存。如果一个透明代理根据目的IP进行路由,但是根据Host字段进行缓存的话,攻击者可以让透明代理对任何URL(攻击者指定)的请求返回恶意修改的内容,如图2所示。watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAVGlnZXLnmoTlrabkuaDov4fnqIs=,size_20,color_FFFFFF,t_70,g_se,x_16

                                                            图2 

    1. 攻击者使用Java与attacker.com主机的80端口建立socket连接。

    2. 攻击者在socket连接上发送一段伪造的HTTP请求头,如下:  

      GET /script.js HTTP/1.1

      Host: target.com

    3. 透明代理把这段字节序列解释为HTTP请求并且根据目的IP进行路由,把消息转发到了attacker.com主机上。

    4. 攻击者的服务器(attacker.com)作为响应,返回了一个恶意脚本(同时增加了Expires字段,并且失效时间无限的延长)。

    5. 因为根据Host字段进行缓存,所以透明代理的缓存内容是,http://target.com/script.js,而不是http://attacker.com/script.js。

    6. 之后只要有客户端通过透明代理请求http://target.com/script.js文件的时候,透明代理都会把恶意脚本返回给客户端。

             另一个比较广泛的缓存投毒攻击,就是利用了透明代理会缓存谷歌的分析脚本( http://www.google-analytics.com/ga.js )导致的。 前10,000名的网站中有57%的网站都会加载谷歌的这个脚本。每一个使用这个透明代理的用户(有可能是整个企业的员工)在访问引用了谷歌这个脚本的网页的时候,会把恶意脚本加载到本地。随着更多的代理用户访问谷歌的这个脚本,攻击者的恶意脚本(因为伪装的是谷歌的脚本,所以有更高的权限)可以发起持久的跨站脚本攻击(XSS)。

  2. 实验(Experiment)

     以上描述的攻击在特定的网络配置下才能发生。为了验证这些网络配置在因特网环境中是否普遍存在,我们进行了一个实验(proof-of-concept),利用Flash Player与Java发起IP劫持和缓存投毒攻击。通过发广告的形式在页面内嵌入我们的脚本,然后通过脚本来攻击位于我们实验室的服务器。

    1. 方法论(Methodology):我们的实验使用了两台位于实验室的主机,这两个主机有不同的主机名字(Host names)和IP地址。一个主机扮演目标(target)服务器,一个主机扮演攻击(attacking)服务器。目标服务器是一个标准的阿帕奇Web服务器。攻击服务器运行着一个标准阿帕奇Web服务器和一个监听843端口的Flash socket policy服务。我们在广告平台(advertising network)上做了一个富媒体形式的广告,这个广告网页中载有我们的测试代码。我们的广告没有交互过程,并且广告中的脚本会在用户浏览器里执行如下任务:

      • IP劫持:我们的脚本通过Flash Player和Java与攻击服务器建立socket连接。攻击服务器在843端口放着允许任何主机能连到本机的许可文件。一旦成功建立连接,脚本就会伪造一个HTTP请求,如下 

        GET /script.php/<random> HTTP/1.1

        Host: target.com

      攻击服务器和目标服务器在/script.php位置上放置了一个PHP文件,但是文件内容不一样,这样我们就可以判断请求是发送到了哪个服务器上。连接后面的用来防止使用中间代理、某些插件以及浏览器的缓存数据。我们也可以在查询字符串中添加随机数(在?后),但是缓存代理对URL中的查询字符串处理逻辑很多不一样。如果HTTP响应来自目标服务器,而不是攻击服务器的话,那么就能证明这个请求是根据Host头部字段来路由的,这样就很容易遭受IP劫持。

      • 缓存投毒:在上面的测试中,脚本的响应头部使用Cache-Control: public,Last-Modified,Expires几个字段用来保证脚本可以被缓存一年。为了检查Socket连接是否在代理缓存中投毒,我们在广告里使用了tag来加载部署在目标服务器中的脚本,使用了带有同样随机值的URL地址(http://target.com/script.php/,random和之前websocket连接里使用的一样)。

      因为之前的链接只有在socket中使用过,所以这个链接不会被浏览器缓存。通过检查响应内容(JavaScript变量)来判断这个脚本是从攻击者服务器加载的还是从目标服务器加载的。如果我们收到的响应文件是来自攻击服务器的,那么我们就可以推测缓存投毒成功。

      译者注:大致流程就是socket连接的目标IP是攻击服务器,透明代理会根据目标IP进行路由,之后在socket里发送了Host为目标服务器主机的HTTP请求,所以透明代理会把攻击服务器返回的脚本当作目标服务器的地址来缓存。这样以后所有访问目标服务器脚本的请求实际都是加载了攻击服务器的脚本。watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAVGlnZXLnmoTlrabkuaDov4fnqIs=,size_20,color_FFFFFF,t_70,g_se,x_16

       

    2. 结果(Results):我们在2011年3月连续5天投放广告,总共花费了100美元,大概获得了174,250的独立点击。通过在用户浏览器的cookies里放置用户标识,我们过滤了一部分重复的用户点击。广告中运行着我们的JavaScript、SWF、Java字节码程序,这些程序不需要用户交互,在用户点击完之后,这些脚本程序就会按照如上描述的流程进行消息通讯,等这些流程都走完之后,程序会把相关结果发送到我们位于实验室的服务中。当脚本在执行过程中,用户关闭了当前窗口,或者跳转到了其他页面,那么这个实验结果是不会发送到我们服务器上的。我们收到了来自SWF的51,273个结果、Java的30,045个结果((19,117个用户同时完成了这两个测试)。这么少的结果主要是因为SWF和Java脚本加载地比较慢,用户没有等实验做完,就关掉了页面或者跳转到其他页面。我们的实验证明,IP劫持、缓存投毒在现实世界中是可以实现的。具体可以见表1。

    • IP劫持:在使用Flash进行IP劫持测试中,我们观察到,51,273个点击中有47,839(93.3%)个请求发送到了攻击服务器,这说明透明代理根据目标IP进行转发而不是根据Host字段进行转发,同时也有233个错误信息是因为Flash socket连接建立失败导致的,这有可能是中间有防火墙阻止了客户端从843端口下载许可文件导致的。有49个请求收到了HTML错误信息,这有可能是透明代理拒绝了这次的模拟请求。最后,大约有3,152个请求是根据Host字段路由到了目标服务器,说明这些用户很容易受到IP劫持攻击。

       当使用Java socket测试时,我们观察到,30,045个点击中有26,759(89.1%)个请求发送到了攻击服务器,这说明透明代理是根据目标IP进行转发。大约有1,134 (3.8%)个连接错误,43个请求收到HTML错误信息。2,109(7%)个请求是根据Host字段进行了路由,表明这些用户很容易受到IP劫持攻击。

    • 缓存投毒:在使用Flash socket进行缓存投毒的实验中,我们发现51,273个请求中有51,163(99.8%)个请求加载了来自目标服务器的脚本。有两个客户端报错。但是我们发现有108(0.21%)个请求是加载了攻击脚本。所以这样可以证明,有些透明代理是根据IP进行路由,但是会根据Host字段进行缓存。

       在使用Java socket进行缓存投毒实验中,我们发现30,045个请求中有26,612(88.6%)个请求加载了来自目标服务器的脚本。大约有3,680个请求查询失败,我们无法确定这些请求的缓存投毒攻击是否成功。与Flash socket差不多,Java socket大概有53(0.18%) 个请求加载了攻击脚本。

       我们的实验证明,攻击者使用Flash socket平均花费1.08美元就可以发起一次成功的缓存投毒攻击。但是,一次成功的缓存投毒攻击,可能会影响被透明代理拦截的所有用户,所以总的影响人数可能超出我们的初步计算的人数。

基于Websocket协议的攻击

 使用Java和Flash socket容易遭受攻击的一个主要原因是因为他们是基于带外的(out-of-band,先去获取许可文件,然后再根据许可文件来确定能不能和服务器建立socket连接)连接验证机制。 因为透明代理没有感知到带外信息,所以它们会误解攻击者在socket上发送的信息。在这一章节,我们考虑三种带内(in-band)验证的方法,这三种方法都是基于HTTP。第一个基于POST的握手,这个是我们独创的,用来阐述设计意图的。第二个基于Upgrade请求头,目前被HTML5广泛使用,已经达到最好水准。第三个基于CONNECT字段,目前处于试验阶段,我们设计用来防御攻击的。

  • 基于POST的握手(POST-based Handshake)

    1. 设计: 设计带内验证机制,最自然的方法是使用HTTP协议进行一次握手过程。在服务器没有同意接受Websocket数据之前,客户端不能发送websocket数据,在握手阶段,客户端和服务器只能发送固定的几个字段,而且在建立websocket连接之后,攻击者在websocket上发送他们之前已经设计好的数据也不会达到攻击中间代理的效果,在websocekt发送的数据被当做Form表单里的数据,这样能产生什么样的影响呢?这样还能规避那些不支持Websocekt的服务器。接下来看下基于HTTP Post请求的握手过程:

      Client -> Server:

      POST /path/of/attackers/choice HTTP/1.1

      Host: host-of-attackers-choice.com

      Sec-WebSocket-Key: < connection-key >

      Server -> Client:

      HTTP/1.1 200 OK

      Sec-WebSocket-Accept: < connection-key >

      服务器返回connection-key表示可以与客户端建立Websocket连接。如果Websocket发送的内容不会比Form表单中的元素更多的话,我们认为这种带内许可是安全的。

    2. 脆弱点(Vulnerabilities): 但是,Websocket能产生比Form元素更多的元素类型。比如,Websocket应用产生一些数据来迷惑中间透明代理,使它认为后面的数据是另一个HTTP连接,而不是之前传输Form数据的连接。尽管我们在Websocket握手成功之前不发送非HTTP请求,但是我们仍然可以迷惑中间代理。

      考虑一个会检查传输与浏览器和攻击者服务器之间数据包的中间代理。客户端发起Websocket请求然后服务器同意这个请求。之后客户端可以在连接上发送任何数据。可是,中间代理并不了解Websocket协议,所以,开始的握手协议对它来说只是一对请求响应的而已。所以,之后客户端可以发送类似HTTP请求的数据,比如:

      GET /sensitive-document HTTP/1.1

      Host: target.com

      当中间代理检查这些数据的时候,它认为这是第二个请求。如果这个中间代理是透明代理,他可能会根据Host字段进行路由或者缓存。

    3. 实验: 为了评估使用Websocket握手过程后,是否还能发起IP挟持和缓存投毒攻击,我们使用Flash socket来实现了Websocket握手过程,并且使用python实现了一个Websocekt服务器。我们继续使用了之前测试Java还有Flash socekt时使用的系统,并且做了如下几个修改,我们在攻击服务器的80端口放了一个转发服务器,可以根据请求头把数据转发到标准的阿帕奇服务器或者Websocket服务器(Python实现)。我们在2010年11月进行了连续四天的广告宣传活动,在菲律宾话了20美元做广告,在全球花了80美元做广告。我们的广告包含一个SWF程序,这个程序会模拟Websocket握手,在握手成功之后,会模拟发送一个HTTP请求,只是浏览器从目标服务器加载一个脚本。我们测试中间代理如何处理Websocket的握手数据。实验结果如表2。

       大约有54,534个有效点击,其中49,218个 (90,2%)完成了POST握手,5,316 (9,4%)个失败。在49,218个点击中,我们进行了IP劫持测试,47,741 (96,9%)个请求都没有成功欺骗中间代理。我们发现大约有1,376(2,8%)成功发起了IP劫持攻击,并且这些客户端是位于基于Host路由的代理后面。有97个请求是根据IP路由的,有4个收到了HTML错误响应。进行缓存投毒实现时,有15个实验成功。这些数据表明基于POST的握手也容易遭受这两种攻击。

  • 基于Upgrade的握手(Upgrade-based Handshake)

    1. 设计: HTML5试图使用HTTP的Upgrade机制来提升握手的安全性。HTTP的Upgrade是一个比较通用的用来协商协议的机制,最初是用来协商TLS协议。Upgrade机制有两个字段,一个是Connection字段,值为Upgrade,另一个是Upgrade,值是客户端希望升级的协议。以下是HTTP5用来升级到Websocket协议的简单实例:

      Client -> Server:

      GET /path/of/attackers/choice HTTP/1.1

      Host: host-of-attackers-choice.com Connection: Upgrade

      Sec-WebSocket-Key: < connection-key >

      Upgrade: WebSocket

      Server -> Client:

      HTTP/1.1 101 Switching Protocols

      Connection: Upgrade

      Upgrade: WebSocket

      Sec-WebSocket-Accept:

      HMAC(< connection-key >, "...")

    2. 缺点: 实际上HTTP的Upgrade机制很少在实际中使用到。在使用HTTPS的时候基本上是使用443端口[16],与HTTP的80端口分开使用。所以,很多组织部署的中间代理很有可能没有正确实现Upgrade机制,并且这些中间代理还在正确运行,所以,中间代理的实现者和使用方,没有太大的兴趣去实现Upgrade机制,并且也不想去实现。对于不理解HTTP Upgrade机制的中间代理,HTML5的握手机制就类似于我们的POST握手机制。

      中间代理处理Upgrade的方式和处理POST的方式很有可能是一样的。所以,POST容易遭受的攻击,Upgrade方式的握手也容易遭受同样的攻击。

    3. 实验: 在我们的实验中,我们测试中间代理如何处理基于Upgrade的握手。54,534个独立访问中,47,338 (86,8%)成功地完成了握手,7,196 (13,2%)握手失败。失败率比POST高,有可能是因为不支持Upgrade机制。在47,338个成功完成握手的访问中,我们进行了IP劫持实验,大约47,162 (99,6%) 个模拟HTTP请求都没有响应。我们注意到有一个独立访问成功地进行了IP劫持攻击,这个独立访问的代理是基于Host字段进行地路由。47,338个独立访问中,有174个请求是基于IP进行路由的。有一个收到了HTML错误信息。

       我们也在47,338个独立访问中进行了缓存投毒实验,发现有8个可以成功地进行投毒,而且这八个在使用POST握手测试时,也遭受了缓存投毒攻击。

  • 基于CONNECT的握手(CONNECT-based Handshake)

    1. 设计: 我们使用CONNECT机制来通知中间代理后续的socket数据不是HTTP,而不是使用HTTP Upgrade机制。因为CONNECT经常用来建立隐藏通道传输TLS数据,所以透明代理会把这个请求当作HTTPS请求,而且之后的数据也不会试图去解析,所以透明代理会根据IP来路由消息。所以,我们基于CONNECT设计了一个握手机制。

      Client -> Server:

      CONNECT websocket.invalid:443 HTTP/1.1

      Host: websocket.invalid:443

      Sec-WebSocket-Key: < connection-key >

      Sec-WebSocket-Metadata: < metadata >

      Server -> Client:

      HTTP/1.1 200 OK

      Sec-WebSocket-Accept: < hmac >

    < connection-key >是一个128的随机数经过base64编码之后的字符串,< metadata >用来传递连线相关信息(比如客户端希望建立Websocket连接的服务器URL),在服务器的响应里< hmac >的值就是通过HMAC算法把全球唯一值258EAFA5-E914-47DA-95CA-C5AB0DC85B11(这个值有可能不是客户端传过来的,应该是写在服务器代码里,因为这个值只有在Websocket里才会有)与< connection-key >计算出来的值。通过回复< hmac >,服务器表明它可以与客户端建立Websocket连接,因为这个唯一值只有在Websocket里才会出现。

    我们没有使用目的服务器的主机名字,而是使用了一个非法的主机名字。任何不理解Websocket协议但是理解HTTP协议的透明代理可能会根据Host字段把请求转发到不存在的主机那里。

    1. 实验: 我们继续验证通过CONNECT握手之后,透明代理是否还会遭受这些攻击。54,534个点击中,47,206(86,6%)个请求成功地完成了握手,有7,328 (13,4%)个请求失败。47,206个请求中,我们用来模拟IP劫持攻击,只有3个模拟HTTP请求收到了响应,其中一个响应是HTML错误信息,另外两个是根据IP地址路由到了攻击服务器,没有日志表明透明代理根据Host字段进行路由。透明代理貌似只是简单透传了CONNECT请求到我们的服务器,对于后面的请求只是根据IP进行转发。后续的缓存投毒实验,没有发现成功的攻击。
  • 我们的建议(Our Proposal)

  1. 设计:在我们的实验中,我们发现基于POST和Upgrade的握手都能成功地发起攻击。对于基于CONNECT的握手,我们发现两个不理解CONNECT的代理,他们只是根据IP进行了转发。尽管这种代理不进行缓存,但是这种代理还是有可能会缓存数据(我们的数据表示这种可能性比较小)。所以有的时候还是可以成功发起缓存投毒攻击。

     可以通过对Websocket上发送的数据进行流密码掩码来规避这两种网络攻击。流密码不能防窃听,但是可以使得在连接上发送的字节流都变得非常随机,这样攻击者就很难在构造虚拟请求来混淆中间代理。

     我们建议对握手数据以及后面发送的数据帧都使用流密码(比如AES-128-CTR)进行加密(对比特位流进行加密,类似流处理)。C1BA787A-0556-49F3-B6AE-32E5376F992B与< connection-key >经过HMAC之后产生加密秘钥,但是,只使用这一个秘钥进行加密是不够的,因为攻击者在握手阶段获取这个秘钥之后,同样可以根据他们的意向来伪造数据。所以,我们对每个数据段都使用不同的秘钥,我们使用一个随机值当作CTR计数块的上半部分,CTR的下半部分预留给块计数。对于攻击者来说,连接上发送的数据都是随机的,即使他们握手阶段截获了秘钥。浏览器在收到应用的整个数据块之后,再使用一个新的随机值对应用数据进行加密。否则的话,攻击者会猜测到这个随机值,然后再使用随机值对后续的内容进行伪造。这种方案可能会有一些性能损耗,也会使发送的数据包变大,但是,引用的随机值越大,攻击者猜到随机值的可能性就会很小。

     使用AES-128-CTR算法对数据流进行加密会有一些性能损耗,为了降低这种损耗,Stachowiak[19]建议采用XOR加密套件,这种加密更简单,性能损耗更低。客户端针对每个数据帧都生成一个新的随机值,然后用这个随机值与数据帧进行XOR加密运算。因为攻击者在接收到数据之前是不知道这个随机值的,所以攻击者很难控制数据流。

     Websocket工作组也讨论了其他更简单的转换方式,比如翻转数据流的第一个比特位,把握手请求中的字符和回车转义。但是这种方式不能保护那些会忽略非ASCII编码的中间代理。使用字节掩码也可以保护那些不使用HTTP协议的服务器。我们相信使用字节掩码可以经受住更多的安全考验。watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAVGlnZXLnmoTlrabkuaDov4fnqIs=,size_20,color_FFFFFF,t_70,g_se,x_16

     

  2. 实验:我们使用了一个Java版本[20]的Websocket实现来测试未经过掩码、XOR掩码(32位随机数)、和AES-128-CTR加密后(使用32, 64 and 128位随机数)的网络性能。在slicehost.com网站上,我们申请了一个1024M内存的服务器(进站带宽几乎无限制)和8台256兆内存的客户端,每个客户端的出站带宽是10M。每个客户端向服务器发送10M的应用数据,这些数据会被分成不同大小的数据帧,我们计算每个客户端发送完这些数据的时间。数据帧被分成1000Byte、100Byte、10Byte的大小,他们的具体测量结果在图 3(a)、3(b)、3(c)中分别展示出来。我们发现,当数据帧大于1000Byte的时候,使用AES-128-CTR的性能损耗比较小。但是当数据帧比较小的时候,相比较于不使用掩码,AES-128-CTR的性能损耗还是比较大的,XOR掩码的性能基本可以接受。

  3. 采纳(Adoption):在2010年11月,我们向Websocket工作组说明了相关的脆弱点。考虑到这些攻击的可能性,Firefox [21] 和 Opera [22]暂时关闭了Websocket功能。最后工作组采用了基于XOR掩码的方案。Internet Explorer使用了他们自己的Silverlight插件来对数据帧进行掩码。我们希望Java和Flash Player在未来也会解决相关问题。

  4. 讨论(Discussion):在我们的调研过程中,我们发现了许多实现不是很合理的中间代理。但是我们又不能确定这些中间代理到底是哪种实现,因为他们确实很透明。比如,透明代理不会在HTTP头部表明自己的存在(如HTTP规范要求得那样)。再或者,脆弱点可能是一连串的透明底代理造成的,而不是其中一台机器。

 解决这种问题的唯一手段就是等待这些实现错误的透明代理被升级或者替换掉。但是,这个等待的时间是不确定的,我们建议浏览器提供商在HTML5 Websocket协议中解决相关问题。之后,我们会建议Flash Player和Java提供商也解决相关问题。

相关工作

  1. 跨协议攻击(Cross-Protocol Attacks)

    跨协议攻击用来迷惑服务器或者中间代理把一个请求当成其他的协议请求。我们描述了使用Websocket协议用来伪装HTTP请求的实例。Topf [24]描述了使用HTML forms向运行着基于ASCII编码(SMTP, NNTP, POP3, IMAP和IRC)的协议服务器发送命令。为了防止这种攻击,浏览器会阻止Websocket应用向比较易受攻击的应用服务器的知名端口发送请求,比如SMTP的25端口。这种措施不适用于Websocket协议,因为Websocket是基于HTTP的80端口。我们认为还会有其他类似的跨协议攻击,并且希望在未来的工作中尽量解决更多的类似问题。

  2. HTTP缓存投毒(HTTP Cache Poisoning)

    Bueno [25]描述的HTTP缓存投毒攻击基于HTTP Host字段来生成HTML link。恶意客户端会发送一个带有精心设计的Host头部信息的请求,同时攻击者的服务器收到请求后会重写这个头部连接。如果这个链路中有透明代理,那么被这个透明代理代理的客户端都有可能会收到注入了某些特定文字的页面。

    解决这种攻击的简单方法就是,不依赖Host字段去生成页面内容。作为对比,我们的缓存投毒攻击不依赖目标页面中的Host字段,并且我们的攻击允许攻击者可以在透明代理中对任何目标服务器的任何URL进行投毒。

  3. HTTP响应拆分攻击(HTTP Response Splitting)

    在HTTP响应拆分攻击[26]中,攻击者发送一个HTTP请求,用来迷惑服务器产生一个HTTP响应,这个响应会被浏览器或者中间代理认为是两个HTTP响应。恶意请求可能会携带CRLF序列,然后服务器会把这个序列写在响应数据(响应头)中,这个序列就会作为第一个响应的结尾,后续的字节序列,浏览器或者中间代理会认为是第二个响应。攻击者可以向服务器发送第二个请求来向浏览器或者中间代理发起缓存投毒攻击。禁止在响应头部中携带CRLF字符序列可以防止这种攻击。在我们的工作中,我们引入了针对透明代理的新的缓存投毒攻击,之前的两个方案都不能防止这种攻击。

  4. Pretty-Bad-Proxy

    Chen et. al. [27]介绍了恶意中间代理打破TLS协议保证的端到端的安全保证发起的一系列攻击。恶意中间代理可以利用HTTP error错误页面让浏览器加载攻击者指定的脚本,也可以利用HTTP重定向让浏览器加载恶意脚本。浏览器在TLS握手成功之前会忽略代理返回的重定向和错误信息。我们的工作没有考虑中间人攻击。我们比较关注那些善良的但是容易被迷惑的中间代理。但是,在设计协议时应该时刻考虑着恶意中间代理的可能。

总结

 尽管对于某些功能全面的浏览器应用来说,socket api非常重要,但是设计一个安全的socket api非常具有挑战性。尽管在得到目标服务器的许可后才可以发起连接,但是我们的实验证明,尽管有这种措施,如果中间有透明代理的话,依然会出现某些问题。我们的实验证明,大约有7%的浏览器用户被实现不合理的透明代理代理,导致他们容易遭受之前讨论的网络攻击。

 协议的设计者应该考虑攻击者如何通过协议来控制中间代理,这些中间代理可能并不理解这些协议。我们建议通过对每个数据帧都进行加密来提高许可协议的安全性,这样对于中间代理来说,这些字节都是随机的,很难被控制的。最后Websocket工作组采用了掩码的方式来提高Websocket的安全性。

 

本文翻译自:Talking to yourself for fun and profit

 

参考

[1] C. Jackson, A. Barth, A. Bortz, W. Shao, and D. Boneh, “Protecting browsers from dns rebinding attacks,” in Proceedings of the 14th ACM Conference on Computer and Communications Security, 2007.

[2] R. Auger, “Socket capable browser plugins result in transparent proxy abuse,” 2010, The Security Practice security practice/ TransparentProxyAbuse.pdf.

[3] I. Fette, “The WebSocket protocol,” 2011, http://tools.ietf.org/html/ draft-ietf-hybi-thewebsocketprotocol.

[4] I. Hickson, “The Web Sockets API,” 2009, All Standards and Drafts - W3C websockets/.

[5] R. Fielding, J. Gettys, J. Mogul, H. Frystyk, L. Masinter, P. Leach, and T. Berners-Lee, “Hypertext Transfer Protocol – HTTP/1.1,” RFC 2616 (Draft Standard), Internet Engineering Task Force, Jun. 1999, updated by RFCs 2817, 5785. [Online]. Available: http://www.ietf.org/rfc/rfc2616.txt

[6] D. D. Edward, E. W. Felten, and D. S. Wallach, “Java security: From hotjava to netscape and beyond,” in Proceedings of the 1996 IEEE Symposium on Security and Privacy, 1996.

[7] H. Wang, X. Fan, J. Howell, and C. Jackson, “Protection and communication abstractions for web browsers in mashupos,” in Proceedings of 21st ACM SIGOPS Symposium on Operating Systems Principles (SOSP),

[8] Adobe, “White paper: Adobe flash player 10 security,” 2008, http://www. adobe.com/devnet/flashplayer/articles/flash player10 security wp.html.

[9] Adobe, “Cross-domain policy file specification,” 2010, http://www.adobe. com/devnet/articles/crossdomain policy file spec.html.

[10] M. Zalewski, “Browser security handbook,” http://code.google.com/p/ browsersec/wiki/Main.

[11] A. van Kesteren, “Cross-Origin Resource Sharing,” 2010, http://www. w3.org/TR/cors/.

[12] A. Russell, “Comet: Low Latency Data for the Browser,” 2006, http: //infrequently.org/2006/03/comet-low-latency-data-for-the-browser/.

[13] R. Khare and S. Lawrence, “Upgrading to TLS Within HTTP/1.1,” RFC 2817 (Proposed Standard), Internet Engineering Task Force, May 2000. [Online]. Available: http://www.ietf.org/rfc/rfc2817.txt

[14] V. Anupam, A. Mayer, K. N. an Benny Pinkas, and M. K. Reiter, “On the security of pay-per-click and other web advertising schemes,” in Proceedings of the 8th International Conference on World Wide Web,

[15] BuiltWith, “Google Analytics Usage Statistics,” 2011, http://trends. builtwith.com/analytics/Google-Analytics.

[16] E. Rescorla, “HTTP Over TLS,” RFC 2818 (Informational), Internet Engineering Task Force, May 2000, updated by RFC 5785. [Online]. Available: http://www.ietf.org/rfc/rfc2818.txt

[17] D. Eastlake 3rd and A. Panitz, “Reserved Top Level DNS Names,” RFC 2606 (Best Current Practice), Internet Engineering Task Force, Jun.[Online]. Available: http://www.ietf.org/rfc/rfc2606.txt

[18] T. Dierks and E. Rescorla, “The Transport Layer Security (TLS) Protocol Version 1.2,” RFC 5246 (Proposed Standard), Internet Engineering Task Force, Aug. 2008, updated by RFCs 5746, 5878. [Online]. Available: http://www.ietf.org/rfc/rfc5246.txt

[19] M. Stachowiak, “Re: [hybi] handshake was: The websocket protocol issues.” 2010, hybi. html.

[20] J. Tamplin, “Sample code for evaluation of WebSocket draft proposals,” 2011, http://code.google.com/p/websocket-draft-eval/.

[21] C. Heilmann, “WebSocket disabled in Firefox 4,” 2010, http://hacks. mozilla.org/2010/12/websockets-disabled-in-firefox-4/.

[22] A. van Kesteren, “Disabling the WebSocket Protocol,” 2010, http:// annevankesteren.nl/2010/12/websocket-protocol-vulnerability.

[23] C. Caldato, “The Updated WebSockets Prototype,” 2011, DevBlogs - Microsoft Developer Blogs the-updated-websockets-prototype.aspx.

[24] J. Topf, “Html form protocol attack,” 2001, http://www.remote.org/jochen/ sec/hfpa/hfpa.pdf.

[25] C. Bueno, “HTTP Cache Poisoning via Host Header Injection,” 2008, 15KB Of Fame: HTTP Cache Poisoning via Host Header Injection.

[26] A. Klein, “Divide and conquer - HTTP response splitting, web cache poisoning attacks, and related topics,” 2004, http://packetstormsecurity. org/papers/general/whitepaper httpresponse.pdf.

[27] S. Chen, Z. Mao, Y.-M. Wang, and M. Zhang, “Pretty-bad-proxy: An overlooked adversary in browsers’ https deployments,” in Proceedings of the 2009 30th IEEE Symposium on Security and Privacy, 2009.

 

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值