实现效果
自动修改请求数据包中的header、body和param,并修改响应包结果,以及单独发送新的请求。
涉及接口:
- IHttpListener
实现代码
创建项目过程省略,直接从代码入手,使用旧版API开发。
package burp;
import java.util.Arrays;
import java.util.List;
public class BurpExtender implements IBurpExtender, IHttpListener {
// 回调对象
private IBurpExtenderCallbacks callbacks;
// 辅助类,一般用于辅助分析数据包结构
private IExtensionHelpers helpers;
// 实现 IBurpExtender 接口函数
@Override
public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
// 设置插件名字
callbacks.setExtensionName("Demo");
// callbacks到处都要用,搞成类变量
this.callbacks = callbacks;
// 辅助类,一般用于辅助分析数据包结构,类变量方便其他函数调用
helpers = callbacks.getHelpers();
// 注册 HttpListener ,必须要注册了burp有新消息才会通知你
callbacks.registerHttpListener(this);
}
// 实现 IHttpListener 接口函数
@Override
public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) {
// 判断是哪个地方监听到的请求,此处为 Proxy 监听到的请求
if (toolFlag == IBurpExtenderCallbacks.TOOL_PROXY) {
// 判断是请求还是响应,True 就是请求数据包, False就是响应数据包
if (messageIsRequest) {
// 使用helper辅助分析请求
IRequestInfo requestInfo = helpers.analyzeRequest(messageInfo.getRequest());
// 获取header
List<String> headers = requestInfo.getHeaders();
// 获取param(包含了body中的)
List<IParameter> parameters = requestInfo.getParameters();
// 获取post raw body
byte[] raw_body = Arrays.copyOfRange(messageInfo.getRequest(), requestInfo.getBodyOffset(), messageInfo.getRequest().length);
// 更新header中的UA
for (String header: headers) {
if (header.contains("User-Agent")){
int index = headers.indexOf(header);
headers.set(index, "User-Agent: TEST UA");
}
}
// 增加一条header
headers.add("Add-Header: TEST ADD HEADER");
// 更新整体header内容到请求体中
byte[] newReq = helpers.buildHttpMessage(headers, raw_body);
// 更新param: a=xxx
IParameter parameter1 = helpers.buildParameter("a", "testUrlParam", IParameter.PARAM_URL);
// 第一个参数为请求数据包,由于上方更新了请求数据包,所以这里用了更新后的newReq,具体可以下断点分析
// 如果没有更新请求题,就用原始的 messageInfo.getRequest() 即可
// helpers.updateParameter(messageInfo.getRequest(), parameter1); // 从原始数据包更新
newReq = helpers.updateParameter(newReq, parameter1);
// 增加一个参数到body
IParameter parameter2 = helpers.buildParameter("testParam", "testValue", IParameter.PARAM_BODY);
newReq = helpers.addParameter(newReq, parameter2);
// 在当前请求基础上进行更新
messageInfo.setRequest(newReq);
// 单独发送一次篡改后的请求,增加Cookie特征
newReq = helpers.addParameter(newReq, helpers.buildParameter("make", "request", IParameter.PARAM_COOKIE));
IHttpRequestResponse response = callbacks.makeHttpRequest(messageInfo.getHttpService(), newReq);
// callbacks.makeHttpRequest(messageInfo.getHttpService(), messageInfo.getRequest()); // 发送一个原始请求
callbacks.printOutput(new String(response.getResponse()));
} else {
// 响应数据包
// 使用helper辅助分析请求
IResponseInfo requestInfo = helpers.analyzeResponse(messageInfo.getResponse());
byte[] response = helpers.buildHttpMessage(requestInfo.getHeaders(), "modify response".getBytes());
// 篡改
messageInfo.setResponse(response);
}
}
}
}
实现测试
实际发送请求
curl -x http://127.0.0.1:8080 'http://127.0.0.1/?a=bbbb' -v
* Trying 127.0.0.1:8080...
* Connected to 127.0.0.1 (127.0.0.1) port 8080
> GET http://127.0.0.1/?a=bbbb HTTP/1.1
> Host: 127.0.0.1
> User-Agent: curl/8.4.0
> Accept: */*
> Proxy-Connection: Keep-Alive
>
nc接收到的请求,可见已经被替换
GET /?a=testUrlParam HTTP/1.1
Host: 127.0.0.1
User-Agent: TEST UA
Accept: */*
Connection: close
Add-Header: TEST ADD HEADER
Content-Type: application/x-www-form-urlencoded
Content-Length: 19
testParam=testValue
得到的被替换响应内容
HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/3.7.9
Date: Wed, 18 Sep 2024 11:03:04 GMT
Content-type: text/html
Content-Length: 15
Last-Modified: Wed, 18 Sep 2024 10:44:55 GMT
modify response
需要注意的是,通过这种方法修改的请求响应,并不会在burp中显示数据包被替换过,如下:
不存在如下的显示
刚才除了直接篡改原始请求,还有通过makeHttpRequest
发起新的请求,可在logger++
中查看到该请求。
扩展总结
- 获取的header包括了请求和响应的第一行
- 可通过callbacks提供的helper来辅助处理数据包,减少工作量
- messageInfo除了获取、设置请求响应外,还可以控制Comment和高亮显示等。