平常每次出一个漏洞都会出一个burp被动扫描的插件 所以可以提前做好一个模板
burp插件开发注意事项
- 所有的burp插件都必须实现IBurpExtender这个接口
- 实现类的包名称必须是burp
- 实现类的名称必须是BurpExtender
- 实现类比较是public的
- 实现类必须有默认构造函数(public,无参),如果没有定义构造函数就是默认构造函数
maven
<dependency>
<groupId>net.portswigger.burp.extender</groupId>
<artifactId>burp-extender-api</artifactId>
<version>LATEST</version>
</dependency>
打包
模板
UI
设置一个大众化的UI
package burp;
import java.awt.Component;
import java.io.PrintWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
//import java.util.Random;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
//IMessageEditor使用IMessageEditorController接口获取当前显示的消息的详细信息
//扩展可以实现这个IScannerCheck接口,然后调用 IBurpExtenderCallbacks.registerScannerCheck()来注册一个自定义的 Scanner 检查。
//Itab这个接口用于使用 IBurpExtenderCallbacks.addSuiteTab ()之类的方法为 Burp 提供将添加到 Burp 的 UI 中的自定义选项卡的详细信息。
public class BurpExtender extends AbstractTableModel implements IBurpExtender, IScannerCheck, ITab, IMessageEditorController {
//IBurpExtenderCallbacks接口类是IBurpExtender接口的实 现类与Burp其他各个组件(Scanner、Intruder、Spider......)、各个通信对象 (HttpRequestResponse、HttpService、SessionHandlingAction)之间的连接
private IBurpExtenderCallbacks callbacks;
//IExtensionHelpers接口包含许多辅助方法,扩展可以使用这些方法来协助 Burp 扩展出现的各种常见任务
//比如向 HTTP 请求添加新参数,分析 HTTP 请求
private IExtensionHelpers helpers;
//分隔面板,SplitPane用于分隔两个(只能两个)组件,分割request和response
private JSplitPane splitPane;
//IMessageEditor用于为扩展提供 Burp 的 HTTP 消息编辑器的实例,以便扩展在其自己的 UI 中使用
private IMessageEditor requestViewer;
private IMessageEditor responseViewer;
private final List<LogEntry> log = new ArrayList<>();
//IHttpRequestResponse此接口用于检索和更新有关 HTTP 消息的详细信息。
private IHttpRequestResponse currentlyDisplayedItem;
private String ExtenderName = "SpringCore";
private PrintWriter stdout;
//此方法将在扩展加载后被调用,它注册了一个 IBurpExtenderCallbacks 接口的实例, IBurpExtenderCallbacks 接口提供了许多在开发插件过程中常用的一些操作。
@Override
public void registerExtenderCallbacks(final IBurpExtenderCallbacks callbacks) {
//获取burp提供的标准输出流
this.stdout = new PrintWriter(callbacks.getStdout(), true);
//打印到标准输出流
this.stdout.println(this.ExtenderName);
//保留对callbacks的引用
this.callbacks = callbacks;
//此方法用于获取IExtensionHelpers对象,扩展程序可以使用该对象执行许多有用的任务。
this.helpers = callbacks.getHelpers();
//设置插件的名称
callbacks.setExtensionName(this.ExtenderName);
//调用 IBurpExtenderCallbacks.registerScannerCheck()来注册一个自定义的 Scanner 检查
callbacks.registerScannerCheck(this);
//创建一个Swing线程用于我们的burp的UI
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
BurpExtender.this.splitPane = new JSplitPane(0);
BurpExtender.Table logTable = new BurpExtender.Table(BurpExtender.this);
//创建一个滚动条
JScrollPane scrollPane = new JScrollPane(logTable);
//设置滚动条位置左侧或上方
BurpExtender.this.splitPane.setLeftComponent(scrollPane);
JTabbedPane tabs = new JTabbedPane();
//此方法用于创建 Burp 的 HTTP 消息编辑器的新实例,以便扩展在其自己的 UI 中使用。
BurpExtender.this.requestViewer = callbacks.createMessageEditor(BurpExtender.this, false);
BurpExtender.this.responseViewer = callbacks.createMessageEditor(BurpExtender.this, false);
tabs.addTab("Request", BurpExtender.this.requestViewer.getComponent());
tabs.addTab("Response", BurpExtender.this.responseViewer.getComponent());
//将组件设置在分隔线的右侧或下方
BurpExtender.this.splitPane.setRightComponent(tabs);
//customizeUiComponent方法用于自定义符合 Burp 的 UI 风格的 UI 组件,包括字体大小、颜色、表格行距等。
callbacks.customizeUiComponent(BurpExtender.this.splitPane);
callbacks.customizeUiComponent(logTable);
callbacks.customizeUiComponent(scrollPane);
callbacks.customizeUiComponent(tabs);
//addSuiteTab方法用于将自定义选项卡添加到 Burp Suite 主窗口。
callbacks.addSuiteTab(BurpExtender.this);
}
});
}
//设置我们的被动扫描
@Override
public List<IScanIssue> doPassiveScan(IHttpRequestResponse baseRequestResponse) {
//等会要添加被动扫描代码
return null;
}
//设置我们的主动扫描
@Override
public List<IScanIssue> doActiveScan(IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) {
return null;
}
//当报告同一URL有多个问题时,将调用此方法
//漏洞去重函数,可以根据自己的需求,根据不同的参数来判断是否重复,比如URL、漏洞名称等
@Override
public int consolidateDuplicateIssues(IScanIssue existingIssue, IScanIssue newIssue) {
/**
* if (existingIssue.getIssueName().equals(newIssue.getIssueName()))
* return -1;
* else return 0;
*/
return 0;
}
//JTable使用此方法来确定它应该显示多少行
@Override
public int getRowCount() {
return this.log.size();
}
//JTable使用此方法来确定默认情况下它应该创建和显示多少列
@Override
public int getColumnCount() {
return 3;
}
//返回列的默认名称
@Override
public String getColumnName(int columnIndex) {
switch (columnIndex) {
case 0:
return "Vuln";
case 1:
return "URL";
case 2:
return "Position";
}
return "";
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return String.class;
}
//返回值
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
LogEntry logEntry = this.log.get(rowIndex);
switch (columnIndex) {
case 0:
return "SpringCoreRCE";
case 1:
return logEntry.url.toString();
case 2:
return logEntry.position;
}
return "";
}
//设置Tab标签名称
@Override
public String getTabCaption() {
return "YanMu";
}
//设置Tab标签的内容
@Override
public Component getUiComponent() {
return this.splitPane;
}
//返回相关request信息
@Override
public byte[] getRequest() {
return this.currentlyDisplayedItem.getRequest();
}
//返回相关response信息
@Override
public byte[] getResponse() {
return this.currentlyDisplayedItem.getResponse();
}
//返回相关HttpService信息
@Override
public IHttpService getHttpService() {
return this.currentlyDisplayedItem.getHttpService();
}
private class Table extends JTable {
public Table(TableModel tableModel) {
super(tableModel);
}
//更新表格
@Override
public void changeSelection(int row, int col, boolean toggle, boolean extend) {
//返回此列表中指定位置的元素
BurpExtender.LogEntry logEntry = BurpExtender.this.log.get(row);
BurpExtender.this.requestViewer.setMessage(logEntry.requestResponse.getRequest(), true);
BurpExtender.this.responseViewer.setMessage(logEntry.requestResponse.getResponse(), false);
BurpExtender.this.currentlyDisplayedItem = logEntry.requestResponse;
super.changeSelection(row, col, toggle, extend);
}
}
//检测变化
private static class LogEntry {
final int tool;
final IHttpRequestResponse requestResponse;
final URL url;
final String position;
LogEntry(int tool, IHttpRequestResponse requestResponse, URL url, String position) {
this.tool = tool;
this.requestResponse = requestResponse;
this.url = url;
this.position = position;
}
}
}
DNS
被动扫描DNSlog的出场率一直很高
burp自带的DNSlog
//与dnslog平台进行交互
IBurpCollaboratorClientContext context= this.callbacks.createBurpCollaboratorClientContext();
// 一个burp提供的dnslog平台
String dnslog = context.generatePayload(true);
List<IBurpCollaboratorInteraction> dnsres = new ArrayList<>();
this.stdout.println(dnslog);
//替换以后String.format(),发送请求
IHttpRequestResponse resp = this.callbacks.makeHttpRequest(iHttpService, new_Request);
//休眠2秒
Thread.sleep(2000);
// 返回的是一个dns响应数组
dnsres = context.fetchCollaboratorInteractionsFor(dnslog);
this.stdout.println(dnsres);
if(!dnsres.isEmpty()){
this.stdout.println("found!!!");
// 漏洞存在就更新表格中存在漏洞那一行的数据
//LogEntry logEntry = new LogEntry(url, "finished", "vul!!!", resp);
//log.set(row, logEntry);
// 这个方法是swing中的一个方法,会通知表格更新指定行的数据
//fireTableRowsUpdated(row, row);
break;
}
sprigcore为演示
解释基本都在注释中
package burp;
import java.awt.Component;
import java.io.PrintWriter;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
//import java.util.Random;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTabbedPane;
import javax.swing.JTable;
import javax.swing.SwingUtilities;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableModel;
//IMessageEditor使用IMessageEditorController接口获取当前显示的消息的详细信息
//扩展可以实现这个IScannerCheck接口,然后调用 IBurpExtenderCallbacks.registerScannerCheck()来注册一个自定义的 Scanner 检查。
//Itab这个接口用于使用 IBurpExtenderCallbacks.addSuiteTab ()之类的方法为 Burp 提供将添加到 Burp 的 UI 中的自定义选项卡的详细信息。
public class BurpExtender extends AbstractTableModel implements IBurpExtender, IScannerCheck, ITab, IMessageEditorController {
//IBurpExtenderCallbacks接口类是IBurpExtender接口的实 现类与Burp其他各个组件(Scanner、Intruder、Spider......)、各个通信对象 (HttpRequestResponse、HttpService、SessionHandlingAction)之间的连接
private IBurpExtenderCallbacks callbacks;
//IExtensionHelpers接口包含许多辅助方法,扩展可以使用这些方法来协助 Burp 扩展出现的各种常见任务
//比如向 HTTP 请求添加新参数,分析 HTTP 请求
private IExtensionHelpers helpers;
//分隔面板,SplitPane用于分隔两个(只能两个)组件,分割request和response
private JSplitPane splitPane;
//IMessageEditor用于为扩展提供 Burp 的 HTTP 消息编辑器的实例,以便扩展在其自己的 UI 中使用
private IMessageEditor requestViewer;
private IMessageEditor responseViewer;
private final List<LogEntry> log = new ArrayList<>();
//IHttpRequestResponse此接口用于检索和更新有关 HTTP 消息的详细信息。
private IHttpRequestResponse currentlyDisplayedItem;
private String ExtenderName = "SpringCore";
private PrintWriter stdout;
//此方法将在扩展加载后被调用,它注册了一个 IBurpExtenderCallbacks 接口的实例, IBurpExtenderCallbacks 接口提供了许多在开发插件过程中常用的一些操作。
@Override
public void registerExtenderCallbacks(final IBurpExtenderCallbacks callbacks) {
//获取burp提供的标准输出流
this.stdout = new PrintWriter(callbacks.getStdout(), true);
//打印到标准输出流
this.stdout.println(this.ExtenderName);
//保留对callbacks的引用
this.callbacks = callbacks;
//此方法用于获取IExtensionHelpers对象,扩展程序可以使用该对象执行许多有用的任务。
this.helpers = callbacks.getHelpers();
//设置插件的名称
callbacks.setExtensionName(this.ExtenderName);
//调用 IBurpExtenderCallbacks.registerScannerCheck()来注册一个自定义的 Scanner 检查
callbacks.registerScannerCheck(this);
//创建一个Swing线程用于我们的burp的UI
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
BurpExtender.this.splitPane = new JSplitPane(0);
BurpExtender.Table logTable = new BurpExtender.Table(BurpExtender.this);
//创建一个滚动条
JScrollPane scrollPane = new JScrollPane(logTable);
//设置滚动条位置左侧或上方
BurpExtender.this.splitPane.setLeftComponent(scrollPane);
JTabbedPane tabs = new JTabbedPane();
//此方法用于创建 Burp 的 HTTP 消息编辑器的新实例,以便扩展在其自己的 UI 中使用。
BurpExtender.this.requestViewer = callbacks.createMessageEditor(BurpExtender.this, false);
BurpExtender.this.responseViewer = callbacks.createMessageEditor(BurpExtender.this, false);
tabs.addTab("Request", BurpExtender.this.requestViewer.getComponent());
tabs.addTab("Response", BurpExtender.this.responseViewer.getComponent());
//将组件设置在分隔线的右侧或下方
BurpExtender.this.splitPane.setRightComponent(tabs);
//customizeUiComponent方法用于自定义符合 Burp 的 UI 风格的 UI 组件,包括字体大小、颜色、表格行距等。
callbacks.customizeUiComponent(BurpExtender.this.splitPane);
callbacks.customizeUiComponent(logTable);
callbacks.customizeUiComponent(scrollPane);
callbacks.customizeUiComponent(tabs);
//addSuiteTab方法用于将自定义选项卡添加到 Burp Suite 主窗口。
callbacks.addSuiteTab(BurpExtender.this);
}
});
}
//设置我们的被动扫描
@Override
public List<IScanIssue> doPassiveScan(IHttpRequestResponse baseRequestResponse) {
//IHttpRequestResponse接口用于检索和更新有关 HTTP 消息的详细信息
try {
//此方法可用于分析 HTTP 请求,并获取有关它的各种关键细节。
IRequestInfo analyzeRequest = this.helpers.analyzeRequest(baseRequestResponse);
//此方法用于检索请求消息。
byte[] request = baseRequestResponse.getRequest();
//此方法用于检索此请求/响应的 HTTP 服务。
IHttpService httpService = baseRequestResponse.getHttpService();
boolean flag = false;
URL url = analyzeRequest.getUrl();
String subfix = getSubfix(url.toString());
//设置不扫描的路径
String blacklist = ".js|.png|.jpg|.jpeg|.svg|.gif|.ico|.css";
if (!subfix.isEmpty() && blacklist.contains(subfix)) {
this.stdout.println(subfix + " no check");
return null;
}
String host = httpService.getHost();
int port = httpService.getPort();
String protocol = httpService.getProtocol();
boolean https = false;
if (protocol.equals("https")){
https = true;
}
List<IParameter> paramsList = analyzeRequest.getParameters();
byte getCode = 0;
byte postCode = 1;
this.stdout.println("checking..." + analyzeRequest.getUrl());
//此方法根据提供的详细信息构造一个 IParameter 对象。
IParameter getParam = this.helpers.buildParameter("class.mod%75le.classLoader.DefaultAssertionStatus", "true", getCode);
IParameter postParam = this.helpers.buildParameter("class.mod%75le.classLoader.DefaultAssertionStatus", "true", postCode);
request = this.helpers.updateParameter(request, getParam);
//此方法更新 HTTP 请求中的参数值,如果适当,则更新 Content-Length 标头。
request = this.helpers.updateParameter(request, postParam);
//此方法可用于发出 HTTP 请求并检索其响应。
IHttpRequestResponse newRequest2 = this.callbacks.makeHttpRequest(httpService, request);
//此方法可用于分析 HTTP 响应,并获取关于它的各种关键细节。
IResponseInfo analyzeRequest2 = this.helpers.analyzeResponse(newRequest2.getResponse());
if (analyzeRequest2.getStatusCode() == 200){
flag = true;
}
if (flag) {
//制造
IParameter getParam2 = this.helpers.buildParameter("class.mod%75le.classLoader.DefaultAssertionStatus", createRandomStr(4), getCode);
IParameter postParam2 = this.helpers.buildParameter("class.mod%75le.classLoader.DefaultAssertionStatus", createRandomStr(4), postCode);
//更新请求参数
request = this.helpers.updateParameter(request, getParam2);
request = this.helpers.updateParameter(request, postParam2);
IHttpRequestResponse newRequest3 = this.callbacks.makeHttpRequest(httpService, request);
IResponseInfo analyzeRequest3 = this.helpers.analyzeResponse(newRequest3.getResponse());
if (analyzeRequest3.getStatusCode() == 400){
synchronized (this.log) {
int row = this.log.size();
//漏洞利用成功返回表格数据
this.log.add(new LogEntry(4, this.callbacks.saveBuffersToTempFiles(newRequest3), this.helpers.analyzeRequest(baseRequestResponse).getUrl(), null));
fireTableRowsInserted(row, row);
}
}
}
} catch (Exception e) {
this.stdout.print(e);
return null;
}
return null;
}
//Url解析
public String getSubfix(String url) {
int index = url.indexOf("?");
String tmp = "";
if (index != -1) {
tmp = url.substring(0, index);
} else {
tmp = url;
}
int index2 = tmp.lastIndexOf("/");
String tmp2 = tmp.substring(index2 + 1);
int index3 = tmp2.lastIndexOf(".");
return tmp2.substring(index3 + 1);
}
//设置我们的随机数
public String createRandomStr(int length) {
String str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Random random = new Random();
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < length; i++) {
int number = random.nextInt(62);
stringBuffer.append(str.charAt(number));
}
return stringBuffer.toString();
}
//设置我们的主动扫描
@Override
public List<IScanIssue> doActiveScan(IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint) {
return null;
}
//当报告同一URL有多个问题时,将调用此方法
//漏洞去重函数,可以根据自己的需求,根据不同的参数来判断是否重复,比如URL、漏洞名称等
@Override
public int consolidateDuplicateIssues(IScanIssue existingIssue, IScanIssue newIssue) {
/**
* if (existingIssue.getIssueName().equals(newIssue.getIssueName()))
* return -1;
* else return 0;
*/
return 0;
}
//JTable使用此方法来确定它应该显示多少行
@Override
public int getRowCount() {
return this.log.size();
}
//JTable使用此方法来确定默认情况下它应该创建和显示多少列
@Override
public int getColumnCount() {
return 3;
}
//返回列的默认名称
@Override
public String getColumnName(int columnIndex) {
switch (columnIndex) {
case 0:
return "Vuln";
case 1:
return "URL";
case 2:
return "Position";
}
return "";
}
@Override
public Class<?> getColumnClass(int columnIndex) {
return String.class;
}
//返回值
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
LogEntry logEntry = this.log.get(rowIndex);
switch (columnIndex) {
case 0:
return "SpringCoreRCE";
case 1:
return logEntry.url.toString();
case 2:
return logEntry.position;
}
return "";
}
//设置Tab标签名称
@Override
public String getTabCaption() {
return this.ExtenderName;
}
//设置Tab标签的内容
@Override
public Component getUiComponent() {
return this.splitPane;
}
//返回相关request信息
@Override
public byte[] getRequest() {
return this.currentlyDisplayedItem.getRequest();
}
//返回相关response信息
@Override
public byte[] getResponse() {
return this.currentlyDisplayedItem.getResponse();
}
//返回相关HttpService信息
@Override
public IHttpService getHttpService() {
return this.currentlyDisplayedItem.getHttpService();
}
private class Table extends JTable {
public Table(TableModel tableModel) {
super(tableModel);
}
//更新表格
@Override
public void changeSelection(int row, int col, boolean toggle, boolean extend) {
//返回此列表中指定位置的元素
BurpExtender.LogEntry logEntry = BurpExtender.this.log.get(row);
BurpExtender.this.requestViewer.setMessage(logEntry.requestResponse.getRequest(), true);
BurpExtender.this.responseViewer.setMessage(logEntry.requestResponse.getResponse(), false);
BurpExtender.this.currentlyDisplayedItem = logEntry.requestResponse;
super.changeSelection(row, col, toggle, extend);
}
}
//检测变化
private static class LogEntry {
final int tool;
final IHttpRequestResponse requestResponse;
final URL url;
final String position;
LogEntry(int tool, IHttpRequestResponse requestResponse, URL url, String position) {
this.tool = tool;
this.requestResponse = requestResponse;
this.url = url;
this.position = position;
}
}
}