Skip to content

Commit fa9704f

Browse files
author
githubnull
committed
feat(burp): 批量选择HTTP请求时自动过滤二进制报文
- 新增FilterResult类封装过滤结果和统计信息 - 批量发送时对每个请求单独检测二进制内容 - 菜单项显示可扫描统计 [x/y 可扫描] - 记录被过滤的二进制请求URL和原因到日志 - 只有纯文本请求才会被发送到SQLMap后端 两端(Montoya API/Legacy API)同步实现
1 parent b8ffa5d commit fa9704f

2 files changed

Lines changed: 220 additions & 52 deletions

File tree

src/burpEx/legacy-api/src/main/java/com/sqlmapwebui/burp/BurpExtender.java

Lines changed: 112 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@
2222
* 5. 提交会话Header
2323
* 6. 提交Header规则
2424
*
25+
* 批量选择时自动过滤二进制内容的报文,只有纯文本请求才会被发送
26+
*
2527
* @author SQLMap WebUI Team
2628
* @version 1.0.0
2729
*/
@@ -42,6 +44,47 @@ public class BurpExtender implements IBurpExtender, IContextMenuFactory, ITab {
4244
private static final String EXTENSION_NAME = "SQLMap WebUI";
4345
private static final String EXTENSION_VERSION = "1.0.0";
4446

47+
/**
48+
* 过滤结果类 - 存储过滤后的纯文本请求和过滤统计
49+
*/
50+
private static class FilterResult {
51+
final List<IHttpRequestResponse> textMessages;
52+
final List<IHttpRequestResponse> binaryMessages;
53+
54+
FilterResult(List<IHttpRequestResponse> textMessages, List<IHttpRequestResponse> binaryMessages) {
55+
this.textMessages = textMessages;
56+
this.binaryMessages = binaryMessages;
57+
}
58+
59+
int totalCount() {
60+
return textMessages.size() + binaryMessages.size();
61+
}
62+
63+
int textCount() {
64+
return textMessages.size();
65+
}
66+
67+
int binaryCount() {
68+
return binaryMessages.size();
69+
}
70+
71+
boolean hasTextMessages() {
72+
return !textMessages.isEmpty();
73+
}
74+
75+
boolean allBinary() {
76+
return textMessages.isEmpty() && !binaryMessages.isEmpty();
77+
}
78+
79+
String getMenuSuffix() {
80+
if (totalCount() == 1) {
81+
return binaryMessages.isEmpty() ? "" : " (二进制报文)";
82+
} else {
83+
return String.format(" [%d/%d 可扫描]", textCount(), totalCount());
84+
}
85+
}
86+
}
87+
4588
@Override
4689
public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
4790
this.callbacks = callbacks;
@@ -118,68 +161,68 @@ public List<JMenuItem> createMenuItems(IContextMenuInvocation invocation) {
118161
return menuItems;
119162
}
120163

121-
// 检测请求是否为二进制内容
122-
IHttpRequestResponse firstMessage = selectedMessages[0];
123-
BinaryContentDetector.DetectionResult detectionResult =
124-
BinaryContentDetector.detect(firstMessage, helpers);
125-
boolean isBinary = detectionResult.isBinary();
126-
String binarySuffix = isBinary ? " (二进制报文)" : "";
164+
// 过滤二进制请求
165+
FilterResult filterResult = filterBinaryRequests(selectedMessages);
166+
String menuSuffix = filterResult.getMenuSuffix();
127167

128168
// 使用默认配置发送
129-
JMenuItem sendWithDefault = new JMenuItem("Send to SQLMap WebUI" + binarySuffix);
130-
if (isBinary) {
169+
JMenuItem sendWithDefault = new JMenuItem("Send to SQLMap WebUI" + menuSuffix);
170+
if (filterResult.allBinary()) {
131171
sendWithDefault.setEnabled(false);
132-
sendWithDefault.setToolTipText("二进制报文无法发起扫描任务: " + detectionResult.getReason());
172+
sendWithDefault.setToolTipText("所有选中的报文都是二进制格式,无法发起扫描任务");
133173
} else {
134174
sendWithDefault.addActionListener(e -> {
135-
for (IHttpRequestResponse message : selectedMessages) {
136-
sendRequestToBackend(message, configManager.getDefaultConfig());
137-
}
175+
sendFilteredRequests(filterResult, configManager.getDefaultConfig());
138176
});
139177
}
140178
menuItems.add(sendWithDefault);
141179

142180
// 选择配置发送
143-
JMenuItem sendWithOptions = new JMenuItem("Send to SQLMap WebUI (选择配置)..." + binarySuffix);
144-
if (isBinary) {
181+
JMenuItem sendWithOptions = new JMenuItem("Send to SQLMap WebUI (选择配置)..." + menuSuffix);
182+
if (filterResult.allBinary()) {
145183
sendWithOptions.setEnabled(false);
146-
sendWithOptions.setToolTipText("二进制报文无法发起扫描任务: " + detectionResult.getReason());
184+
sendWithOptions.setToolTipText("所有选中的报文都是二进制格式,无法发起扫描任务");
147185
} else {
148186
sendWithOptions.addActionListener(e -> {
149-
ConfigSelectionDialog dialog = new ConfigSelectionDialog(
150-
callbacks, apiClient, configManager, uiTab);
151-
dialog.show(selectedMessages[0]);
187+
if (filterResult.hasTextMessages()) {
188+
ConfigSelectionDialog dialog = new ConfigSelectionDialog(
189+
callbacks, apiClient, configManager, uiTab);
190+
dialog.show(filterResult.textMessages.get(0));
191+
}
152192
});
153193
}
154194
menuItems.add(sendWithOptions);
155195

156196
// 标记注入点并扫描
157-
JMenuItem markInjectionPoints = new JMenuItem("标记注入点并扫描 (*)" + binarySuffix);
158-
if (isBinary) {
197+
JMenuItem markInjectionPoints = new JMenuItem("标记注入点并扫描 (*)" +
198+
(filterResult.allBinary() ? " (二进制报文)" : ""));
199+
if (filterResult.allBinary()) {
159200
markInjectionPoints.setEnabled(false);
160-
markInjectionPoints.setToolTipText("二进制报文无法发起扫描任务: " + detectionResult.getReason());
201+
markInjectionPoints.setToolTipText("所有选中的报文都是二进制格式,无法发起扫描任务");
161202
} else {
162203
markInjectionPoints.addActionListener(e -> {
163-
InjectionPointDialog dialog = new InjectionPointDialog(
164-
callbacks, apiClient, configManager, uiTab);
165-
dialog.show(selectedMessages[0]);
204+
if (filterResult.hasTextMessages()) {
205+
InjectionPointDialog dialog = new InjectionPointDialog(
206+
callbacks, apiClient, configManager, uiTab);
207+
dialog.show(filterResult.textMessages.get(0));
208+
}
166209
});
167210
}
168211
menuItems.add(markInjectionPoints);
169212

170213
// 提交会话Header 和 Header规则 - 仅在选中单条请求时显示
171-
if (selectedMessages.length == 1) {
214+
if (selectedMessages.length == 1 && filterResult.hasTextMessages()) {
172215
JMenuItem submitSessionHeaders = new JMenuItem("提交会话Header");
173216
submitSessionHeaders.addActionListener(e -> {
174217
SessionHeaderDialog dialog = new SessionHeaderDialog(callbacks, apiClient, uiTab);
175-
dialog.show(selectedMessages[0]);
218+
dialog.show(filterResult.textMessages.get(0));
176219
});
177220
menuItems.add(submitSessionHeaders);
178221

179222
JMenuItem submitHeaderRule = new JMenuItem("提交Header规则");
180223
submitHeaderRule.addActionListener(e -> {
181224
HeaderRuleDialog dialog = new HeaderRuleDialog(callbacks, apiClient, uiTab);
182-
dialog.show(selectedMessages[0]);
225+
dialog.show(filterResult.textMessages.get(0));
183226
});
184227
menuItems.add(submitHeaderRule);
185228
}
@@ -188,6 +231,48 @@ public List<JMenuItem> createMenuItems(IContextMenuInvocation invocation) {
188231
return menuItems;
189232
}
190233

234+
/**
235+
* 过滤二进制请求,返回纯文本请求列表和统计信息
236+
*/
237+
private FilterResult filterBinaryRequests(IHttpRequestResponse[] messages) {
238+
List<IHttpRequestResponse> textMessages = new ArrayList<>();
239+
List<IHttpRequestResponse> binaryMessages = new ArrayList<>();
240+
241+
for (IHttpRequestResponse message : messages) {
242+
if (BinaryContentDetector.isTextRequest(message, helpers)) {
243+
textMessages.add(message);
244+
} else {
245+
binaryMessages.add(message);
246+
}
247+
}
248+
249+
return new FilterResult(textMessages, binaryMessages);
250+
}
251+
252+
/**
253+
* 发送过滤后的纯文本请求,并记录被过滤的二进制请求日志
254+
*/
255+
private void sendFilteredRequests(FilterResult filterResult, ScanConfig config) {
256+
// 记录过滤统计
257+
if (filterResult.binaryCount() > 0) {
258+
uiTab.appendLog(String.format("[*] 过滤统计: 共选中 %d 个请求,%d 个纯文本可扫描,%d 个二进制已过滤",
259+
filterResult.totalCount(), filterResult.textCount(), filterResult.binaryCount()));
260+
261+
// 记录被过滤的二进制请求URL
262+
for (IHttpRequestResponse binaryMsg : filterResult.binaryMessages) {
263+
IRequestInfo reqInfo = helpers.analyzeRequest(binaryMsg);
264+
String url = reqInfo.getUrl().toString();
265+
BinaryContentDetector.DetectionResult detection = BinaryContentDetector.detect(binaryMsg, helpers);
266+
uiTab.appendLog(String.format(" [跳过] %s (原因: %s)", url, detection.getReason()));
267+
}
268+
}
269+
270+
// 发送纯文本请求
271+
for (IHttpRequestResponse message : filterResult.textMessages) {
272+
sendRequestToBackend(message, config);
273+
}
274+
}
275+
191276
/**
192277
* 发送请求到后端 - 使用默认配置发送
193278
*/

0 commit comments

Comments
 (0)