Compare commits

...

5 Commits
2.5.7 ... 2.5.8

Author SHA1 Message Date
gh0stkey
765807de6e Version: 2.5.8 Update 2023-11-16 19:44:27 +08:00
gh0stkey
548315e163 Version: 2.5.8 Update 2023-11-16 19:33:38 +08:00
ᴋᴇʏ
d3ab207825 Update issue templates 2023-11-16 14:31:15 +08:00
ᴋᴇʏ
44260dd4ff Update issue templates 2023-11-16 14:27:15 +08:00
gh0stkey
cf3ac4978f Update README.md 2023-11-15 13:18:50 +08:00
8 changed files with 155 additions and 109 deletions

27
.github/ISSUE_TEMPLATE/问题反馈.md vendored Normal file
View File

@@ -0,0 +1,27 @@
---
name: 问题反馈
about: 尽可能详细的描述问题并反馈
title: "[BUG] "
labels: bug
assignees: ''
---
## 使用环境
```
HaE版本
BurpSuite版本
JDK版本
操作系统版本:
```
## 问题详情
问题描述:
出现的场景:
## 解决建议
无。

View File

@@ -23,6 +23,22 @@
除此之外,您也可以选择将配置文件存放在`HaE Jar包`的同级目录下的`/.config/HaE/`中,**以便于离线携带**。 除此之外,您也可以选择将配置文件存放在`HaE Jar包`的同级目录下的`/.config/HaE/`中,**以便于离线携带**。
### 规则释义
HaE目前的规则一共有6个字段分别是规则名称、规则正则、规则作用域、正则引擎、规则匹配颜色、规则敏感性。
详细的含义如下所示:
| 字段 | 含义 |
|-----------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Name | 规则名称,主要用于简短概括当前规则的作用。 |
| Regex | 规则正则主要用于填写正则表达式。在HaE中所需提取匹配的内容需要用`(``)`将正则表达式进行包裹。 |
| Scope | 规则作用域主要用于表示当前规则作用与HTTP报文的哪个部分。 |
| Engine | 正则引擎,主要用于表示当前规则的正则表达式所使用的引擎。**DFA引擎**:对于文本串里的每一个字符只需扫描一次,速度快、特性少;**NFA引擎**:要翻来覆去标注字符、取消标注字符,速度慢,但是特性(如:分组、替换、分割)丰富。 |
| Color | 规则匹配颜色主要用于表示当前规则匹配到对应HTTP报文时所需标记的高亮颜色。 |
| Sensitive | 规则敏感性,主要用于表示当前规则对于大小写字母是否敏感,敏感(`True`)则严格按照大小写要求匹配,不敏感(`False`)则反之。 |
## 优势特点 ## 优势特点
1. 精细配置:高度自由的配置选项,以满足各类精细化场景需求。 1. 精细配置:高度自由的配置选项,以满足各类精细化场景需求。

View File

@@ -9,7 +9,6 @@ import burp.ui.board.MessagePanel;
import java.beans.PropertyChangeEvent; import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener; import java.beans.PropertyChangeListener;
import java.net.URL; import java.net.URL;
import java.security.NoSuchAlgorithmException;
import java.util.*; import java.util.*;
import javax.swing.*; import javax.swing.*;
import java.awt.*; import java.awt.*;
@@ -39,7 +38,7 @@ public class BurpExtender implements IBurpExtender, IHttpListener, IMessageEdito
new ConfigLoader(); new ConfigLoader();
String version = "2.5.7"; String version = "2.5.8";
callbacks.setExtensionName(String.format("HaE (%s) - Highlighter and Extractor", version)); callbacks.setExtensionName(String.format("HaE (%s) - Highlighter and Extractor", version));
// 定义输出 // 定义输出
@@ -121,65 +120,41 @@ public class BurpExtender implements IBurpExtender, IHttpListener, IMessageEdito
public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) { public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) {
// 判断是否是响应且该代码作用域为REPEATER、INTRUDER、PROXY分别对应toolFlag 64、32、4 // 判断是否是响应且该代码作用域为REPEATER、INTRUDER、PROXY分别对应toolFlag 64、32、4
if (toolFlag == 64 || toolFlag == 32 || toolFlag == 4) { if (toolFlag == 64 || toolFlag == 32 || toolFlag == 4) {
byte[] content; if (!messageIsRequest) {
IHttpService iHttpService = messageInfo.getHttpService();
String host = iHttpService.getHost();
if (messageIsRequest) { List<Map<String, String>> result = null;
content = messageInfo.getRequest();
} else {
content = messageInfo.getResponse();
}
IHttpService iHttpService = null; String originalColor = messageInfo.getHighlight();
String originalComment = messageInfo.getComment();
String host = ""; try {
result = messageProcessor.processMessage(helpers, messageInfo, host, true);
try { if (result != null && !result.isEmpty() && result.size() > 0) {
iHttpService = messageInfo.getHttpService(); List<String> colorList = new ArrayList<>();
host = iHttpService.getHost();
} catch (Exception ignored) {
}
if (Objects.equals(host, "")) { if (originalColor != null) {
List<String> requestTmpHeaders = helpers.analyzeRequest(content).getHeaders(); colorList.add(originalColor);
host = requestTmpHeaders.get(1).split(":")[1].trim(); }
}
List<Map<String, String>> result = null; colorList.add(result.get(0).get("color"));
String resColor = colorProcessor.retrieveFinalColor(colorProcessor.retrieveColorIndices(colorList));
messageInfo.setHighlight(resColor);
try { String addComment = String.join(", ", result.get(1).get("comment"));
result = messageProcessor.processMessage(helpers, content, messageIsRequest, true, host); String allComment = !Objects.equals(originalComment, "") ? String.format("%s, %s", originalComment, addComment) : addComment;
} catch (NoSuchAlgorithmException e) { String resComment = mergeComment(allComment);
throw new RuntimeException(e); messageInfo.setComment(resComment);
}
String resComment = ""; messagePanel.add(messageInfo, resComment, resColor);
String resColor = ""; }
String originalColor = messageInfo.getHighlight(); } catch (Exception e) {
String originalComment = messageInfo.getComment(); e.printStackTrace();
if (result != null && !result.isEmpty() && result.size() > 0) {
List<String> colorList = new ArrayList<>();
if (originalColor != null) {
colorList.add(originalColor);
} }
colorList.add(result.get(0).get("color"));
resColor = colorProcessor.retrieveFinalColor(colorProcessor.retrieveColorIndices(colorList));
messageInfo.setHighlight(resColor);
String addComment = String.join(", ", result.get(1).get("comment"));
String allComment = !Objects.equals(originalComment, "") ? String.format("%s, %s", originalComment, addComment) : addComment;
resComment = mergeComment(allComment);
messageInfo.setComment(resComment);
} }
String endComment = resComment.isEmpty() ? originalComment : resComment;
String endColor = resColor.isEmpty() ? originalColor : resColor;
if (!messageIsRequest && !Objects.equals(endComment, "") && !Objects.equals(endColor, "")) {
messagePanel.add(messageInfo, endComment, String.valueOf(content.length), endColor);
}
} }
} }
@@ -250,9 +225,13 @@ public class BurpExtender implements IBurpExtender, IHttpListener, IMessageEdito
List<Map<String, String>> result = null; List<Map<String, String>> result = null;
try { try {
result = messageProcessor.processMessage(helpers, content, isRequest, false, ""); if (isRequest) {
} catch (NoSuchAlgorithmException e) { result = messageProcessor.processRequestMessage(helpers, content, "", false);
throw new RuntimeException(e); } else {
result = messageProcessor.processResponseMessage(helpers, content, "", false);
}
} catch (Exception e) {
e.printStackTrace();
} }
if (result != null && !result.isEmpty()) { if (result != null && !result.isEmpty()) {
@@ -264,6 +243,7 @@ public class BurpExtender implements IBurpExtender, IHttpListener, IMessageEdito
} }
return true; return true;
} }
return false; return false;
} }

View File

@@ -132,7 +132,7 @@ public class DataProcessingUnit {
tmpMap.put("data", dataStr); tmpMap.put("data", dataStr);
finalMap.put(nameAndSize, tmpMap); finalMap.put(nameAndSize, tmpMap);
// 添加到全局变量中便于Databoard检索 // 添加到全局变量中便于Databoard检索
if (!Objects.equals(host, "")) { if (!Objects.equals(host, "") && host != null) {
List<String> dataList = Arrays.asList(dataStr.split("\n")); List<String> dataList = Arrays.asList(dataStr.split("\n"));
if (ConfigEntry.globalDataMap.containsKey(host)) { if (ConfigEntry.globalDataMap.containsKey(host)) {
Map<String, List<String>> gRuleMap = new HashMap<>(ConfigEntry.globalDataMap.get(host)); Map<String, List<String>> gRuleMap = new HashMap<>(ConfigEntry.globalDataMap.get(host));

View File

@@ -1,10 +1,10 @@
package burp.core.processor; package burp.core.processor;
import burp.IExtensionHelpers; import burp.IExtensionHelpers;
import burp.IHttpRequestResponse;
import burp.IRequestInfo; import burp.IRequestInfo;
import burp.IResponseInfo; import burp.IResponseInfo;
import burp.core.utils.MatchTool; import burp.core.utils.MatchTool;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
@@ -12,53 +12,78 @@ import java.util.List;
import java.util.Map; import java.util.Map;
public class MessageProcessor { public class MessageProcessor {
MatchTool matcher = new MatchTool(); private MatchTool matcher = new MatchTool();
DataProcessingUnit dataProcessingUnit = new DataProcessingUnit(); private DataProcessingUnit dataProcessingUnit = new DataProcessingUnit();
ColorProcessor colorProcessor = new ColorProcessor(); private ColorProcessor colorProcessor = new ColorProcessor();
public List<Map<String, String>> processMessage(IExtensionHelpers helpers, byte[] content, boolean isRequest, boolean messageInfo, String host) public List<Map<String, String>> processMessage(IExtensionHelpers helpers, IHttpRequestResponse messageInfo, String host, boolean actionFlag) throws Exception {
throws NoSuchAlgorithmException {
List<Map<String, String>> result = new ArrayList<>(); byte[] requestByte = messageInfo.getRequest();
byte[] responseByte = messageInfo.getResponse();
List<Map<String, String>> reqObj = processRequestMessage(helpers, requestByte, host, actionFlag);
List<Map<String, String>> resObj = processResponseMessage(helpers, responseByte, host, actionFlag);
List<Map<String, String>> mergedList = new ArrayList<>(reqObj);
mergedList.addAll(resObj);
return mergedList;
}
public List<Map<String, String>> processRequestMessage(IExtensionHelpers helpers, byte[] content, String host, boolean actionFlag) throws Exception {
Map<String, Map<String, Object>> obj; Map<String, Map<String, Object>> obj;
if (isRequest) { IRequestInfo requestInfo = helpers.analyzeRequest(content);
IRequestInfo requestInfo = helpers.analyzeRequest(content); List<String> requestTmpHeaders = requestInfo.getHeaders();
List<String> requestTmpHeaders = requestInfo.getHeaders(); String requestHeaders = String.join("\n", requestTmpHeaders);
String requestHeaders = String.join("\n", requestTmpHeaders);
try { try {
String urlString = requestTmpHeaders.get(0).split(" ")[1]; String urlString = requestTmpHeaders.get(0).split(" ")[1];
urlString = urlString.indexOf("?") > 0 ? urlString.substring(0, urlString.indexOf("?")) : urlString; urlString = urlString.indexOf("?") > 0 ? urlString.substring(0, urlString.indexOf("?")) : urlString;
if (matcher.matchUrlSuffix(urlString)) { if (matcher.matchUrlSuffix(urlString)) {
return result; return null;
}
} catch (Exception e) {
return result;
} }
} catch (Exception e) {
int requestBodyOffset = requestInfo.getBodyOffset(); e.printStackTrace();
byte[] requestBody = Arrays.copyOfRange(content, requestBodyOffset, content.length); return null;
obj = dataProcessingUnit.matchContentByRegex(content, requestHeaders, requestBody, "request", host);
} else {
IResponseInfo responseInfo = helpers.analyzeResponse(content);
try {
String inferredMimeType = String.format("hae.%s", responseInfo.getInferredMimeType().toLowerCase());
String statedMimeType = String.format("hae.%s", responseInfo.getStatedMimeType().toLowerCase());
if (matcher.matchUrlSuffix(statedMimeType) || matcher.matchUrlSuffix(inferredMimeType)) {
return result;
}
} catch (Exception e) {
return result;
}
List<String> responseTmpHeaders = responseInfo.getHeaders();
String responseHeaders = String.join("\n", responseTmpHeaders);
int responseBodyOffset = responseInfo.getBodyOffset();
byte[] responseBody = Arrays.copyOfRange(content, responseBodyOffset, content.length);
obj = dataProcessingUnit.matchContentByRegex(content, responseHeaders, responseBody, "response", host);
} }
int requestBodyOffset = requestInfo.getBodyOffset();
byte[] requestBody = Arrays.copyOfRange(content, requestBodyOffset, content.length);
obj = dataProcessingUnit.matchContentByRegex(content, requestHeaders, requestBody, "request", host);
return getDataList(obj, actionFlag);
}
public List<Map<String, String>> processResponseMessage(IExtensionHelpers helpers, byte[] content, String host, boolean actionFlag) throws Exception {
Map<String, Map<String, Object>> obj;
IResponseInfo responseInfo = helpers.analyzeResponse(content);
try {
String inferredMimeType = String.format("hae.%s", responseInfo.getInferredMimeType().toLowerCase());
String statedMimeType = String.format("hae.%s", responseInfo.getStatedMimeType().toLowerCase());
if (matcher.matchUrlSuffix(statedMimeType) || matcher.matchUrlSuffix(inferredMimeType)) {
return null;
}
} catch (Exception e) {
e.printStackTrace();
return null;
}
List<String> responseTmpHeaders = responseInfo.getHeaders();
String responseHeaders = String.join("\n", responseTmpHeaders);
int responseBodyOffset = responseInfo.getBodyOffset();
byte[] responseBody = Arrays.copyOfRange(content, responseBodyOffset, content.length);
obj = dataProcessingUnit.matchContentByRegex(content, responseHeaders, responseBody, "response", host);
return getDataList(obj, actionFlag);
}
private List<Map<String, String>> getDataList(Map<String, Map<String, Object>> obj, boolean actionFlag) {
List<Map<String, String>> highlightList = new ArrayList<>();
List<Map<String, String>> extractList = new ArrayList<>();
if (obj.size() > 0) { if (obj.size() > 0) {
if (messageInfo) { if (actionFlag) {
List<List<String>> resultList = dataProcessingUnit.extractColorsAndComments(obj); List<List<String>> resultList = dataProcessingUnit.extractColorsAndComments(obj);
List<String> colorList = resultList.get(0); List<String> colorList = resultList.get(0);
List<String> commentList = resultList.get(1); List<String> commentList = resultList.get(1);
@@ -70,13 +95,14 @@ public class MessageProcessor {
Map<String, String> commentMap = new HashMap<String, String>() {{ Map<String, String> commentMap = new HashMap<String, String>() {{
put("comment", String.join(", ", commentList)); put("comment", String.join(", ", commentList));
}}; }};
result.add(colorMap); highlightList.add(colorMap);
result.add(commentMap); highlightList.add(commentMap);
} }
} else { } else {
result.add(dataProcessingUnit.extractDataFromMap(obj)); extractList.add(dataProcessingUnit.extractDataFromMap(obj));
} }
} }
return result;
return actionFlag ? highlightList : extractList;
} }
} }

View File

@@ -1,8 +1,6 @@
package burp.rule.utils; package burp.rule.utils;
import burp.*; import burp.*;
import burp.config.ConfigEntry;
import burp.config.ConfigLoader;
import java.io.FileOutputStream; import java.io.FileOutputStream;
import java.net.URL; import java.net.URL;
import java.util.Arrays; import java.util.Arrays;

View File

@@ -301,9 +301,6 @@ public class Databoard extends JPanel {
for (Map.Entry<String, Map<String, List<String>>> entry : dataMap.entrySet()) { for (Map.Entry<String, Map<String, List<String>>> entry : dataMap.entrySet()) {
JTabbedPane newTabbedPane = new JTabbedPane(); JTabbedPane newTabbedPane = new JTabbedPane();
newTabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT); newTabbedPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
if (currentWorker != null && !currentWorker.isDone()) {
currentWorker.cancel(true);
}
for (Map.Entry<String, List<String>> entrySet : entry.getValue().entrySet()) { for (Map.Entry<String, List<String>> entrySet : entry.getValue().entrySet()) {
currentWorker = new SwingWorker<Object, Void>() { currentWorker = new SwingWorker<Object, Void>() {
@@ -322,8 +319,10 @@ public class Databoard extends JPanel {
if (!isCancelled()) { if (!isCancelled()) {
try { try {
Object[] result = (Object[]) get(); Object[] result = (Object[]) get();
newTabbedPane.addTab(result[0].toString(), (DatatablePanel) result[1]); SwingUtilities.invokeLater(() -> {
dataTabbedPane.addTab(entry.getKey(), newTabbedPane); newTabbedPane.addTab(result[0].toString(), (DatatablePanel) result[1]);
dataTabbedPane.addTab(entry.getKey(), newTabbedPane);
});
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
} }

View File

@@ -308,13 +308,13 @@ public class MessagePanel extends AbstractTableModel implements IMessageEditorCo
return currentlyDisplayedItem.getHttpService(); return currentlyDisplayedItem.getHttpService();
} }
public void add(IHttpRequestResponse messageInfo, String comment, String length, String color) { public void add(IHttpRequestResponse messageInfo, String comment, String color) {
synchronized(log) { synchronized(log) {
IRequestInfo iRequestInfo = helpers.analyzeRequest(messageInfo); IRequestInfo iRequestInfo = helpers.analyzeRequest(messageInfo);
URL url = iRequestInfo.getUrl(); URL url = iRequestInfo.getUrl();
String method = iRequestInfo.getMethod(); String method = iRequestInfo.getMethod();
String status = String.valueOf(helpers.analyzeResponse(messageInfo.getResponse()).getStatusCode()); String status = String.valueOf(helpers.analyzeResponse(messageInfo.getResponse()).getStatusCode());
String length = String.valueOf(messageInfo.getResponse().length);
LogEntry logEntry = new LogEntry(callbacks.saveBuffersToTempFiles(messageInfo), method, url, comment, length, color, status); LogEntry logEntry = new LogEntry(callbacks.saveBuffersToTempFiles(messageInfo), method, url, comment, length, color, status);
try { try {
@@ -329,8 +329,8 @@ public class MessagePanel extends AbstractTableModel implements IMessageEditorCo
byte[] reqByteB = reqResMessage.getRequest(); byte[] reqByteB = reqResMessage.getRequest();
byte[] resByteB = reqResMessage.getResponse(); byte[] resByteB = reqResMessage.getResponse();
try { try {
// 采用匹配数据结果比对 // 通过URL、请求和响应报文、匹配数据内容多维度进行对比
if (areMapsEqual(getCacheData(reqByteB), getCacheData(reqByteA)) && areMapsEqual(getCacheData(resByteB), getCacheData(resByteA))) { if ((entry.getUrl().toString().equals(url.toString()) || (Arrays.equals(reqByteB, reqByteA) || Arrays.equals(resByteB, resByteA))) && (areMapsEqual(getCacheData(reqByteB), getCacheData(reqByteA)) && areMapsEqual(getCacheData(resByteB), getCacheData(resByteA)))) {
isDuplicate = true; isDuplicate = true;
break; break;
} }