SRC思路分享-JS逆向(jsrpc运用)

admin 2024年6月3日18:32:53评论15 views字数 4564阅读15分12秒阅读模式

前言‍‍‍‍‍

当进行渗透测试或安全评估时,JavaScript(JS)成为我们特别关注的领域之一。在前端源代码中,我们可能会找到接口、敏感信息以及一些逻辑处理,比如参数加解密等。为了防止攻击者拦截数据包篡改参数,使服务端执行恶意指令,开发者通常会在前端对输入参数进行加密,这是一种常见的防御手段。这导致我们抓取到的数据包中传入的参数和返回的包内容都是加密的。我们需要对加密方式进行逆向分析。如果无法还原出加密和解密方式,渗透测试可能会受到阻碍。逆向分析有多种方法,下面将介绍一种常用的,即JSRPCJS逆向中的应用。

JSRPC工作原理‍‍‍‍

JSRPC简单来说就是远程调用JavaScript函数的方法。它的原理是在客户端(也就是浏览器)注入JSRPC环境,使客户端与JSRPC服务器建立WebSocket连接,保持通信。然后在客户端注册需要用到的加解密函数的demo,这样当JSRPC服务器发送信息给客户端时,客户端接收到并执行相应的方法,然后将结果发送回服务器。服务器接收到结果并将其显示出来。

SRC思路分享-JS逆向(jsrpc运用)

案例‍‍‍‍

先抓个包看看是哪个接口‍‍

SRC思路分享-JS逆向(jsrpc运用)
SRC思路分享-JS逆向(jsrpc运用)
在接口处打个断点,可以看到email首先通过:SG_sm4encrypt(this.email, 'N200y834yEhD5gX5')加密

SRC思路分享-JS逆向(jsrpc运用)

继续跟进,如下图,大致可以看懂完整的加密函数流程,但是一些函数的调用需要继续跟进,因此先在关键三处打上断点

SRC思路分享-JS逆向(jsrpc运用)

a:三十多位随机值o:g.a.sign(a + s() (e.data) + n)n:时间戳email:SG_sm4encrypt("[email protected]","N200y834yEhD5gX5")s()(e.data):{"email":SG_sm4encrypt("[email protected]","N200y834yEhD5gX5"),"simpleCaptcha":"YNS2a"}param:g.a.globalEncrypt(a + s() (e.data) + o)t:时间戳,0Requesttime:g.a.globalEncrypt(t)

这些可以通过控制台进行调试出来

SRC思路分享-JS逆向(jsrpc运用)
梳理大致流程后,只需跟进g.a.globalEncryptg.a.sign,可以通过多种方式回溯函数;
第一种:如上图打断点

第二种:在控制台调试出相应函数全局搜索

SRC思路分享-JS逆向(jsrpc运用)

全局搜索

SRC思路分享-JS逆向(jsrpc运用)
很明显,还有一个函数不是很明确,继续打个断点,调试出来即可this.sg2()

SRC思路分享-JS逆向(jsrpc运用)

SRC思路分享-JS逆向(jsrpc运用)

至此函数所用到的加密参数都知道了,a是三十多位的随机值可以写死,s() (e.data) 里面带有邮箱和图形验证码,o的加密公式也知道了,n是时间戳,t是时间戳,其他:

o的值就是:SG_sm3encrypt(a + s() (e.data) + n)

param的值就是:SG_sm4encrypt(a + s() (e.data) + o,'N200y834yEhD5gX5')

Requesttime的值就是:SG_sm4encrypt(t,'N200y834yEhD5gX5')

整个流程已经基本完成,接下来只需编写还原加密函数的整体逻辑。但这可能会很费时,因此有了第二种方式:利用JSRPC远程调用JavaScript函数。这样做的好处是我无需编写加解密逻辑,只需了解参数值是如何生成的,然后调用目标网站的函数来实现加解密功能即可。

JSRPC案例

首先在Github下载JSRPC,下载地址:https://github.com/jxhczhl/JsRpc,编译成exe后,再本地命令行执行exe文件,目的是启动一个JSRPC服务,然后监听12080端口,在客户端控制台注入JSRPC环境。
function Hlclient(wsURL) {    this.wsURL = wsURL;    this.handlers = {        _execjs: function (resolve, param) {            var res = eval(param)            if (!res) {                resolve("没有返回值")            } else {                resolve(res)            }

        }    };    this.socket = undefined;    if (!wsURL) {        throw new Error('wsURL can not be empty!!')    }    this.connect()}

Hlclient.prototype.connect = function () {    console.log('begin of connect to wsURL: ' + this.wsURL);    var _this = this;    try {        this.socket = new WebSocket(this.wsURL);        this.socket.onmessage = function (e) {            _this.handlerRequest(e.data)        }    } catch (e) {        console.log("connection failed,reconnect after 10s");        setTimeout(function () {            _this.connect()        }, 10000)    }    this.socket.onclose = function () {        console.log('rpc已关闭');        setTimeout(function () {            _this.connect()        }, 10000)    }    this.socket.addEventListener('open', (event) => {        console.log("rpc连接成功");    });    this.socket.addEventListener('error', (event) => {        console.error('rpc连接出错,请检查是否打开服务端:', event.error);    });

};Hlclient.prototype.send = function (msg) {    this.socket.send(msg)}

Hlclient.prototype.regAction = function (func_name, func) {    if (typeof func_name !== 'string') {        throw new Error("an func_name must be string");    }    if (typeof func !== 'function') {        throw new Error("must be function");    }    console.log("register func_name: " + func_name);    this.handlers[func_name] = func;    return true

}

//收到消息后这里处理,Hlclient.prototype.handlerRequest = function (requestJson) {    var _this = this;    try {        var result = JSON.parse(requestJson)    } catch (error) {        console.log("catch error", requestJson);        result = transjson(requestJson)    }    //console.log(result)    if (!result['action']) {        this.sendResult('', 'need request param {action}');        return    }    var action = result["action"]    var theHandler = this.handlers[action];    if (!theHandler) {        this.sendResult(action, 'action not found');        return    }    try {        if (!result["param"]) {            theHandler(function (response) {                _this.sendResult(action, response);            })            return        }        var param = result["param"]        try {            param = JSON.parse(param)        } catch (e) {}        theHandler(function (response) {            _this.sendResult(action, response);        }, param)

    } catch (e) {        console.log("error: " + e);        _this.sendResult(action, e);    }}

Hlclient.prototype.sendResult = function (action, e) {    if (typeof e === 'object' && e !== null) {        try {            e = JSON.stringify(e)        } catch (v) {            console.log(v)//不是json无需操作        }    }    this.send(action + atob("aGxeX14") + e);}

function transjson(formdata) {    var regex = /"action":(?<actionName>.*?),/g    var actionName = regex.exec(formdata).groups.actionName    stringfystring = formdata.match(/{..data..:.*..w+..:s...*?..}/g).pop()    stringfystring = stringfystring.replace(/\"/g, '"')    paramstring = JSON.parse(stringfystring)    tens = `{"action":` + actionName + `,"param":{}}`    tjson = JSON.parse(tens)    tjson.param = paramstring    return tjson}

然后再控制台建立链接JSRPC服务器的通信

// 注入环境后连接通信var demo = new Hlclient("ws://127.0.0.1:12080/ws?group=zzz");// 可选  //var demo = new Hlclient("ws://127.0.0.1:12080/ws?group=zzz&clientId=hliang/"+new Date().getTime())

SRC思路分享-JS逆向(jsrpc运用)

后续就是需要注册需要调用哪个函数的方法,JSRPC作者也是提供了demo,过一遍就行,这里不做解释,这里我们只需要注册相应调用函数的方法就可以了

demo.regAction("SG_sm3encrypt", function (resolve,param) {//这样添加了一个param参数,http接口带上它,这里就能获得var o = SG_sm3encrypt(param)resolve(o);})

demo.regAction("SG_sm4encrypt", function (resolve,param) {//这里还是param参数 param里面的key 是先这里写,但到时候传接口就必须对应的上res=SG_sm4encrypt(param["value"],param["key"])resolve(res);})

SRC思路分享-JS逆向(jsrpc运用)

然后编写脚本识别图形验证码获取图形验证码的值,带入函数中即可,核心代码逻辑就这些

SRC思路分享-JS逆向(jsrpc运用)

SRC思路分享-JS逆向(jsrpc运用)

那么解密过程也是同理,后续就是与burp联动这些了,有时间再分享。

原文始发于微信公众号(极星信安):SRC思路分享-JS逆向(jsrpc运用)

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年6月3日18:32:53
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   SRC思路分享-JS逆向(jsrpc运用)https://cn-sec.com/archives/2810430.html

发表评论

匿名网友 填写信息