PRELOADER

当前文章 : 《跨站点WebSocket劫持如何导致完整的会话妥协》

12/2/2019 —— 

跨站点WebSocket劫持如何导致完整的会话妥协

WebSockets是一种HTML5功能,可通过单个TCP连接提供双向通信通道。这样可以通过在浏览器和服务器之间创建持久连接来构建实时应用程序。

Websockets最常见的应用是向Web应用程序添加聊天功能。下面这张图片为websockets工作原理图:

(参考:http://www.websocket.org

最近,我们对具有大量菜单选项和功能的相当复杂的应用程序进行了安全评估。该应用程序正在利用Web套接字技术来完成大部分操作。

这实际上意味着在大多数http代理日志中都找不到日志。在访问主页时,该网站会加载一个静态HTML页面以及一些JavaScript和CSS文件。

在此之后,整个通信转移到Websockets。为服务器创建websocket连接,这将加载网站的所有可见HTML部分。单击链接或提交表单会触发

该页面以向服务器发送多个WebSocket消息。服务器内部处理这些消息并通过WebSocket消息发送新的HTML内容,然后在浏览器中显示。

当捕获websocket消息时,很明显消息的数量是压倒性的。增加了每1秒后有一个短间隔保持活动消息交换的事实。现有工具无法完成任务。

因此,我必须向IronWASP添加一个Websocket Message Analyzer和WebSocket客户端,以了解这个Websocket实现过程。

你可以在这里读到它实现的全部过程。在测试应用程序时,我们发现它很容易受到跨站点WebSocket劫持的攻击

(首先由christian schneider http://www.christian-schneider.net/CrossSiteWebSocketHijacking.html讨论)。在讨论如何测试之前,

我将先讨论这个问题的影响。对这个问题的测试非常简单,您可以在测试前10分钟内使用Websockets的应用程序完成此操作。

我们应该明白,不通过浏览器在websockets上强制实施同源策略(SOP)(通过SSL加载的页面在某些浏览器中不能进行非SSL WebSocket连接)。

我们测试的应用程序依赖于http cookie进行会话验证。通过WebSocket从浏览器发送的消息不包含任何会话ID或其他随机参数。

这意味着,如果一个用户已经登录到他/她的浏览器漏洞的应用程序,具有HTTP://攻击者.COM在不同的标签页中打开,然后HTTP://攻击者.COM

可以尝试创建一个WebSocket连接易受攻击的应用程序和有效的经过身份验证的会话ID将(与浏览器一起)与此请求一起发送。

因此,现在由http://攻击者.com建立的WebSocket连接将具有与从易受攻击的应用程序中创建的WebSocket相同的访问级别。

由于我们的整个应用程序都在websockets上运行,因此劫持WebSocket将等同于劫持用户的会话。因此,实质上影响相当于持久性跨站点脚本。

如果你认为这很漏洞已经很严重了,那么你会惊讶地发现,在某些情况下,跨站点WebSocket脚本甚至可以导致用户系统上的远程代码执行,

就像IPython Notebook一样.[http://lambdaops.com/cross-origin-websocket-hijacking-of-ipython]

希望到现在为止,您确信这是你必须对使用WebSockets的应用程序执行的第一次检查。在进行测试之前,你需要完成这三步才能执行此检查:

1. WebSocket连接的URL。这从ws://或wss://开始

1. 用于创建此连接的Origin标头。这是进行WebSocket连接的页面的必要条件。

1. 浏览器和服务器之间发送一些消息,以便我们知道正常连接是什么样的。

下图显示了如何从IronWASP日志中获取Origin和WebSocket URL值。

获得此信息后,您可以通过几种不同的方式检查跨站点WebSocket劫持。我将解释三个简单的方法:

通过代理工具,如Burp

这里应该注意,burp具有WebSockets的拦截和记录功能。到目前为止,ZAP和IronWASP是唯一能够重新发送websocket请求的软件。

在burp中,我们不能重复发送websockets消息,但是我们仍然可以通过检查WebSocket握手是否成功来以有限的方式测试它。

为了测试这个,我们需要识别通过http(s)连接发生的websocket升级请求,并且可以重复发送请求。

下面的屏幕截图显示了一个burp Repeater日志,显示了对websocket连接的有效请求的请求和响应。

为了测试这个缺陷,我们需要做的就是发送另一个带有修改过的Origin头的请求。如果我们收到101 Web套接字协议握手,则表示已建立WebSocket连接。

如果未建立连接,则表示应用程序是安全的,因为它拒绝来自外部Origins的WebSocket连接。如果建立了连接,

那么我们将不得不执行进一步的检查以确认应用程序是否容易受到跨站点WebSocket劫持的攻击。即使建立了连接,

应用程序也只有在响应WebSocket消息时才会受到攻击,就像它对来自有效Origin的连接一样。

这是因为开发人员可以将Origin验证逻辑与访问控制检查一起放置。因此,仍然会建立连接,但在这种情况下,

外部Origins将无法访问经过身份验证的数据,这是一件好事。

ZAP具有重新发送消息的能力,但据我所知,它确实允许篡改Origin头。下面显示的方法说明了如何对CSWSH进行更详细的检查。

使用跨站点WebSocket劫持在线测试程序

打开应用程序以在浏览器中进行测试并登录。访问完毕后,在另一个选项卡中打开http://ironwasp.org/cswsh.html,

输入WebSocket URL并点击“连接”。建立连接后,您必须能够从此页面向服务器发送消息。发送从有效会话中捕获的消息,

并查看服务器如何响应。如果服务器以与有效会话相同的方式响应,那么它很可能容易受到跨站点WebSocket劫持的攻击。

使用IronWASP的WebSocket客户端

使用上述方法进行测试时,发送到服务器的Origin是http://ironwasp.org。如果您想要更灵活地设置Origin值,

那么您可以使用IronWASP的WebSocket Client实用程序。这让你定义你想要的任何Origin值并测试WebSocket连接。

在应用程序可能允许来自应用程序的公共Origin的WebSocket连接以及来自Origin值的连接的情况下,这可能会派上用场,

这些连接来自localhost或某些内部私有IP地址。这可能是为了支持公司的开发人员和内部测试人员。通过使用IronWASP的WebSocket客户端,

您可以尝试使用localhost或私有IP地址的组合来查看它是否有效。如果确实如此,那么在现实场景中利用这个问题可能有点棘手。

例如,如果应用程序允许http:/127.0.0.1:8080作为Origin,那么如果被攻击者在端口8080上运行本地Web服务器并且应用程序具有跨站点脚本,则可以利用此功能。

使用IronWASP的WebSocket API自动检查

如果您要检查Origin标头的localhost和私有IP地址的不同组合,那么使用自定义脚本自动执行此检查可能更容易。IronWASP使您能够以Python或Ruby编写脚本。

例如,以下脚本将检查专用IP地址空间中的每个IP作为Origin标头值,以查看它是否被接受。

import clr
clr.AddReference("WebsocketClient.exe")
from WebsocketClient import *
def check_conn(origin):
print "Testing origin - " + origin
ws = SyncWebsockClient()
ws.Connect("ws://tatgetapp.com/ws", origin, "SessionID=KSDI2923EWE9DJSDS01212")
ws.Send("first message to send")
msg = ws.Read()
ws.Close()
if msg == "message that is part of valid session":
  print "Connection successful!!"
  return True
else:
  return False

def check_nw():
  for nws in ["192.168.0.0/16", "172.16.0.0/12", "10.0.0.0/8"]:
for ip in Tools.NwToIp(nws):
  if check_conn("http://" + ip):
break

check_nw()

原文链接:https://www.notsosecure.com/how-cross-site-websocket-hijacking-could-lead-to-full-session-compromise/