WebSockets应用安全

一、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[i] = 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[i] = 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)); 

猜你喜欢

转载自blog.csdn.net/haoren_xhf/article/details/80927851