资源:
sekiro : http://sekiro.iinti.cn/sekiro-doc/ ( 官方文档 jsRPC )
sekiro下载地址: https://oss.iinti.cn/sekiro/sekiro-demo
MorePossibility: https://github.com/kaliwin/MorePossibility
go-Api : https://github.com/kaliwin/MorePossibility-GO (以后api都会放着直接引用即可)
jsRpc连接代码 :https://github.com/kaliwin/ManDown (名字是jsrpc.js)
GO的代码也在https://github.com/kaliwin/ManDown/ (名字是jsRpc-GO-Demo)
场景演示
目标:寻找js加密函数做成RPC 然后使用MorePossibility 制作迭代处理器和重放包自动加密
目标fofa语法 : fid="1GicJUgv/iuztxzbGce3Qw=="
这里只是做演示实际并没有发起入侵测试
密码是经过js加密的
你在控制台就能直接调用加解密函数, 实际中你要自己调试
现在有几个方案
1、继续调试找到IV和KEY 之后便可还原算法
2、不跟了因为我们现在已经找到加密和解密函数了,直接调用就行了
这就涉及到了js RPC 以下是一个生动的逻辑图
逻辑就是sekiro开启一个服务然后你浏览器要运行一个js和他建立webSocket连接 之后用户发起http请求给sekiro要调用js函数然后sekiro就会给浏览器发送命令调用之后返回
我们先启动sekiro服务
下载地址 :https://oss.iinti.cn/sekiro/sekiro-demo
就下最新的 他会运行jar 目前没发现对jre有要求,有java环境就行
进到bin 你是linux就执行sh windows就是另一个
conf/config.properties 是你服务的端口默认是5612
建立连接的js脚本
https://github.com/kaliwin/ManDown/blob/main/jsrpc.js
后面都是写死的,改这里就行
大致逻辑是注册一个连接 那个组group就当作连接名就行,因为他允许多个连接, client.registerAction 是注册一个行动第一个参数是名称后面调用的时候要用到,第二个参数是 function (request, resolve, reject)
后面演示你就懂了
var client = new SekiroClientTest("ws://127.0.0.1:5612/business-demo/register?group=test&clientId=" + guid());
//注册一个行动监听
client.registerAction("encrypt", function (request, resolve, reject) {
try {
var data = request['data']
resolve(window._e(data))
} catch (e) {
reject("error: " + e);
}
});
client.registerAction("Decrypt", function (request, resolve, reject) {
try {
var data = request['data']
resolve(window._d(data))
} catch (e) {
reject("error: " + e);
}
});
client.registerAction("test", function (request, resolve, reject) {
try {
console.log(request)
reject("200 0k");
} catch (e) {
reject("error: " + e);
}
});
}
官方文档只要几行,但是我告诉你不要用他的,因为我永远也不能忘记当时万事具备在要使用他的时候他服务器特么504 ,而且有时在机房里是没有外网的所以你就用我这个就行
我们先把sekiro注入进去
这里注册了两个行动监听加密和解密他会调用window._d和window._e
但是现在并没有这个函数 所以我们要把实际加解密的函数赋值给他们
//创建webSocket 连接
var client = new SekiroClientTest("ws://127.0.0.1:5612/business-demo/register?group=test&clientId=" + guid());
//注册一个行动监听
client.registerAction("encrypt", function (request, resolve, reject) {
try {
var data = request['data']
resolve(window._e(data))
} catch (e) {
reject("error: " + e);
}
});
client.registerAction("Decrypt", function (request, resolve, reject) {
try {
var data = request['data']
resolve(window._d(data))
} catch (e) {
reject("error: " + e);
}
});
}
console.log("超时连接")
setTimeout(sek_start, 2000)
直接把这个代码放到控制台回车就行 (上面这个只是关键代码 记得是完整的js代码)
进行函数赋值 你可以在断点调式的时候赋值 之后就可以在外面调用
现在函数已经绑定好了我们发起http调用
group和action 都是你注入时定义的 , 你把他理解为路由就行
http://127.0.0.1:5612/business-demo/invoke?group=test&action=encrypt&data=admin123
现在jsRPC有了我们可以使用MorePossibility 去联动了
我把grpc的包稍稍封装了你建立新项目直接引用包就行
import "github.com/kaliwin/MorePossibility-GO/BurpApi"
我都封装好了你直接引用我的包 就这一个main文件,你随时可以开启IDE编写你想要的逻辑
package main
import (
"context"
"encoding/json"
"fmt"
"github.com/kaliwin/MorePossibility-GO/BurpApi"
"google.golang.org/grpc"
"io"
"log"
"net"
"net/http"
)
// SekiroData Sekiro返回的数据结构
type SekiroData struct {
ClientId string `json:"clientId"`
Data string `json:"data"`
Status int `json:"status"`
}
// JsRpcDemo jsRpc演示
type JsRpcDemo struct {
BurpApi.UnimplementedIntruderPayloadProcessorServerServer // 迭代处理器
}
// IntruderPayloadProcessor 迭代处理器
func (JsRpcDemo) IntruderPayloadProcessor(c context.Context, payload *BurpApi.PayloadProcessorData) (*BurpApi.ByteData, error) {
// 通过http去调用js函数 如果数据过大可以用POST
resp, err := http.Get("http://127.0.0.1:5612/business-demo/invoke?group=test&action=encrypt&data=" + string(payload.GetPayload()))
if err != nil {
return nil, err
}
byteS, _ := io.ReadAll(resp.Body)
var sekiroData SekiroData
err = json.Unmarshal(byteS, &sekiroData)
if err != nil {
log.Println(err)
return nil, err
}
// 返回js加密后的结果
return &BurpApi.ByteData{ByteData: []byte(sekiroData.Data)}, err
}
func main() {
listen, err := net.Listen("tcp", ":9000")
if err != nil {
log.Println(err)
return
}
server := grpc.NewServer()
BurpApi.RegisterIntruderPayloadProcessorServerServer(server, JsRpcDemo{})
fmt.Println("[+] Grpc 服务启动")
err = server.Serve(listen)
if err != nil {
log.Println(err)
return
}
}
程序启动 注册服务
打完收工
接下来就是流量处理在重放器中自动完成加密
这里我做了比较复杂的操作 首先判断流量来源是不是重放器
之后判断有没有encrypt{ 因为我们并不希望重放器所有流量都要加密我们也不能确定所有需要加密的参数位置,因此用encrypt{admin}end 来表示admin需要被加密,这样你的代码就会很灵动了你可以写多个加密方案这样更像一种模板 ,由你的程序来决定admin要被如何处理
这样说你不会明白的你得细细品尝这个代码
gh{admin}end
encrypt{admin}end
aes{admin}end
// HttpHandleRequestReceived 请求流量处理
func (JsRpcDemo) HttpHandleRequestReceived(c context.Context, req *BurpApi.HttpFlowReqData) (*BurpApi.HttpRequestAction, error) {
if BurpApi.HttpFlowSource_REPEATER == req.GetHttpFlowSource() { // 判断流量来源 只处理重放器流量
reqData := req.GetHttpReqGroup().GetHttpReqData()
httpData := reqData.GetData() // 完整请求报文
body := httpData[reqData.BodyIndex:] // 切割请求体
str := string(body)
indexStr := "encrypt{"
endStr := "}end"
index := strings.Index(str, indexStr) // 要加密的开始下标
end := strings.Index(str, endStr) // 要加密的结束下标
if index == -1 { // 没有要加密的数据
return &BurpApi.HttpRequestAction{Continue: true}, nil
}
text := str[index+len(indexStr) : end] // 需要解密的内容
fmt.Println("原文: " + text)
// 通过http去调用js函数 如果数据过大可以用POST
resp, err := http.Get("http://127.0.0.1:5612/business-demo/invoke?group=test&action=encrypt&data=" + text)
if err != nil {
return nil, err
}
byteS, _ := io.ReadAll(resp.Body)
var sekiroData SekiroData
err = json.Unmarshal(byteS, &sekiroData) // 解析jsRpc结果
replace := []byte(strings.Replace(str, indexStr+text+endStr, sekiroData.Data, 1)) // 替换请求体
// 将字节流读回请求对象这样方便处理Content-Length 你直接将字节流转为String在修改也是一样
request, _ := http.ReadRequest(bufio.NewReader(bytes.NewReader(httpData)))
request.ContentLength = int64(len(replace)) // 计算长度
request.Body = io.NopCloser(bytes.NewReader(replace)) // 重写请求体
var by bytes.Buffer
_ = request.Write(&by) // 将请求体读回字节流
// 获取原先请求组 注意这个一个指针引用 GetHttpReqGroup()这个函数返回的不是指针 但是如果你直接使用HttpReqGroup 可能会有空指针 自行判断
reqGroup := req.HttpReqGroup
reqGroup.HttpReqData.Data = by.Bytes() // 修改请求报文
reqGroup.AnnotationsText.IsInfo = true
reqGroup.AnnotationsText.Notes = "重放器自动加密测试"
reqGroup.AnnotationsText.Color = BurpApi.HighlightColor_BLUE // 蓝色高亮
return &BurpApi.HttpRequestAction{
Continue: false,
IsReviseReq: true, // 修改请求
HttpReqGroup: reqGroup,
}, err
}
return &BurpApi.HttpRequestAction{Continue: true}, nil
}
程序启动
服务注册
如果没有加密服务器就是500
完成自动加密
将用户名加密
解密也是一样的建议使用编辑框来渲染解密后的报文
大致逻辑是一样的 这里是解密不要忘了改sekiro的action
之后你就慢慢点看到的就都是明文了,就可以测他人所不能测的了
说实话这个框框是真的丑, 我一直想把他弄成像下面这样的多好看
还有一个应用场景就是sqlmap的ByPass了 无非就是sqlmap挂个代理到burp然后再像上面这样处理 ,我就不演示了
原文始发于微信公众号(KQsec):MorePossibility 实际应用(加解密场景 Demo)
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论