diff --git a/BurpFastJsonScan.iml b/BurpFastJsonScan.iml
new file mode 100644
index 0000000..1559b52
--- /dev/null
+++ b/BurpFastJsonScan.iml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 925fa63..262162a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
com.github.pmiaowu
BurpFastJsonScan
- 2.1.3
+ 2.2.0
diff --git a/src/main/java/burp/Application/CmdEchoExtension/CmdEcho.java b/src/main/java/burp/Application/CmdEchoExtension/CmdEcho.java
index 9f584a4..42456c3 100644
--- a/src/main/java/burp/Application/CmdEchoExtension/CmdEcho.java
+++ b/src/main/java/burp/Application/CmdEchoExtension/CmdEcho.java
@@ -5,6 +5,7 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
+import burp.Bootstrap.GlobalVariableReader;
import burp.IBurpExtenderCallbacks;
import burp.Bootstrap.YamlReader;
@@ -12,6 +13,8 @@
import burp.Application.ExtensionInterface.IAppExtension;
public class CmdEcho {
+ private GlobalVariableReader globalVariableReader;
+
private IBurpExtenderCallbacks callbacks;
private BurpAnalyzedRequest analyzedRequest;
@@ -24,10 +27,13 @@ public class CmdEcho {
private Date startDate = new Date();
public CmdEcho(
+ GlobalVariableReader globalVariableReader,
IBurpExtenderCallbacks callbacks,
BurpAnalyzedRequest analyzedRequest,
YamlReader yamlReader,
String callClassName) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
+ this.globalVariableReader = globalVariableReader;
+
this.callbacks = callbacks;
this.analyzedRequest = analyzedRequest;
@@ -47,6 +53,7 @@ private void init(String callClassName) throws ClassNotFoundException, NoSuchMet
Class c = Class.forName("burp.Application.CmdEchoExtension.ExtensionMethod." + callClassName);
Constructor cConstructor = c.getConstructor(
+ GlobalVariableReader.class,
IBurpExtenderCallbacks.class,
BurpAnalyzedRequest.class,
YamlReader.class,
@@ -54,6 +61,7 @@ private void init(String callClassName) throws ClassNotFoundException, NoSuchMet
Date.class,
Integer.class);
this.cmdEcho = (IAppExtension) cConstructor.newInstance(
+ this.globalVariableReader,
this.callbacks,
this.analyzedRequest,
this.yamlReader,
diff --git a/src/main/java/burp/Application/CmdEchoExtension/ExtensionMethod/CmdEchoScan.java b/src/main/java/burp/Application/CmdEchoExtension/ExtensionMethod/CmdEchoScan.java
index 61fa3c8..d638281 100644
--- a/src/main/java/burp/Application/CmdEchoExtension/ExtensionMethod/CmdEchoScan.java
+++ b/src/main/java/burp/Application/CmdEchoExtension/ExtensionMethod/CmdEchoScan.java
@@ -8,15 +8,14 @@
import burp.*;
-import burp.Bootstrap.CustomBurpHelpers;
-import burp.Bootstrap.YamlReader;
-import burp.Bootstrap.CustomHelpers;
-import burp.Bootstrap.BurpAnalyzedRequest;
+import burp.Bootstrap.*;
import burp.Application.ExtensionInterface.AAppExtension;
import burp.CustomErrorException.TaskTimeoutException;
public class CmdEchoScan extends AAppExtension {
+ private GlobalVariableReader globalVariableReader;
+
private IBurpExtenderCallbacks callbacks;
private IExtensionHelpers helpers;
@@ -34,9 +33,12 @@ public class CmdEchoScan extends AAppExtension {
// 命令输出点
private String commandOutputPoint;
- public CmdEchoScan(IBurpExtenderCallbacks callbacks, BurpAnalyzedRequest analyzedRequest,
+ public CmdEchoScan(GlobalVariableReader globalVariableReader,
+ IBurpExtenderCallbacks callbacks, BurpAnalyzedRequest analyzedRequest,
YamlReader yamlReader, List payloads,
Date startDate, Integer maxExecutionTime) {
+ this.globalVariableReader = globalVariableReader;
+
this.callbacks = callbacks;
this.helpers = callbacks.getHelpers();
@@ -57,6 +59,11 @@ public CmdEchoScan(IBurpExtenderCallbacks callbacks, BurpAnalyzedRequest analyze
private void runExtension() {
for (String payload : this.payloads) {
+ // 这个参数为true说明插件已经被卸载,退出所有任务,避免继续扫描
+ if (this.globalVariableReader.getBooleanData("isExtensionUnload")) {
+ return;
+ }
+
if (this.isIssue()) {
return;
}
diff --git a/src/main/java/burp/Application/RemoteCmdExtension/ExtensionMethod/RemoteCmdScan.java b/src/main/java/burp/Application/RemoteCmdExtension/ExtensionMethod/RemoteCmdScan.java
index 4f24e09..5809f47 100644
--- a/src/main/java/burp/Application/RemoteCmdExtension/ExtensionMethod/RemoteCmdScan.java
+++ b/src/main/java/burp/Application/RemoteCmdExtension/ExtensionMethod/RemoteCmdScan.java
@@ -8,6 +8,7 @@
import burp.*;
+import burp.Bootstrap.GlobalVariableReader;
import burp.CustomScanIssue;
import burp.DnsLogModule.DnsLog;
import burp.Bootstrap.YamlReader;
@@ -17,6 +18,8 @@
import burp.CustomErrorException.TaskTimeoutException;
public class RemoteCmdScan extends AAppExtension {
+ private GlobalVariableReader globalVariableReader;
+
private IBurpExtenderCallbacks callbacks;
private IExtensionHelpers helpers;
@@ -37,9 +40,12 @@ public class RemoteCmdScan extends AAppExtension {
private ArrayList dnsLogUrlArrayList = new ArrayList<>();
private ArrayList httpRequestResponseArrayList = new ArrayList<>();
- public RemoteCmdScan(IBurpExtenderCallbacks callbacks, BurpAnalyzedRequest analyzedRequest,
+ public RemoteCmdScan(GlobalVariableReader globalVariableReader,
+ IBurpExtenderCallbacks callbacks, BurpAnalyzedRequest analyzedRequest,
DnsLog dnsLog, YamlReader yamlReader, List payloads,
Date startDate, Integer maxExecutionTime) {
+ this.globalVariableReader = globalVariableReader;
+
this.callbacks = callbacks;
this.helpers = callbacks.getHelpers();
@@ -62,6 +68,11 @@ public RemoteCmdScan(IBurpExtenderCallbacks callbacks, BurpAnalyzedRequest analy
private void runExtension() {
for (String payload : this.payloads) {
+ // 这个参数为true说明插件已经被卸载,退出所有任务,避免继续扫描
+ if (this.globalVariableReader.getBooleanData("isExtensionUnload")) {
+ return;
+ }
+
// 说明接收到了dnslog请求确定是FastJson
if (this.isIssue()) {
return;
diff --git a/src/main/java/burp/Application/RemoteCmdExtension/RemoteCmd.java b/src/main/java/burp/Application/RemoteCmdExtension/RemoteCmd.java
index b2e4442..45c7855 100644
--- a/src/main/java/burp/Application/RemoteCmdExtension/RemoteCmd.java
+++ b/src/main/java/burp/Application/RemoteCmdExtension/RemoteCmd.java
@@ -5,6 +5,7 @@
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
+import burp.Bootstrap.GlobalVariableReader;
import burp.IBurpExtenderCallbacks;
import burp.DnsLogModule.DnsLog;
@@ -13,6 +14,8 @@
import burp.Application.ExtensionInterface.IAppExtension;
public class RemoteCmd {
+ private GlobalVariableReader globalVariableReader;
+
private IBurpExtenderCallbacks callbacks;
private BurpAnalyzedRequest analyzedRequest;
@@ -27,11 +30,14 @@ public class RemoteCmd {
private Date startDate = new Date();
public RemoteCmd(
+ GlobalVariableReader globalVariableReader,
IBurpExtenderCallbacks callbacks,
BurpAnalyzedRequest analyzedRequest,
DnsLog dnsLog,
YamlReader yamlReader,
String callClassName) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
+ this.globalVariableReader = globalVariableReader;
+
this.callbacks = callbacks;
this.analyzedRequest = analyzedRequest;
@@ -53,6 +59,7 @@ private void init(String callClassName) throws ClassNotFoundException, NoSuchMet
Class c = Class.forName("burp.Application.RemoteCmdExtension.ExtensionMethod." + callClassName);
Constructor cConstructor = c.getConstructor(
+ GlobalVariableReader.class,
IBurpExtenderCallbacks.class,
BurpAnalyzedRequest.class,
DnsLog.class,
@@ -61,6 +68,7 @@ private void init(String callClassName) throws ClassNotFoundException, NoSuchMet
Date.class,
Integer.class);
this.remoteCmd = (IAppExtension) cConstructor.newInstance(
+ this.globalVariableReader,
this.callbacks,
this.analyzedRequest,
this.dnsLog,
diff --git a/src/main/java/burp/Bootstrap/GlobalVariableReader.java b/src/main/java/burp/Bootstrap/GlobalVariableReader.java
new file mode 100644
index 0000000..f847ad2
--- /dev/null
+++ b/src/main/java/burp/Bootstrap/GlobalVariableReader.java
@@ -0,0 +1,36 @@
+package burp.Bootstrap;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class GlobalVariableReader {
+ private ConcurrentHashMap booleanMap;
+
+ public GlobalVariableReader() {
+ this.booleanMap = new ConcurrentHashMap();
+ }
+
+ public Map getBooleanMap() {
+ return this.booleanMap;
+ }
+
+ public Boolean getBooleanData(String key) {
+ return this.getBooleanMap().get(key);
+ }
+
+ public void putBooleanData(String key, Boolean b) {
+ if (key == null || key.length() <= 0) {
+ throw new IllegalArgumentException("key不能为空");
+ }
+
+ synchronized (this.getBooleanMap()) {
+ this.getBooleanMap().put(key, b);
+ }
+ }
+
+ public void delBooleanData(String key) {
+ if (this.getBooleanMap().get(key) != null) {
+ this.getBooleanMap().remove(key);
+ }
+ }
+}
diff --git a/src/main/java/burp/BurpExtender.java b/src/main/java/burp/BurpExtender.java
index 0584e64..ef8808b 100644
--- a/src/main/java/burp/BurpExtender.java
+++ b/src/main/java/burp/BurpExtender.java
@@ -1,6 +1,7 @@
package burp;
import java.util.List;
+import java.util.Arrays;
import java.util.ArrayList;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
@@ -11,12 +12,15 @@
import burp.Bootstrap.YamlReader;
import burp.Bootstrap.CustomBurpUrl;
import burp.Bootstrap.BurpAnalyzedRequest;
+import burp.Bootstrap.GlobalVariableReader;
import burp.CustomErrorException.TaskTimeoutException;
import burp.Application.RemoteCmdExtension.RemoteCmd;
-public class BurpExtender implements IBurpExtender, IScannerCheck {
+public class BurpExtender implements IBurpExtender, IScannerCheck, IExtensionStateListener {
public static String NAME = "FastJsonScan";
- public static String VERSION = "2.1.3";
+ public static String VERSION = "2.2.0";
+
+ private GlobalVariableReader globalVariableReader;
private IBurpExtenderCallbacks callbacks;
private IExtensionHelpers helpers;
@@ -36,6 +40,15 @@ public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
this.stdout = new PrintWriter(callbacks.getStdout(), true);
this.stderr = new PrintWriter(callbacks.getStderr(), true);
+ // 全局变量的数据保存地址
+ // 用于在程序执行的过程中能够实时的修改变量数据使用
+ this.globalVariableReader = new GlobalVariableReader();
+
+ // 是否卸载扩展
+ // 用于卸载插件以后,把程序快速退出去,避免卡顿
+ // true = 已被卸载, false = 未卸载
+ this.globalVariableReader.putBooleanData("isExtensionUnload", false);
+
// 标签界面
this.tags = new Tags(callbacks, NAME);
@@ -44,6 +57,7 @@ public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
callbacks.setExtensionName(NAME);
callbacks.registerScannerCheck(this);
+ callbacks.registerExtensionStateListener(this);
// 基本信息输出
// 作者拿来臭美用的 ╰(*°▽°*)╯
@@ -72,6 +86,9 @@ private static String basicInformationOutput() {
public List doPassiveScan(IHttpRequestResponse baseRequestResponse) {
List issues = new ArrayList<>();
+ List domainNameBlacklist = this.yamlReader.getStringList("scan.domainName.blacklist");
+ List domainNameWhitelist = this.yamlReader.getStringList("scan.domainName.whitelist");
+
// 基础url解析
CustomBurpUrl baseBurpUrl = new CustomBurpUrl(this.callbacks, baseRequestResponse);
@@ -86,6 +103,25 @@ public List doPassiveScan(IHttpRequestResponse baseRequestResponse)
return null;
}
+ // 判断域名黑名单
+ if (domainNameBlacklist != null && domainNameBlacklist.size() >= 1) {
+ if (isMatchDomainName(baseBurpUrl.getRequestHost(), domainNameBlacklist)) {
+ return null;
+ }
+ }
+
+ // 判断域名白名单
+ if (domainNameWhitelist != null && domainNameWhitelist.size() >= 1) {
+ if (!isMatchDomainName(baseBurpUrl.getRequestHost(), domainNameWhitelist)) {
+ return null;
+ }
+ }
+
+ // 判断当前请求后缀,是否为url黑名单后缀
+ if (this.isUrlBlackListSuffix(baseBurpUrl)) {
+ return null;
+ }
+
// 判断是否有允许扫描的JSON类型
if (this.tags.getBaseSettingTagClass().getScanTypeList().size() == 0) {
return null;
@@ -271,7 +307,7 @@ private IScanIssue cmdEchoExtension(int tagId, BurpAnalyzedRequest analyzedReque
return null;
}
- CmdEcho cmdEcho = new CmdEcho(this.callbacks, analyzedRequest, this.yamlReader, provider);
+ CmdEcho cmdEcho = new CmdEcho(this.globalVariableReader, this.callbacks, analyzedRequest, this.yamlReader, provider);
if (!cmdEcho.run().isIssue()) {
return null;
}
@@ -312,7 +348,7 @@ private IScanIssue remoteCmdExtension(int tagId, BurpAnalyzedRequest analyzedReq
}
DnsLog dnsLog = new DnsLog(this.callbacks, this.yamlReader.getString("dnsLogModule.provider"));
- RemoteCmd remoteCmd = new RemoteCmd(this.callbacks, analyzedRequest, dnsLog, this.yamlReader, provider);
+ RemoteCmd remoteCmd = new RemoteCmd(this.globalVariableReader, this.callbacks, analyzedRequest, dnsLog, this.yamlReader, provider);
if (!remoteCmd.run().isIssue()) {
return null;
}
@@ -370,4 +406,118 @@ private Integer getSiteJsonNumber(String domainName) {
}
return number;
}
+
+ /**
+ * 判断是否查找的到指定的域名
+ *
+ * @param domainName 需匹配的域名
+ * @param domainNameList 待匹配的域名列表
+ * @return
+ */
+ private static Boolean isMatchDomainName(String domainName, List domainNameList) {
+ domainName = domainName.trim();
+
+ if (domainName.length() <= 0) {
+ return false;
+ }
+
+ if (domainNameList == null || domainNameList.size() <= 0) {
+ return false;
+ }
+
+ if (domainName.contains(":")) {
+ domainName = domainName.substring(0, domainName.indexOf(":"));
+ }
+
+ String reverseDomainName = new StringBuffer(domainName).reverse().toString();
+
+ for (String domainName2 : domainNameList) {
+ domainName2 = domainName2.trim();
+
+ if (domainName2.length() <= 0) {
+ continue;
+ }
+
+ if (domainName2.contains(":")) {
+ domainName2 = domainName2.substring(0, domainName2.indexOf(":"));
+ }
+
+ String reverseDomainName2 = new StringBuffer(domainName2).reverse().toString();
+
+ if (domainName.equals(domainName2)) {
+ return true;
+ }
+
+ if (reverseDomainName.contains(".") && reverseDomainName2.contains(".")) {
+ List splitDomainName = new ArrayList(Arrays.asList(reverseDomainName.split("[.]")));
+
+ List splitDomainName2 = new ArrayList(Arrays.asList(reverseDomainName2.split("[.]")));
+
+ if (splitDomainName.size() <= 0 || splitDomainName2.size() <= 0) {
+ continue;
+ }
+
+ if (splitDomainName.size() < splitDomainName2.size()) {
+ for (int i = splitDomainName.size(); i < splitDomainName2.size(); i++) {
+ splitDomainName.add("*");
+ }
+ }
+
+ if (splitDomainName.size() > splitDomainName2.size()) {
+ for (int i = splitDomainName2.size(); i < splitDomainName.size(); i++) {
+ splitDomainName2.add("*");
+ }
+ }
+
+ int ii = 0;
+ for (int i = 0; i < splitDomainName.size(); i++) {
+ if (splitDomainName2.get(i).equals("*")) {
+ ii = ii + 1;
+ } else if (splitDomainName.get(i).equals(splitDomainName2.get(i))) {
+ ii = ii + 1;
+ }
+ }
+
+ if (ii == splitDomainName.size()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * 判断是否url黑名单后缀
+ * 大小写不区分
+ * 是 = true, 否 = false
+ *
+ * @param burpUrl
+ * @return
+ */
+ private boolean isUrlBlackListSuffix(CustomBurpUrl burpUrl) {
+ if (!this.yamlReader.getBoolean("urlBlackListSuffix.config.isStart")) {
+ return false;
+ }
+
+ String noParameterUrl = burpUrl.getHttpRequestUrl().toString().split("\\?")[0];
+ String urlSuffix = noParameterUrl.substring(noParameterUrl.lastIndexOf(".") + 1);
+
+ List suffixList = this.yamlReader.getStringList("urlBlackListSuffix.suffixList");
+ if (suffixList == null || suffixList.size() == 0) {
+ return false;
+ }
+
+ for (String s : suffixList) {
+ if (s.toLowerCase().equals(urlSuffix.toLowerCase())) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public void extensionUnloaded() {
+ this.globalVariableReader.putBooleanData("isExtensionUnload", true);
+ }
}
diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml
index 80c2d03..460fd14 100644
--- a/src/main/resources/config.yml
+++ b/src/main/resources/config.yml
@@ -20,6 +20,35 @@ scan:
# 超过次数以后就不在对该站点进行扫描了
# 0 表示无限次扫描
siteScanNumber: 0
+ # 域名扫描规则
+ domainName:
+ # 域名黑名单
+ # 注: 黑名单优先级最高
+ # 注: 为空表示关闭该功能
+ # 使用规则:
+ # 1. 过滤某个域名: www.domain1.com
+ # 2. 过滤某个域名的全部子域名: *.domain2.com
+ # 3. 过滤某个域名的部分子域名: a.*.domain2.com/*.a.*.domain2.com
+ # 使用方法:
+ # blacklist:
+ # - "www.domain1.com"
+ # - "*.domain2.com"
+ blacklist:
+ - "*.dnslog.cn"
+ - "*.ceye.io"
+ - "*.fofa.so"
+ # 域名白名单
+ # 注: 黑名单优先级最高
+ # 注: 为空表示关闭该功能
+ # 使用规则:
+ # 1. 只扫描某个域名: www.domain1.com
+ # 2. 只扫描某个域名的全部子域名: *.domain2.com
+ # 3. 只扫描某个域名的部分子域名: a.*.domain2.com/*.a.*.domain2.com
+ # 使用方法:
+ # whitelist:
+ # - "www.domain1.com"
+ # - "*.domain2.com"
+ whitelist:
# 扫描类型
type:
# 用于判断是否将 Get参数的Json 作为扫描参数
@@ -33,6 +62,120 @@ scan:
# 用于判断是否将 HTTP请求正文的Json 作为扫描参数
isScanBodyJson: true
+# url黑名单后缀
+# url的后缀出现这些字段的都不进行测试
+urlBlackListSuffix:
+ config:
+ isStart: true
+ suffixList:
+ - "3g2"
+ - "3gp"
+ - "7z"
+ - "aac"
+ - "abw"
+ - "aif"
+ - "aifc"
+ - "aiff"
+ - "arc"
+ - "au"
+ - "avi"
+ - "azw"
+ - "bin"
+ - "bmp"
+ - "bz"
+ - "bz2"
+ - "cmx"
+ - "cod"
+ - "csh"
+ - "css"
+ - "csv"
+ - "doc"
+ - "docx"
+ - "eot"
+ - "epub"
+ - "gif"
+ - "gz"
+ - "ico"
+ - "ics"
+ - "ief"
+ - "jar"
+ - "jfif"
+ - "jpe"
+ - "jpeg"
+ - "jpg"
+ - "m3u"
+ - "mid"
+ - "midi"
+ - "mjs"
+ - "mp2"
+ - "mp3"
+ - "mpa"
+ - "mpe"
+ - "mpeg"
+ - "mpg"
+ - "mpkg"
+ - "mpp"
+ - "mpv2"
+ - "odp"
+ - "ods"
+ - "odt"
+ - "oga"
+ - "ogv"
+ - "ogx"
+ - "otf"
+ - "pbm"
+ - "pdf"
+ - "pgm"
+ - "png"
+ - "pnm"
+ - "ppm"
+ - "ppt"
+ - "pptx"
+ - "ra"
+ - "ram"
+ - "rar"
+ - "ras"
+ - "rgb"
+ - "rmi"
+ - "rtf"
+ - "snd"
+ - "svg"
+ - "swf"
+ - "tar"
+ - "tif"
+ - "tiff"
+ - "ttf"
+ - "vsd"
+ - "wav"
+ - "weba"
+ - "webm"
+ - "webp"
+ - "woff"
+ - "woff2"
+ - "xbm"
+ - "xls"
+ - "xlsx"
+ - "xpm"
+ - "xul"
+ - "xwd"
+ - "zip"
+ - "js"
+ - "wmv"
+ - "asf"
+ - "asx"
+ - "rm"
+ - "rmvb"
+ - "mp4"
+ - "mov"
+ - "m4v"
+ - "dat"
+ - "mkv"
+ - "flv"
+ - "vob"
+ - "txt"
+ - "php"
+ - "asp"
+
# 应用程序配置
application:
# 命令回显扩展