js前端加密绕过-Jsrpc
2023-6-10 21:9:2 Author: E条咸鱼(查看原文) 阅读量:36 收藏

JSRPC(JavaScript Remote Procedure Call)是一种基于 JavaScript 的远程过程调用协议,用于实现客户端和服务器之间的通信和函数调用。它允许开发人员在客户端 JavaScript 代码中调用远程服务器上的函数,以便获取数据、执行操作或获取服务。

在实际渗透测试的场景中,会遇到很多前端加密、签名校验、返回包加密等等的场景,如果是自己去尝试获取加解密函数,然后自己构造环境去绕过,第一时间成本确实很高,如果js文件进行混淆那种,时间成本还是很高的,第二点对于我这种看看还行,自己本地运行就是纯折磨的来说,jsrpc算是不错的选择。

因为不需要知道完整流程是如何实现的,只需要找到函数然后调用即可,因为没有找到数据包也加密的场景尝试自动解密,本文就拿快手src的登录功能进行演示。

文章实现的逻辑流程图如下:

寻找网站加密函数

演示的站点用快手src,别的不说,快手src的礼物确实多(

直接搜索encrypt或者password都可以定位到加密的函数

因为不运行的状态下,浏览器可能不会加载这个js,导致你在console.log(le.encrypt("123",w(w({},0))));的时候会提示le这个是未定义的,所以我们先设置断点,然后在调试模式下,设置为全局变量

设置完成后,尝试加密一个内容

这部分的内容完成后,就可以尝试构造jsrpc的部分了

安装Jsrpc

这里用到的是sekiro,jsrpc只是其中的一部分

https://github.com/yint-tech/sekiro-open

下载后,按照下面的方式运行

构建完成后,会生成文件夹sekiro-open-demo,在bin文件夹中根据系统来选择运行.bat还是.sh即可

如果你不想自己构建,可以在下面地址里下载

https://oss.iinti.cn/sekiro/sekiro-demo

运行后的样子如下:

这里要说明的是,在网上很多文章文档的地址都不正确(毕竟时间长,难免地址变了),新的地址是https://sekiro.iinti.cn/sekiro-doc/

在文档中可以看到,官方提供了注入的js

但是在.js中,还需要我们自己单独注册一个接口

所以我们把前面的js复制进来后,在底下自己自定义接口就好了(注意:免费版的地址是business-demo)

function guid({
    function S4({
        return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1);
    }
    return (S4() + S4() + "-" + S4() + "-" + S4() + "-" + S4() + "-" + S4() + S4() + S4());
}
//Modify content
group = "kuaishou";
//自定义组织名,一般以网站为单位
registerAction = "encrypt";
//自定义方法名,一般以函数为单位
var client = new SekiroClient("ws://127.0.0.1:5612/business-demo/register?group=" + group + "&clientId=" + guid());
client.registerAction(registerAction, function(request, resolve, reject{
    response = le.encrypt(request['text'], w(w({}, o)));
    //接口返回内容 resolve(response);
    resolve(response);
})

写完后,运行就ok了

这个时候我们访问接口,就能请求数据并加密了

设置mitmproxy

在我们的环境中,我们需要调用这个jsrpc来加密后,将处理过的数据包发送到网站中,所以需要一个mitmproxy来加密参数,然后发送

首先安装运行库

pip3 install mitmproxy

接着创建服务器

import requests
import re
import json
from mitmproxy import ctx

def encrypt(data):
    url="http://127.0.0.1:5612/business-demo/invoke?group=kuaishou&action=encrypt&text={}".format(data)
    res=requests.get(url)
    print(res.text)
    res = json.loads(res.text)
    return res['encryptText']

def request(flow):
    # 获取数据包
    body = flow.request.get_text()

    data = {}
    for pair in body.split("&"):
        key, value = pair.split("=")
        data[key] = value

    # 获取 password
    password = data.get("password""")
    phone = data.get("phone""")
    # 调用 encrypt 函数进行加密
    encrypted_password = encrypt(password)
    encrypted_phone = encrypt(phone)
    # 修改请求的 body 数据为加密后的值
    data["password"] = encrypted_password
    data["phone"] = encrypted_phone

    # 构造修改后的 body 数据
    modified_body = "&".join([f"{key}={value}" for key, value in data.items()])

    # 设置修改后的请求 body 数据
    flow.request.set_text(modified_body)
    ctx.log.warn("加密内容: "+str(flow.request.get_text()))

# 请求后的数据
def response(flow):
    response = flow.response 
    print(response.text)
    ctx.log.info(str(response.status_code))

注意我这里面的

data = {}
    for pair in body.split("&"):
        key, value = pair.split("=")
        data[key] = value

正常来说,网上的例子都是json.loads(),但是我们的数据包并不是json格式的

所以只能自己获取内容后,重新生成这部分的内容,写完后保存,命令运行

mitmproxy -v -s <filename> -p <port>
mitmweb -v -s <filename> -p <port>

这两个都可以,web也会监听端口,但是web的话会多一个web的可视化界面

我们设置一个burpsuite的代理到mitmproxy中,然后尝试发送一个包

burpsuite数据包如下


我们在mitmweb中查看数据包,可以看到内容已经加密了



文章来源: http://mp.weixin.qq.com/s?__biz=MzU1Mjk3MDE2Mg==&mid=2247485499&idx=1&sn=377bc45dd046110b9fded5bc5cd05e11&chksm=fbf8bae6cc8f33f0e5fc5963e52c10560875772f4b54c19f48029060d9d317878703c187ff21#rd
如有侵权请联系:admin#unsafe.sh