首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

深入理解跨站点 WebSocket 劫持漏洞的原理及防范(2)

深入理解跨站点 WebSocket 劫持漏洞的原理及防范(2)

跨站点 WebSocket 劫持漏洞原理尽管 WebSocket 协议设计时充分考虑了安全保障机制,但随着 WebSocket 技术推广,安全工作者们慢慢还是发现了一些 WebSocket 相关的安全漏洞,譬如 Wireshark 的漏洞 CVE-2013-3562                                (Wireshark                                1.8.7 之前的 1.8.x 版本中的 Websocket 解析器中的 epan/dissectors/packet-websocket.c 中的‘tvb_unmasked’函数中存在多个整数符号错误,远程攻击者可通过恶意的数据包利用这些漏洞造成拒绝服务)。Asterisk                                WebSocket Server 的 DoS 漏洞 CVE-2014-9374(该 WebSocket                                Server 某模块中存在双重释放漏洞,远程攻击者可通过发送零长度的帧利用该漏洞造成拒绝服务)。这两个 DDoS 漏洞跟 WebSocket 协议本身以及 WebSocket 应用程序相关性不大。但 2015 年来自 Cisco 的 Brian                                Manifold 和 Nebula 的 Paul McMillan 报告了一个 OpenStack Nova                                console 的 WebSocket 漏洞(CVE-2015-0259),这个漏洞得到广泛关注,并且被在很多 WebSocket 应用中发现。事实上,这种漏洞早在 2013 年就被一个德国的白帽黑客 Christian                                Schneider 发现并公开,Christian 将之命名为跨站点 WebSocket 劫持 Cross Site WebSocket                                Hijacking(CSWSH)。跨站点 WebSocket 劫持相对危害较大,也更容易被开发人员忽视。
什么是跨站点 WebSocket 劫持漏洞呢,前文已经提及,为了创建全双工通信,客户端需要基于 HTTP 进行握手切换到 WebSocket 协议,这个升级协议的过程正是潜在的阿喀琉斯之踵。大家仔细观察上文的握手 Get 请求,可以看到 Cookie 头部把域名下的 Cookie 都发送到服务器端。如果有机会阅读 WebSocket 协议(10.5 章客户端身份认证)就发现,WebSocket 协议没有规定服务器在握手阶段应该如何认证客户端身份。服务器可以采用任何 HTTP 服务器的客户端身份认证机制,譬如 cookie,HTTP 基础认证,TLS 身份认证等。因此,对于绝大多数 Web 应用来说,客户端身份认证应该都是 SessionID 等 Cookie 或者 HTTP                                Auth 头部参数等。熟悉跨站点请求伪造攻击 Cross Site Request                                Forgery(CSRF)的朋友到这里应该就可以联想到黑客可能伪造握手请求来绕过身份认证。
因为 WebSocket 的客户端不仅仅局限于浏览器,因此 WebSocket 规范没有规范 Origin 必须相同(有兴趣的读者可以阅读规范 10.2 章节了解对于 Origin 的规范)。所有的浏览器都会发送 Origin 请求头,如果服务器端没有针对 Origin                                头部进行验证可能会导致跨站点 WebSocket 劫持攻击。譬如,某个用户已经登录了应用程序,如果他被诱骗访问某个社交网站的恶意网页,恶意网页在某元素中植入一个 WebSocket 握手请求申请跟目标应用建立 WebSocket 连接。一旦打开该恶意网页,则自动发起如下请求。请注意,Origin 和 Sec-WebSocket-Key 都是由浏览器自动生成,Cookie 等身份认证参数也都是由浏览器自动上传到目标应用服务器端。如果服务器端疏于检查 Origin,该请求则会成功握手切换到 WebSocket 协议,恶意网页就可以成功绕过身份认证连接到 WebSocket 服务器,进而窃取到服务器端发来的信息,抑或发送伪造信息到服务器端篡改服务器端数据。有兴趣的读者可以将这个漏洞跟 CSRF 进行对比,CSRF 主要是通过恶意网页悄悄发起数据修改请求,不会导致信息泄漏问题,而跨站点 WebSocket 伪造攻击不仅可以修改服务器数据,还可以控制整个读取/修改双向沟通通道。正是因为这个原因,Christian 将这个漏洞命名为劫持(Hijacking),而不是请求伪造(Request                                Forgery)。
清单 3. 篡改过的 WebSocket 协议升级请求
1
2
3
4
5
6
7
8
9
10
11
12
13
14
GET ws://echo.websocket.org/?encoding=text HTTP/1.1
Host: echo.websocket.org
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
Upgrade: websocket
Origin: http://www.malicious
website.com
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-US,en;q=0.8,zh-CN;q=0.6
Cookie: _gat=1; _ga=GA1.2.290430972.14547651; JSESSIONID=1A9431CF043F851E0356F5837845B2EC
Sec-WebSocket-Key: 7ARps0AjsHN8bx5dCI1KKQ==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits




读到这里,熟悉 JavaScript 跨域资源访问的读者可能会怀疑以上观点。如果 HTTP                                Response 没有指定“Access-Control-Allow-Origin”的话,浏览器端的脚本是无法访问跨域资源的啊,是的,这就是众所周知的跨域资源共享 Cross-Origin                                Resource                                Sharing(CORS),这确实也是 HTML5 带来的新特性之一。但是很不幸,跨域资源共享不适应于 WebSocket,WebSocket 没有明确规定跨域处理的方法。
返回列表