跳到主要内容

WebSocket 提交返回劫持

测试环境搭建

首先我们可以搭建一个简易的测试环境

测试环境的搭建

点击下面的标签查看环境搭建教程

新建一个目录后输入 npm init 初始化项目

然后输入 npm i -S express express-ws 安装相关依赖

劫持

基础劫持 send

首先我们尝试一个最基础的劫持,尝试劫持 WebSocketsend 属性,以劫持发送内容。

const originSocket = window.WebSocket;
window.WebSocket = function (...args) {
const ws = new originSocket(...args);
const originSend = ws.send;
ws.send = function (...args) {
if (args[0].length > 0) {
args[0] = args[0] + "【被劫持提交了】";
}
return originSend.call(this, ...args);
};
return ws;
};

到这里还能正常跑通,接下来尝试劫持 onmessage 属性。

进阶劫持 onmessage

我们发现 socket 默认没有这个属性,这代表只能挂载一次,如果我们挂载了,网页再尝试挂载这个属性就会被覆盖。

所以尝试使用 Object.defineProperty 拦截回调内容,由我们管理回调

const originSocket = window.WebSocket;
window.WebSocket = function (...args) {
let callback = undefined;
const ws = new originSocket(...args);
const originSend = ws.send;
ws.send = function (...args) {
if (args[0].length > 0) {
args[0] = args[0] + "【被劫持提交了】";
}
return originSend.call(this, ...args);
};
ws.onmessage = function (evt) {
callback && callback(evt);
};
Object.defineProperty(ws, "onmessage", {
get: () => {
return callback;
},
set: (setCall) => {
callback = setCall;
},
});
return ws;
};

高级劫持: onmessage 返回值

然后发现onmeggsage返回的 evt 对象的属性无法修改,看过之前的教程,这里应该可以立刻就想到使用 Proxy 进行属性代理

const originSocket = window.WebSocket;
window.WebSocket = function (...args) {
let callback = undefined;
const ws = new originSocket(...args);
const originSend = ws.send;
ws.send = function (...args) {
if (args[0].length > 0) {
args[0] = args[0] + "【被劫持提交了】";
}
return originSend.call(this, ...args);
};
ws.onmessage = function (evt) {
const proxyEvent = new Proxy(evt, {
get: function (target, prop) {
const data = target[prop];
if (prop === "data") {
return data + " 【被劫持返回了】";
}
return data;
},
});
callback && callback(proxyEvent);
};
Object.defineProperty(ws, "onmessage", {
get: () => {
return callback;
},
set: (setCall) => {
callback = setCall;
},
});
return ws;
};

测试

最后测试一下拦截效果:

Connection open ...
Received Message: 你连接成功了 【被劫持返回了】
Received Message: Hello WebSockets!【被劫持提交了】---- 【来自服务端】 【被劫持返回了】

就此我们成功劫持了提交内容和返回数据,这样我们就可以在这里进行一些操作了。