Burpsuite加解密插件Galaxy使用第三课
目录
XX站点针对aes_cbc加解密利用,使用burpsuite:Galaxy3.1.0插件
感谢博主网址支持: vue_demo,(对应的地址还请不要扫描爆破,仅做js逆向学习使用)
源码及github在:GitHub - 0ctDay/encrypt-decrypt-vuls: 加解密逻辑漏洞靶场
001 环境判断
对应的验证码前端验证不影响正常破解
重新输入密码并提交,未提示验证码错误,判断对应的验证码无失效次数
002 获取加解密算法
js逆向,浏览器按F12,搜索加解密关键字,如:decrypt
查询到A处数据
进行相关调试,发现就是对应的加解密算法
获取对应的加解密算法,本次使用aes_cbc逻辑
// aes_cbc加解密算法
var f = a.a.enc.Utf8.parse("1234567891234567")
, h = a.a.enc.Utf8.parse("1234567891234567");
function l(t) {
var e = a.a.AES.encrypt(t, f, {
iv: h,
mode: a.a.mode.CBC,
padding: a.a.pad.Pkcs7
});
return e.toString()
}
function d(t) {
var e = a.a.AES.decrypt(t, f, {
iv: h,
mode: a.a.mode.CBC,
padding: a.a.pad.Pkcs7
});
return e.toString(a.a.enc.Utf8)
}
// 生成随机32位字符数据,对应请求头中的RequestId数据
function p() {
var t = "0123456789abcdef"
, e = Array.from({
length: 32
}, (function() {
return t.substr(Math.floor(16 * Math.random()), 1)
}
));
return e[14] = "4",
e[19] = t.substr(3 & e[19] | 8, 1),
e[8] = e[13] = e[18] = e[23],
e.join("")
}
003 查看相关报文
抓包发现请求和响应全局加密
004 加解密本地化
尝试使用对应的加解密代码和请求响应数据,尝试进行加解密逆向,发现对正文加解密成功
本次使用vscode+nodejs1.18+crypto-js组件(npm install crypto-js)
005 继续测试发现请求头问题
重发对应的请求,返回报错信息,发现服务器有对请求头中数据进行校验(校验签名),本次项目使用的是请求头中RequestId+timestamp+sign的认证,对应的签名一次有效
继续搜索关键字,打断点调试,可以看到相关信息签名sign主要涉及:data + requestId + timestamp
var e = sessionStorage.getItem("user")
, r = Date.parse(new Date)
, n = JSON.stringify(v(t.data))
, i = p()
, s = a.a.MD5(n + i + r);
t.headers["timestamp"] = r,
t.headers["requestId"] = i,
t.headers["sign"] = s,
t.data = l(n);
006 解决请求头问题
可以利用Galaxy中FactorUtil类下randomString方法生成一个32位随机的requestId,获取当前时间戳timestamp,然后再用MD5加密算法加密(data + requestId + timestamp)生成sign(需要做hex处理,否则前端显示乱码,服务器返回签名问题),在HTTP请求从burp发送到server的时候修改这3个请求头即可。
生成32位的随机requestId:
查看源码发现FactorUtil类下randomString方法可生成随机数
String requestId = FactorUtil.randomString(32);
生成当前时间戳(可百度java获取当前系统时间查找到):
String timestamp = String.valueOf(System.currentTimeMillis());
生成签名(3.1.0版本需要转格式):
String sign = ByteUtil.toHexString(HashUtil.calc((datas+requestId+timestamp).getBytes(),"MD5")); // 新版插件已更新对应的加解密算法
更新数据到请求头中
// 获取请求头数据
Headers headers = request.getHeaders();
// 获取被解密的原始数据并转为String类型
String datas = new String(data);
// 生成随机32位数据
String requestId = FactorUtil.randomString(32);
// 获取当前系统时间戳
String timestamp = String.valueOf(System.currentTimeMillis());
byte[] SignData = (datas + requestId + timestamp).getBytes();
// 使用HashUtil类中md5方法生成签名信息
String sign = ByteUtil.toHexString(HashUtil.calc(SignData, "MD5"));
// 更新请求头信息
headers.put("requestId",requestId);
headers.put("timestamp",timestamp);
headers.put("sign",sign);
// 记录相关信息到插件输出日志中
log.info("\r\nrequestId: "+requestId+"\ttimestamp: "+timestamp+"\tsign: "+sign);
007 尝试明文下的测试
配置相关代码(对应代码参考本文末尾附件处)后,运行插件
使用对应的脚本尝试解密,发现解密成功
明文下尝试repeater也是可以的
对应的日志信息可以在如下位置找到
1.保存的日志位置
2.运行时的日志
参考
参考链接:(Galaxy2.2.8) [工具推荐]前端加解密之Burp插件Galaxy-CSDN博客
感谢博主网址支持: vue_demo,(对应的地址还请不要扫描爆破,仅做js逆向学习使用)
源码及github在: GitHub - 0ctDay/encrypt-decrypt-vuls: 加解密逻辑漏洞靶场
Galaxy学习系列
Burpsuite加解密插件Galaxy使用第一课教程-CSDN博客
Burpsuite加解密插件Galaxy使用第二课教程-CSDN博客
Burpsuite加解密插件Galaxy使用第三课教程-CSDN博客
附件
import org.m2sec.core.utils.*;
import org.m2sec.core.models.*;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
/**
* 内置模版,需要自定义代码文件时查看该文档:https://github.com/outlaws-bai/Galaxy/blob/main/docs/Custom.md
* 按 Ctrl(command) + ` 可查看内置函数
*/
public class Aescbc_vue {
private Logger log;
private static final String ALGORITHM = "AES/CBC/PKCS5Padding";
private static final byte[] secret = "****56789****567".getBytes();
private static final byte[] iv = "****56789****567".getBytes();
private static final Map<String, Object> paramMap = new HashMap<>(Map.of("iv", iv));
private static final String jsonKey = "data";
public Aescbc_vue(Logger log) {
this.log = log;
}
/**
* HTTP请求从客户端到达Burp时被调用。在此处完成请求解密的代码就可以在Burp中看到明文的请求报文。
*
* @param request Request 请求对象
* @return 经过处理后的request对象,返回null代表从当前节点开始流量不再需要处理
*/
public Request hookRequestToBurp(Request request) {
// 获取需要解密的数据
byte[] encryptedData = getData(request.getContent());
// 调用函数解密
byte[] data = decrypt(encryptedData);
// 更新body为已加密的数据
request.setContent(data);
return request;
}
/**
* HTTP请求从Burp将要发送到Server时被调用。在此处完成请求加密的代码就可以将加密后的请求报文发送到Server。
*
* @param request Request 请求对象
* @return 经过处理后的request对象,返回null代表从当前节点开始流量不再需要处理
*/
public Request hookRequestToServer(Request request) {
// 获取被解密的数据
byte[] data = request.getContent();
// 调用函数加密回去
byte[] encryptedData = encrypt(data);
// 将已加密的数据转换为Server可识别的格式
byte[] body = toData(encryptedData);
// 更新body
request.setContent(body);
// 获取请求头数据
Headers headers = request.getHeaders();
// 获取被解密的原始数据并转为String类型
String datas = new String(data);
// 生成随机32位数据
String requestId = FactorUtil.randomString(32);
// 获取当前系统时间戳
String timestamp = String.valueOf(System.currentTimeMillis());
byte[] SignData = (datas + requestId + timestamp).getBytes();
// 使用HashUtil类中md5方法生成签名信息
String sign = ByteUtil.toHexString(HashUtil.calc(SignData, "MD5"));
// 更新请求头信息
headers.put("requestId", requestId);
headers.put("timestamp", timestamp);
headers.put("sign", sign);
// 记录相关信息到插件输出日志中
log.info("\r\nrequestId: " + requestId + "\ttimestamp: " + timestamp + "\tsign: " + sign);
return request;
}
/**
* HTTP请求从Server到达Burp时被调用。在此处完成响应解密的代码就可以在Burp中看到明文的响应报文。
*
* @param response Response 响应对象
* @return 经过处理后的response对象,返回null代表从当前节点开始流量不再需要处理
*/
public Response hookResponseToBurp(Response response) {
// 获取需要解密的数据
byte[] encryptedData = getData(response.getContent());
// 调用函数解密
byte[] data = decrypt(encryptedData);
// 更新body
response.setContent(data);
return response;
}
/**
* HTTP请求从Burp将要发送到Client时被调用。在此处完成响应加密的代码就可以将加密后的响应报文返回给Client。
*
* @param response Response 响应对象
* @return 经过处理后的response对象,返回null代表从当前节点开始流量不再需要处理
*/
public Response hookResponseToClient(Response response) {
// 获取被解密的数据
byte[] data = response.getContent();
// 调用函数加密回去
byte[] encryptedData = encrypt(data);
// 更新body
// 将已加密的数据转换为Server可识别的格式
byte[] body = toData(encryptedData);
// 更新body
response.setContent(body);
return response;
}
public byte[] decrypt(byte[] content) {
return CryptoUtil.aesDecrypt(ALGORITHM, content, secret, paramMap);
}
public byte[] encrypt(byte[] content) {
return CryptoUtil.aesEncrypt(ALGORITHM, content, secret, paramMap);
}
public byte[] getData(byte[] content) {
return CodeUtil.b64decode(new String(content));
}
public byte[] toData(byte[] content) {
return CodeUtil.b64encodeToString(content).getBytes();
}
}