Skip to content

Commit e58fd3c

Browse files
committed
fix: 修复 HTTP 方法显示和 Host 头重复问题
后端修复: - Task.py: 使用 self.method 而不是根据 body 推断方法 - TaskRequest.py: 添加 method 字段到请求模型 - taskService.py: 传递 method 参数并返回给前端 - 更新所有 API 端点,传递 method 参数到 star_task Burp 插件修复: - legacy-api/BurpExtender.java: 提取 method 并添加到 JSON payload - montoya-api/SqlmapContextMenuProvider.java: 使用 PayloadBuilder 工具类 - montoya-api/util/PayloadBuilder.java: 新增工具类,正确处理 method 字段 - montoya-api/util/LoggerUtil.java: 新增日志工具类 前端修复: - AddTask/index.vue: 添加 method 到请求数据 - task.ts: 添加 method 类型定义,优先使用后端返回的 method - requestFormatter.ts: 修复 Host 头重复问题
1 parent aa0a7f1 commit e58fd3c

13 files changed

Lines changed: 140 additions & 50 deletions

File tree

src/backEnd/api/burpSuiteExApi/admin.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ async def add_task(taskAddRequest: TaskAddRequest, request: Request, current_use
2626
logger.info(f"request.client: {request.client}")
2727
remote_ip = request.client.host
2828
# pdb.set_trace()
29-
res = await taskService.star_task(remote_addr=remote_ip, scanUrl=taskAddRequest.scanUrl, host=taskAddRequest.host, headers=taskAddRequest.headers, body=taskAddRequest.body, options=taskAddRequest.options)
29+
res = await taskService.star_task(remote_addr=remote_ip, scanUrl=taskAddRequest.scanUrl, host=taskAddRequest.host, method=taskAddRequest.method, headers=taskAddRequest.headers, body=taskAddRequest.body, options=taskAddRequest.options)
3030
return res
3131
else:
3232
remote_ip = None

src/backEnd/api/commonApi/webTaskController.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ async def add_task_from_web(
6868
remote_addr=remote_ip,
6969
scanUrl=taskAddRequest.scanUrl,
7070
host=taskAddRequest.host,
71+
method=taskAddRequest.method,
7172
headers=taskAddRequest.headers,
7273
body=taskAddRequest.body,
7374
options=taskAddRequest.options

src/backEnd/api/webApi/admin.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ async def add_task(taskAddRequest: TaskAddRequest, request: Request, current_use
3131
remote_addr=remote_ip,
3232
scanUrl=taskAddRequest.scanUrl,
3333
host=taskAddRequest.host,
34+
method=taskAddRequest.method,
3435
headers=taskAddRequest.headers,
3536
body=taskAddRequest.body,
3637
options=taskAddRequest.options

src/backEnd/model/Task.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,14 @@ def get_default_http_request_temp_dir():
4747

4848

4949
class Task(object):
50-
def __init__(self, taskid, remote_addr, scanUrl, host, headers, body):
50+
def __init__(self, taskid, remote_addr, scanUrl, host, method, headers, body):
5151
self.status = TaskStatus.New
5252
self.create_datetime = datetime.now() # 任务创建时间 (New状态)
5353
self.start_datetime = None # 任务开始执行时间 (Running状态)
5454
self.taskid = taskid
5555
self.scanUrl = scanUrl
5656
self.host = host
57+
self.method = method
5758
self.headers = headers
5859
self.body = body
5960
self.remote_addr = remote_addr
@@ -266,8 +267,8 @@ def _build_raw_http_request(self):
266267
if parsed_url.query:
267268
path += "?" + parsed_url.query
268269

269-
# 确定请求方法 (如果有body则为POST,否则为GET)
270-
method = "POST" if self.body else "GET"
270+
# 使用存储的method,如果不存在则根据body推断
271+
method = self.method if self.method else ("POST" if self.body else "GET")
271272

272273
# 构建请求行
273274
request_line = f"{method} {path} HTTP/1.1"

src/backEnd/model/requestModel/TaskRequest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class TaskQueryRequest(BaseModel):
3131
class TaskAddRequest(BaseModel):
3232
scanUrl: Annotated[str, Field(description="扫描地址...")]
3333
host: Annotated[str, Field(description="扫描域名...")]
34+
method: Annotated[str, Field(description="请求方法...")]
3435
headers: Annotated[list, Field(description="请求头...")]
3536
body: Annotated[str, Field(description="请求体...")]
3637
options: Annotated[dict, Field(description="扫描参数...")]

src/backEnd/service/taskService.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,17 +59,17 @@ class TaskService(object):
5959
def __init__(self):
6060
pass
6161

62-
def _create_task_sync(self, remote_addr: str, scanUrl: str, host, headers: list, body: str, options: dict, taskid: str):
62+
def _create_task_sync(self, remote_addr: str, scanUrl: str, host, method: str, headers: list, body: str, options: dict, taskid: str):
6363
"""同步创建任务(在线程池中执行)"""
6464
with DataStore.tasks_lock:
65-
DataStore.tasks[taskid] = Task(taskid, remote_addr, scanUrl, host, headers, body)
65+
DataStore.tasks[taskid] = Task(taskid, remote_addr, scanUrl, host, method, headers, body)
6666
for option in options:
6767
logger.debug(f"option: {option}, value: {options[option]}")
6868
DataStore.tasks[taskid].set_option(option, options[option])
6969
DataStore.tasks[taskid].status = TaskStatus.Runnable
7070
return DataStore.tasks[taskid].engine_get_id()
7171

72-
async def star_task(self, remote_addr: str, scanUrl: str, host, headers: list, body: str, options: dict):
72+
async def star_task(self, remote_addr: str, scanUrl: str, host, method: str, headers: list, body: str, options: dict):
7373
option_check_res = validate_options(options)
7474
if option_check_res is not None:
7575
return option_check_res
@@ -81,7 +81,7 @@ async def star_task(self, remote_addr: str, scanUrl: str, host, headers: list, b
8181
engine_id = await loop.run_in_executor(
8282
self._executor,
8383
self._create_task_sync,
84-
remote_addr, scanUrl, host, headers, body, options, taskid
84+
remote_addr, scanUrl, host, method, headers, body, options, taskid
8585
)
8686
return BaseResponseMsg(
8787
data={"engineid": engine_id, "taskid": taskid},
@@ -528,6 +528,7 @@ def _get_task_http_request_info_sync(self, taskId):
528528
task = DataStore.tasks[taskId]
529529
http_info = {
530530
"url": task.scanUrl,
531+
"method": task.method,
531532
"headers": task.headers,
532533
"body": task.body,
533534
}

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

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,10 +351,20 @@ private void sendRequestToBackend(IHttpRequestResponse requestResponse, ScanConf
351351
}
352352
optionsJson.append("}");
353353

354+
// 提取HTTP方法(从headers的第一行)
355+
String method = "GET";
356+
if (headers != null && !headers.isEmpty()) {
357+
String firstHeader = headers.get(0);
358+
if (firstHeader != null && firstHeader.contains(" ")) {
359+
method = firstHeader.substring(0, firstHeader.indexOf(" "));
360+
}
361+
}
362+
354363
String jsonPayload = String.format(
355-
"{\"scanUrl\":\"%s\",\"host\":\"%s\",\"headers\":%s,\"body\":\"%s\",\"options\":%s}",
364+
"{\"scanUrl\":\"%s\",\"host\":\"%s\",\"method\":\"%s\",\"headers\":%s,\"body\":\"%s\",\"options\":%s}",
356365
JsonUtils.escapeJson(url),
357366
JsonUtils.escapeJson(requestInfo.getUrl().getHost()),
367+
JsonUtils.escapeJson(method),
358368
headersJson.toString(),
359369
JsonUtils.escapeJson(body),
360370
optionsJson.toString()

src/burpEx/montoya-api/src/main/java/com/sqlmapwebui/burp/SqlmapContextMenuProvider.java

Lines changed: 12 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import burp.api.montoya.ui.contextmenu.ContextMenuItemsProvider;
88

99
import com.sqlmapwebui.burp.dialogs.*;
10+
import com.sqlmapwebui.burp.util.PayloadBuilder;
1011

1112
import javax.swing.*;
1213
import java.awt.*;
@@ -273,32 +274,6 @@ private void sendRequestToBackend(HttpRequest request, ScanConfig config) {
273274
headersList.add(header.name() + ": " + header.value())
274275
);
275276

276-
// 构建JSON payload
277-
StringBuilder headersJson = new StringBuilder("[");
278-
for (int i = 0; i < headersList.size(); i++) {
279-
headersJson.append("\"").append(JsonUtils.escapeJson(headersList.get(i))).append("\"");
280-
if (i < headersList.size() - 1) headersJson.append(",");
281-
}
282-
headersJson.append("]");
283-
284-
// 构建options
285-
Map<String, Object> options = config.toOptionsMap();
286-
StringBuilder optionsJson = new StringBuilder("{");
287-
boolean first = true;
288-
for (Map.Entry<String, Object> entry : options.entrySet()) {
289-
if (!first) optionsJson.append(",");
290-
first = false;
291-
optionsJson.append("\"").append(entry.getKey()).append("\":");
292-
if (entry.getValue() instanceof String) {
293-
optionsJson.append("\"").append(JsonUtils.escapeJson((String)entry.getValue())).append("\"");
294-
} else if (entry.getValue() instanceof Boolean) {
295-
optionsJson.append(entry.getValue());
296-
} else {
297-
optionsJson.append(entry.getValue());
298-
}
299-
}
300-
optionsJson.append("}");
301-
302277
// 提取host
303278
String host = "";
304279
try {
@@ -308,13 +283,17 @@ private void sendRequestToBackend(HttpRequest request, ScanConfig config) {
308283
host = "unknown";
309284
}
310285

311-
String jsonPayload = String.format(
312-
"{\"scanUrl\":\"%s\",\"host\":\"%s\",\"headers\":%s,\"body\":\"%s\",\"options\":%s}",
313-
JsonUtils.escapeJson(url),
314-
JsonUtils.escapeJson(host),
315-
headersJson.toString(),
316-
JsonUtils.escapeJson(body),
317-
optionsJson.toString()
286+
// 构建options
287+
Map<String, Object> options = config.toOptionsMap();
288+
289+
// 使用 PayloadBuilder 构建JSON
290+
String jsonPayload = PayloadBuilder.buildTaskPayload(
291+
url,
292+
host,
293+
request.method(),
294+
headersList,
295+
body,
296+
options
318297
);
319298

320299
// 异步发送到后端
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
package com.sqlmapwebui.burp.util;
2+
3+
import org.slf4j.Logger;
4+
import org.slf4j.LoggerFactory;
5+
6+
/**
7+
* 日志工具类(Java 17)
8+
* 统一使用 SLF4J 替代 System.out.println 和 PrintWriter
9+
*/
10+
public final class LoggerUtil {
11+
12+
private LoggerUtil() {
13+
throw new AssertionError("LoggerUtil cannot be instantiated");
14+
}
15+
16+
/**
17+
* 获取 Logger
18+
*/
19+
public static Logger getLogger(Class<?> clazz) {
20+
return LoggerFactory.getLogger(clazz);
21+
}
22+
23+
/**
24+
* 获取 Logger(使用类名)
25+
*/
26+
public static Logger getLogger(String name) {
27+
return LoggerFactory.getLogger(name);
28+
}
29+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package com.sqlmapwebui.burp.util;
2+
3+
import com.google.gson.Gson;
4+
import com.google.gson.JsonObject;
5+
6+
import java.util.List;
7+
import java.util.Map;
8+
9+
/**
10+
* HTTP 请求 Payload 构建器
11+
* 使用 Gson 统一处理 JSON 序列化,替代手动拼接
12+
*
13+
* 注意:此类使用 Java 17 语法
14+
*/
15+
public final class PayloadBuilder {
16+
17+
private static final Gson GSON = new Gson();
18+
19+
private PayloadBuilder() {
20+
throw new AssertionError("PayloadBuilder cannot be instantiated");
21+
}
22+
23+
/**
24+
* 构建任务 Payload
25+
*
26+
* @param scanUrl 扫描 URL
27+
* @param host 主机
28+
* @param method HTTP 方法
29+
* @param headers Headers 列表
30+
* @param body 请求体
31+
* @param options 扫描选项
32+
* @return JSON 字符串
33+
*/
34+
public static String buildTaskPayload(
35+
String scanUrl,
36+
String host,
37+
String method,
38+
List<String> headers,
39+
String body,
40+
Map<String, Object> options) {
41+
42+
JsonObject payload = new JsonObject();
43+
payload.addProperty("scanUrl", scanUrl);
44+
payload.addProperty("host", host);
45+
payload.addProperty("method", method);
46+
payload.add("headers", GSON.toJsonTree(headers));
47+
payload.addProperty("body", body);
48+
payload.add("options", GSON.toJsonTree(options));
49+
50+
return GSON.toJson(payload);
51+
}
52+
}

0 commit comments

Comments
 (0)