新版Burpsuite加解密插件开发基础

目前项目测试中总会遇到很多的加解密相关的请求和响应,由于早期的加解密插件不太好用,且目前加解密请求响应越来越普遍,因此就尝试自己写一个简单的burp加解密插件

环境基础

本次编写用到软件及平台有:Windows10+burpsuite_community24.5.3+IntelliJ IDEA Community Edition 2023.2.3+Visual Studio Code+nodejs1.18

本次涉及相关参考插件:xia.SQL.3.3.jdk16.jar+Galaxy加解密插件

IDEA配置

01 新建maven项目

02 maven配置pom.xml

<dependencies>

<!-- https://mvnrepository.com/artifact/net.portswigger.burp.extensions/montoya-api -->

<dependency>

<groupId>net.portswigger.burp.extensions</groupId>

<artifactId>montoya-api</artifactId>

<version>2023.12.1</version>

</dependency>

<!-- https://mvnrepository.com/artifact/com.alibaba.fastjson2/fastjson2 -->

<dependency>

<groupId>com.alibaba.fastjson2</groupId>

<artifactId>fastjson2</artifactId>

<version>2.0.51</version>

</dependency>

</dependencies>

新增对应的文件夹,并新增对应的初始化调用类:BurpExtender类

测试问题

测试发现的问题:对应的程序,默认请求全局加密,密钥放在请求头sign中,密钥和当前时间组合后做RSA加密,响应为json报文部分加密,具体如下

默认解决方法

测试发现对应的加解密使用了通用型加解密算法:AES/ECB/PKCS5Padding和RSA算法

具体实现脚本可以在对应的js脚本中找到

想要运行对应的js代码,需要使用Visual Studio Code和NodeJS进行联动才能运行指定的js代码

加解密算法

依据对应的加解密算法,尝试在网上找到对应的Java实现代码

AES-ECB算法

public class Encryptor {
    private static final String AES_ECB = "AES/ECB/PKCS5Padding";
    private static final Integer IV_LENGTH = 16;
    public static SecretKeySpec getSecretKeySpec(String key) {
        SecretKeySpec secretKeySpec = new SecretKeySpec(getBytes(key), "AES");
        return secretKeySpec;
    }
    public static byte[] getBytes(String str) {
        if (isEmpty(str)) {
            return null;
        }
        try {
            return str.getBytes(StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    public static boolean isEmpty(Object str) {
        return null == str || "".equals(str);
    }

    public static String getIV() {
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < IV_LENGTH.intValue(); i++) {
 int number = random.nextInt("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".length());
            sb.append("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(number));
        }
        return sb.toString();
    }
    public static String encrypt(String text, String key) {
        if (isEmpty(text) || isEmpty(key)) {
            return null;
        }
        try {
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            SecretKeySpec secretKeySpec = getSecretKeySpec(key);
            cipher.init(1, secretKeySpec);
            byte[] encryptedBytes = cipher.doFinal(getBytes(text));
            return Base64.getEncoder().encodeToString(encryptedBytes);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    public static String decrypt(String text, String key) {
        if (isEmpty(text) || isEmpty(key)) {
            return null;
        }
        byte[] textBytes = Base64.getDecoder().decode(text);
        try {
            Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
            SecretKeySpec secretKeySpec = getSecretKeySpec(key);
            cipher.init(2, secretKeySpec);
            byte[] decryptedBytes = cipher.doFinal(textBytes);
            return new String(decryptedBytes, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
    public static void main(String[] args) {
        String key = "8****a";
        String test = "7***********=";
        String dff = decrypt(test, key);
        System.out.println(dff);
    }
}

RSA签名算法

public class RSACrypto {
    public static PublicKey getPublicKeyFromString(String publicKeyStr) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(publicKeyStr);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance("RSA");
        return keyFactory.generatePublic(keySpec);
    }
    public static String encryptWithPublicKey(String publicKeyStr, String data) throws Exception {
        PublicKey publicKey = getPublicKeyFromString(publicKeyStr);
        Cipher cipher = Cipher.getInstance("RSA");
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encryptedBytes = cipher.doFinal(data.getBytes());
        return Base64.getEncoder().encodeToString(encryptedBytes);
    }
    public static void main(String[] args) {
        try {
            // 示例公钥,实际使用时需要替换为有效的公钥
            String publicKeyStr = "M************B";
            // 待加密的数据
            String data_time = String.valueOf(System.currentTimeMillis());
            String data = "b****t0_"+data_time;
            System.out.println("Date: " + data_time);
            String encryptedData = encryptWithPublicKey(publicKeyStr, data);
            System.out.println("Encrypted Data: " + encryptedData);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

基于对应的算法,尝试开发burpsuite插件以便于测试

burp插件开发流程

开发需求

主要涉及如下信息:

burpsuite插件,需要有新的可输入内容的页面,在对应的页面中可以输入host白名单,输入aes_ecb对应的密钥

开发代码

拟定最终效果页面如下:

需要有对应的key输入位置,和设置白名单位置

初始化代码

初始化代码中使用本次涉及的三个类:burp使用三处核心类:registerRequestHandler,registerResponseHandler,registerHttpHandler

Package burp.api.montoya.proxy

registerRequestHandler,registerResponseHandler

Package burp.api.montoya.http

registerHttpHandler

montoyaApi.proxy().registerRequestHandler(new MyProxyRequestHandler(montoyaApi));

montoyaApi.proxy().registerResponseHandler(new MyProxyResponseHandler(montoyaApi));

montoyaApi.http().registerHttpHandler(new MyHttpHandler(montoyaApi));

设置对应的页面显示

在初始化代码中可以配置对应的页面及相关设置

对应的三个类使用了各自的构造方法

MyProxyRequestHandler

MyProxyRequestHandler类对应的位置为浏览器到proxy和proxy到http之间

配置初始数据点

如果修改对应的请求数据,则会改变burpsuite-proxy-history对应的原始请求数据,一般不需要在这边对请求数据进行修改,但是可以在handleRequestReceived做一些初始化操作,如获取key数据,获取请求的ID值等操作,Proxy_Req_In

请求解密点

handleRequestToBeSent对应burpsuite-proxy-history-edited请求的修改页面,该处可以修改相关加密数据为对应的明文数据,Proxy_Req_Out(解密)

MyHttpHandler

MyHttpHandler类对应的位置为burp到服务器和服务器返回的响应之间

包含两个方法handleHttpRequestToBeSent(发往服务器)类和handleHttpResponseReceived(服务器返回响应)类

发往服务器请求加密点

handleHttpRequestToBeSent类可以发送原始数据到服务器中,默认需要使用修改后的请求数据进行加密后发送到服务器(如果直接使用原始数据,会导致在repeater中无法使用),Http_Req_Out

服务器返回响应解密点(该处需要记录原始响应到公共池中

handleHttpResponseReceived类,如果对对应的响应进行修改,显示到burp就是对应的原始响应,该处需要记录原始响应到公共池中,用于最终返回到前端或浏览器,Http_Resp_In

MyProxyResponseHandler类

MyProxyResponseHandler类对应的位置http响应和浏览器之间

包含两个方法handleResponseReceived类和handleResponseToBeSent类

handleResponseReceived类(一般不用修改),Proxy_Resp_In

返回前端原始响应数据

handleResponseToBeSent类(如果在http类中修改了原始响应)该类就需要换成对应的原始响应了,Proxy_Resp_Out

对应burpsuite位置

01 Proxy-HTTP history

02 Repeater对应的为Http相关配置信息

三大类对应流程图

burp插件开发对应的流程图示:

感谢:

目前比较完善的burpsuite加解密插件Galaxy:GitHub - outlaws-bai/Galaxy: Burp插件,自动解密被加密的报文,让你像测试明文一样简单。A Burp plugin that automatically decrypts encrypted messages, making it as simple as testing plaintext.

Galaxy插件示例:GitHub - outlaws-bai/GalaxyDemo: HTTP报文二次加密的具体实现,用于测试 https://github.com/outlaws-bai/Galaxy 中的示例

Galaxy插件使用学习(对应版本2.2.8):[工具推荐]前端加解密之Burp插件Galaxy_burp自动解密数据-CSDN博客

本次使用的代码相关:xia SQL(瞎注) burp插件(www.nmd5.com)GitHub - smxiazi/xia_sql: xia SQL (瞎注) burp 插件 ,在每个参数后面填加一个单引号,两个单引号,一个简单的判断注入小插件。

AES加解密代码:Java实现AES加密和解密方式完整示例_java_脚本之家

RSA加解密代码:通过Java实现RSA加密与验证的方法详解_java_脚本之家

  • 26
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值