BurpSuite扩展开发入门

引言

以解决一个防重放问题为契机,学习一下简单Burp拓展的开发。

相信在场的测试小伙伴都遇到过这个😉

所以我们的需求是:在Repeater和Intruder范围发起HTTP请求时,如果X-GW-NONCE头存在则自动替换值为新随机uuid。

准备工作

软件

  • IntelliJ IDEA 或 eclipse
  • BurpSuite

HelloWorld项目

导出API包

长这样

IDEA新建空JAVA项目

把burp包(文件夹)直接复制到项目的src目录下

新建BurpExtender类,并实现IBurpExtender接口,这是官方规定的:

所有扩展都必须实现这个接口。在包 burp 中,实现类名必须为BurpExtender的公共类,并且必须提供一个默认的(公共的,无参数的)构造函数。

填入以下示例代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
package burp;

import java.io.PrintWriter;

public class BurpExtender implements IBurpExtender
{
@Override
public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks)
{
// 设置插件的名称
callbacks.setExtensionName("Hello world extension");

// 获取burp提供的标准输出流和错误输出流
PrintWriter stdout = new PrintWriter(callbacks.getStdout(), true);
PrintWriter stderr = new PrintWriter(callbacks.getStderr(), true);

// 打印到标准输出流
stdout.println("Hello output");

// 打印到错误输出流
stderr.println("Hello errors");

// 写一个报警信息到burp的报警面板
callbacks.issueAlert("Hello alerts");

// 抛出一个异常,将会在错误输出流中显示
throw new RuntimeException("Hello exceptions");
}
}

打包方法

这个hello world项目写完之后需要打包才能使用

文件 - 项目结构 - 项目设置 - 工件 - “+” - JAR - 具有来自依赖项的模块 - 主类中输入 “BurpExtender” - 确定就好了

然后点击构建-构建工件-选择构建

在项目文件夹out/artifacts下就能找到构建好的jar包,就可以导入Burp了

在output和errors面板可以看到加载结果

功能实现

APIs

仅介绍能解决引言问题的几个API,也就是修改HTTP请求包内容所需的API

其他API可以参考官方文档BurpSuite Extender APIs

本次用到的主要API是IHttpListener,它只有一个processHttpMessage方法,注册好此API事件监听器后,每次即将发送请求或收到响应时会调用这个方法,就可以对报文进行增删查改操作了

三个入参:

  • toolFlag 信息来源标志位 对应来源属性可以在IBurpExtenderCallbacks找到
  • messageIsRequest true表示是一个请求 false为响应
  • messageInfo HTTP报文信息

还有一个IExtensionHelpers帮助我们解析HTTP报文字节,使用见代码部分。

实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
package burp;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.UUID;

import static burp.IBurpExtenderCallbacks.TOOL_INTRUDER;
import static burp.IBurpExtenderCallbacks.TOOL_REPEATER;

public class BurpExtender implements IBurpExtender,IHttpListener{
public IExtensionHelpers helpers;
@Override
public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
// 设置插件的名称
callbacks.setExtensionName("Hello world extension");
//获取处理http报文的helper
helpers = callbacks.getHelpers();
//注册事件监听器
callbacks.registerHttpListener(this);
}

@Override
public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) {
//判断范围,在repeater或intruder才处理
if(toolFlag==TOOL_REPEATER||toolFlag==TOOL_INTRUDER){
//如果发送请求
if (messageIsRequest){
//获取请求信息
byte[] rawRequest=messageInfo.getRequest();
IRequestInfo requestInfo = helpers.analyzeRequest(rawRequest);
//获取headers
List<String> headers = requestInfo.getHeaders();
//如果以X-GW-NONCE开头则删除这项
//标记是否有Nonce
boolean hasNonce=false;
//遍历删除X-GW-NONCE头部
Iterator<String> iterator=headers.iterator();
while (iterator.hasNext()){
String header=iterator.next();
if (header.startsWith("X-GW-NONCE")){
iterator.remove();
hasNonce=true;
}
}
//重新加上随机uuid的X-GW-NONCE头部
if(hasNonce)
headers.add("X-GW-NONCE: "+String.valueOf(UUID.randomUUID()));
//获取body
int len = rawRequest.length;
int bodyOffset = requestInfo.getBodyOffset(); //body偏移量
byte[] rawNewBody = Arrays.copyOfRange(rawRequest, bodyOffset, len);
//合成新请求信息
byte[] modifiedRequest=helpers.buildHttpMessage(headers, rawNewBody);
//放置修改好的请求
messageInfo.setRequest(modifiedRequest);
}
}
}
}

参考文档

Burpsuit插件开发(Java篇)

burp-api-drops

BurpSuite Extender APIs