一、WebSockets应用场景 在Html5的WebSockets标准未出现之前,服务器是通过客户端(浏览器)轮询,来达到“推送消息”效果的,此方法低效且浪费资源 WebSockets在客户端(浏览器)和服务器之间建立TCP 持久连接,进行双向通信。http是请求响应机制(问-答,浏览器端发出请求,服务器端响应),而websocket使得浏览器与服务器建立起对话机制,双方都可以问和答。服务器也就可以任意推送消息到客户端(浏览器)
基于网页的客服系统、弹幕系统、聊天工具等多半会采用WebSockets技术
二、WebSockets使用示例WebSockets客户端代码,(使用ArrayBuffer传输通信数据,一种混淆抓包的方式)
function ab2str(buf) {
return String.fromCharCode.apply(null, new Uint16Array(buf));
}
function str2ab(str) {
var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
var bufView = new Uint16Array(buf);
for (var i=0, strLen=str.length; i < strLen; i++) {
bufView = str.charCodeAt(i);
}
return buf;
}
function connectws(){
var out = document.all.content;
var ws = new WebSocket('ws://xxxx.com');
ws.onopen=function(){
out.innerHTML+="<li>客户端已连接</li>";
ws.send(str2ab('Hello world!'));
}
ws.onmessage=function(evt){
out.innerHTML+="<li>"+ab2str(evt.data)+"</li>";
}
ws.onclose=function(){
out.innerHTML+="<li>客户端已断开连接</li>";
};
ws.onerror=function(evt){
out.innerHTML+="<li>"+evt.data+"</li>";
}
}
WebSockets服务器端代码有各个语言(php\python\nodejs\go...)版本
三、WebSockets安全3.1 wss协议为类似https的协议,而ws类似http明文协议 3.2 通常从http页面发起WebSockets连接,会将cookie传输到WebSockets服务器作为登录凭证。 若仅将cookie作为登录凭证,且没有验证Origin头,会存在csrf攻击,冒用身份连接上WebSockets服务器 某些应用(如京东的jimi智能客服)的做法可以借鉴,先发Ajax请求从服务器获取sid,然后凭此sid连接WebSockets服务器 3.3 安全分析者可以使用chrome开发者工具、burp suite抓websockets数据包 如图,chrome开发者工具
也可以在开发者工具console执行代码,进行抓包
WebSocket.prototype._send = WebSocket.prototype.send;
WebSocket.prototype.send = function(data){
console.log("\u2192 " + data);
this._send(data);
this.addEventListener('message', function(msg){
console.log('\u2190 ' + msg.data);
}, false);
this.send = function (data) {
this._send(data);
console.log("\u2192 " + data);
}
}
另外可以传输ArrayBuffer格式数据,对抓包工具看到的数据进行一定程度的混淆
ArrayBuffer是一种原始内存块,可以按任意数据格式进行存储。DataView提供了对ArrayBuffer进行任意格式set/get的api
var str = 'Hello';
var buf = new ArrayBuffer(str.length*2); // 2 bytes for each char
var bufView = new Uint16Array(buf);
for (var i=0, strLen=str.length; i < strLen; i++) {
bufView = str.charCodeAt(i);
}
var buffer = new ArrayBuffer(12);//byte
var x = new DataView(buffer, 0);//从0位开始
x.setInt8(0, 22);
x.setFloat32(1, Math.PI);
console.log(x.getInt8(0));
console.log(x.getFloat32(1));
3.4 WebSockets服务器能承受的连接资源有限(根据rfc文档),要注意DOS攻击 |