Sekiro环境基础搭建之WSS

一、服务端部署

项目地址:https://github.com/yint-tech/sekiro-open

官方文档地址:https://sekiro.iinti.cn/sekiro-doc/01_manual/4.server_install.html

所用环境是Ubuntu20

安装步骤:

  1. 安装docker,可以参考这篇文章 https://blog.csdn.net/qq_44732146/article/details/121207737
  2. 安装docker-compose:sudo pip install docker-compose
  3. 安装Sekiro:

启动docker之后,执行如下命令

curl https://oss.iinti.cn/sekiro/quickstart.sh | bash
  1. 打开网址 http://(服务器的IP):5612,注册一个账号(第一个注册账号是超级管理员)

img.png

二、客户端连接服务端

此处可参考官方文档

如果你的注入网站有wss的同源检测拦截,那么就算是可以创建wss连接,也可能因为同源问题被阻断.
假定访问网站:https://xxx.abc.com
使用wss连接sekiro: wss://sekiro.iinti.cn/business/register?group=ws-group&clientId=1221
如果 www.abc.com , 存在同源策略拦截,则可能报错:refused to connect to 'wss://sekiro.iinti.cn/business/register?group=ws-group&clientId=1221' because of it violates the following Content Security Policy directive: xxxxxx

提前嗦嗦安装CA证书

点击这里 pem格式 或者 crt格式 下载证书,并跟随系统引导安装根证书

方法一:使用代理解决CSP

Sekiro的端口服务实现了http/https代理,你可以直接将Sekiro的端口设定为你的浏览器的代理

如果你的注入网站由wss的同源检测拦截,那么可以通过将浏览器的代理设定到sekio服务器上,此时由于流量都能经过sekiro服务器,并且sekiro拥有CA根证书可以解密和伪造流量。 那么此时wss连接可以直接使用对应主网页的域名构造wss连接,此时sekiro可以感知这个连接需要转发到sekiro服务器,将会全自动在内部处理。

此时可以完美解决wss同源拦截问题

请注意,当通过代理的方式访问Sekiro,那么Sekiro必然开启ssl解密,请注意此时一定需要安装Sekiro的CA证书(上文已提及),否则https网页将会全部因为证书不被信任而被阻断

方法二:构造子域名解决CSP

如果整体将Sekiro服务器设置为代理服务器,则会将所有的流量打入到Sekiro服务器,在考虑多浏览器集群控制的时候,多IP聚集可能带来风控问题,以及Sekiro服务器作为出口ip也可能带来风控问题。 此时可以使用pac脚本单独控制Sekiro的WebSocket连接进入sekiro服务器,其余的流量则正常通过。

  1. 下载代理插件:https://github.com/FelisCatus/SwitchyOmega
  2. 配置PAC脚本
function FindProxyForURL(url, host) {
    if (shExpMatch(url,"wss://*")) {
        // 只要是wss协议,则代理到sekiro.iinti.cn:5612
        // 这里实现比较粗暴,具体规则可根据网站实际调整
        return "PROXY sekiro.iinti.cn:5612";
    }
return "DIRECT";
}
  1. 构造和目标网站完全一致的同域名websocket连接
var client = new SekiroClient("wss://xxx.abc.com/business/register?group=test-ws&clientId=" + Math.random());
client.registerAction("testAction", function (request, resolve, reject) {
    resolve("ok");
});
  1. 构造子域名解决CSP

    1. 假定网站sekiro部署在: 47.93.16.121:443
    2. 配置hosts文件: sekrio.xxx.abc.com 47.93.16.121 使得域名sekiro.xxx.abc.com解析到47.93.16.121( 也即模拟申请一个域名,绑定在sekiro服务器上,并且让这个域名在目标网站的子域名)
    3. 安装CA证书,确保系统根证书完成安装,并且设置信任sekirio证书
    4. 使用构造子域名的wss连接: wss://sekiro.xxx.abc.com/business/register?group=ws-group&clientId=1221 创建连接

    条件:需要CSP规则中支持wss: connect-src wss: ,否则只能使用代理的方式,这是因为CSP规则认为http的网页不应该被websocket加载:https://csplite.com/csp118/

wss注入

复制官方的代码:

function SekiroClient(e){if(this.wsURL=e,this.handlers={},this.socket={},!e)throw new Error("wsURL can not be empty!!");this.webSocketFactory=this.resolveWebSocketFactory(),this.connect()}SekiroClient.prototype.resolveWebSocketFactory=function(){if("object"==typeof window){var e=window.WebSocket?window.WebSocket:window.MozWebSocket;return function(o){function t(o){this.mSocket=new e(o)}return t.prototype.close=function(){this.mSocket.close()},t.prototype.onmessage=function(e){this.mSocket.onmessage=e},t.prototype.onopen=function(e){this.mSocket.onopen=e},t.prototype.onclose=function(e){this.mSocket.onclose=e},t.prototype.send=function(e){this.mSocket.send(e)},new t(o)}}if("object"==typeof weex)try{console.log("test webSocket for weex");var o=weex.requireModule("webSocket");return console.log("find webSocket for weex:"+o),function(e){try{o.close()}catch(t){}return o.WebSocket(e,""),o}}catch(t){console.log(t)}if("object"==typeof WebSocket)return function(o){return new e(o)};throw new Error("the js environment do not support websocket")},SekiroClient.prototype.connect=function(){console.log("sekiro: begin of connect to wsURL: "+this.wsURL);var e=this;try{this.socket=this.webSocketFactory(this.wsURL)}catch(o){console.log("sekiro: create connection failed,reconnect after 2s"),setTimeout(function(){e.connect()},2e3)}this.socket.onmessage(function(o){e.handleSekiroRequest(o.data)}),this.socket.onopen(function(e){console.log("sekiro: open a sekiro client connection")}),this.socket.onclose(function(o){console.log("sekiro: disconnected ,reconnection after 2s"),setTimeout(function(){e.connect()},2e3)})},SekiroClient.prototype.handleSekiroRequest=function(e){console.log("receive sekiro request: "+e);var o=JSON.parse(e),t=o.__sekiro_seq__;if(!o.action)return void this.sendFailed(t,"need request param {action}");var n=o.action;if(!this.handlers[n])return void this.sendFailed(t,"no action handler: "+n+" defined");var s=this.handlers[n],i=this;try{s(o,function(e){try{i.sendSuccess(t,e)}catch(o){i.sendFailed(t,"e:"+o)}},function(e){i.sendFailed(t,e)})}catch(r){console.log("error: "+r),i.sendFailed(t,":"+r)}},SekiroClient.prototype.sendSuccess=function(e,o){var t;if("string"==typeof o)try{t=JSON.parse(o)}catch(n){t={},t.data=o}else"object"==typeof o?t=o:(t={},t.data=o);(Array.isArray(t)||"string"==typeof t)&&(t={data:t,code:0}),t.code?t.code=0:t.status?t.status=0:t.status=0,t.__sekiro_seq__=e;var s=JSON.stringify(t);console.log("response :"+s),this.socket.send(s)},SekiroClient.prototype.sendFailed=function(e,o){"string"!=typeof o&&(o=JSON.stringify(o));var t={};t.message=o,t.status=-1,t.__sekiro_seq__=e;var n=JSON.stringify(t);console.log("sekiro: response :"+n),this.socket.send(n)},SekiroClient.prototype.registerAction=function(e,o){if("string"!=typeof e)throw new Error("an action must be string");if("function"!=typeof o)throw new Error("a handler must be function");return console.log("sekiro: register action: "+e),this.handlers[e]=o,this};

var client = new SekiroClient("wss://www.linkedin.cn/business/register?group=ws-group&clientId=" + Math.random());
client.registerAction("testAction", function (request, resolve, reject) {
    c = undefined;
    resolve(window.ja("d_incareer2_profile_homepage", c));
});

浏览器调用接口,成功

img_1.png