├── README.md
├── images
├── 1.png
├── 2.png
├── 3.png
├── 4.png
├── 5.png
├── 6.png
├── 7.png
├── 8.png
└── 9.png
├── pom.xml
├── src
└── main
│ ├── java
│ └── burp
│ │ ├── Application
│ │ ├── ShiroCipherKeyExtension
│ │ │ ├── ExtensionInterface
│ │ │ │ ├── AShiroCipherKeyExtension.java
│ │ │ │ └── IShiroCipherKeyExtension.java
│ │ │ ├── ExtensionMethod
│ │ │ │ └── ShiroCipherKeyScan.java
│ │ │ ├── ShiroCipherKey.java
│ │ │ └── ShiroCipherKeyThread.java
│ │ └── ShiroFingerprintExtension
│ │ │ ├── ExtensionInterface
│ │ │ ├── AShiroFingerprintExtension.java
│ │ │ └── IShiroFingerprintExtension.java
│ │ │ ├── ExtensionMethod
│ │ │ ├── ShiroFingerprint1.java
│ │ │ ├── ShiroFingerprint2.java
│ │ │ └── ShiroFingerprint3.java
│ │ │ └── ShiroFingerprint.java
│ │ ├── Bootstrap
│ │ ├── CustomBurpHelpers.java
│ │ ├── CustomBurpUrl.java
│ │ ├── CustomHelpers.java
│ │ ├── DiffPage.java
│ │ ├── Encrypt
│ │ │ ├── CbcEncrypt.java
│ │ │ ├── EncryptInterface.java
│ │ │ └── GcmEncrypt.java
│ │ ├── GlobalPassiveScanVariableReader.java
│ │ ├── GlobalVariableReader.java
│ │ └── YamlReader.java
│ │ ├── BurpExtender.java
│ │ ├── Config.java
│ │ ├── ConfigDlg.java
│ │ ├── CustomErrorException
│ │ ├── DiffPageException.java
│ │ └── TaskTimeoutException.java
│ │ ├── CustomScanIssue.java
│ │ ├── Encrypt.java
│ │ ├── Menu.java
│ │ ├── Ui
│ │ ├── BaseSettingTag.java
│ │ ├── ScanQueueTag.java
│ │ └── Tags.java
│ │ └── Utils.java
│ └── resources
│ └── config.yml
└── target
├── BurpShiroPassiveScan-2.0.0.jar
├── BurpShiroPassiveScan.rar
├── BurpShiroPassiveScan
├── BurpShiroPassiveScan.jar
└── resources
│ └── config.yml
├── classes
├── burp
│ ├── Application
│ │ ├── ShiroCipherKeyExtension
│ │ │ ├── ExtensionInterface
│ │ │ │ ├── AShiroCipherKeyExtension.class
│ │ │ │ └── IShiroCipherKeyExtension.class
│ │ │ ├── ExtensionMethod
│ │ │ │ └── ShiroCipherKeyScan.class
│ │ │ ├── ShiroCipherKey.class
│ │ │ └── ShiroCipherKeyThread.class
│ │ └── ShiroFingerprintExtension
│ │ │ ├── ExtensionInterface
│ │ │ ├── AShiroFingerprintExtension.class
│ │ │ └── IShiroFingerprintExtension.class
│ │ │ ├── ExtensionMethod
│ │ │ ├── ShiroFingerprint1.class
│ │ │ ├── ShiroFingerprint2.class
│ │ │ └── ShiroFingerprint3.class
│ │ │ └── ShiroFingerprint.class
│ ├── Bootstrap
│ │ ├── CustomBurpHelpers.class
│ │ ├── CustomBurpUrl.class
│ │ ├── CustomHelpers.class
│ │ ├── DiffPage.class
│ │ ├── Encrypt
│ │ │ ├── CbcEncrypt.class
│ │ │ ├── EncryptInterface.class
│ │ │ └── GcmEncrypt.class
│ │ ├── GlobalPassiveScanVariableReader.class
│ │ ├── GlobalVariableReader.class
│ │ └── YamlReader.class
│ ├── BurpExtender.class
│ ├── Config.class
│ ├── ConfigDlg$1.class
│ ├── ConfigDlg.class
│ ├── CustomErrorException
│ │ ├── DiffPageException.class
│ │ └── TaskTimeoutException.class
│ ├── CustomScanIssue.class
│ ├── Encrypt.class
│ ├── Menu$1.class
│ ├── Menu$2.class
│ ├── Menu$3.class
│ ├── Menu$4.class
│ ├── Menu$5.class
│ ├── Menu$6.class
│ ├── Menu$7.class
│ ├── Menu.class
│ ├── Ui
│ │ ├── BaseSettingTag.class
│ │ ├── ScanQueueTag$TablesData.class
│ │ ├── ScanQueueTag$URLTable.class
│ │ ├── ScanQueueTag.class
│ │ └── Tags.class
│ ├── Utils$SilentURLStreamHandler.class
│ └── Utils.class
└── config.yml
├── maven-archiver
└── pom.properties
└── maven-status
└── maven-compiler-plugin
└── compile
└── default-compile
├── createdFiles.lst
└── inputFiles.lst
/README.md:
--------------------------------------------------------------------------------
1 | ## ShiroScan2
2 | 基于[BurpShiroPassiveScan](https://github.com/pmiaowu/BurpShiroPassiveScan)项目修改增加了Xray回显链生成,修改的目的很简单,就是当pmiaowu大佬的插件检测出漏洞后,自己生成cookie验证下,进一步利用还得是ShiroAttack这类工具
3 |
4 | ## 编译方法
5 | 参考[BurpShiroPassiveScan](https://github.com/pmiaowu/BurpShiroPassiveScan#%E7%BC%96%E8%AF%91%E6%96%B9%E6%B3%95)
6 |
7 | ## 功能
8 | 在Repeater界面右键
9 |
10 | 
11 |
12 | 点击Config输入key,选择加密模式并保存,支持CBC和GCM两种
13 |
14 | 
15 |
16 | 选择利用链,自动生成Cookie
17 |
18 | 
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/images/1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/S9MF/ShiroScan2/b419d57275c54b094905cc9e46d8a9c0e7d52f45/images/1.png
--------------------------------------------------------------------------------
/images/2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/S9MF/ShiroScan2/b419d57275c54b094905cc9e46d8a9c0e7d52f45/images/2.png
--------------------------------------------------------------------------------
/images/3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/S9MF/ShiroScan2/b419d57275c54b094905cc9e46d8a9c0e7d52f45/images/3.png
--------------------------------------------------------------------------------
/images/4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/S9MF/ShiroScan2/b419d57275c54b094905cc9e46d8a9c0e7d52f45/images/4.png
--------------------------------------------------------------------------------
/images/5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/S9MF/ShiroScan2/b419d57275c54b094905cc9e46d8a9c0e7d52f45/images/5.png
--------------------------------------------------------------------------------
/images/6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/S9MF/ShiroScan2/b419d57275c54b094905cc9e46d8a9c0e7d52f45/images/6.png
--------------------------------------------------------------------------------
/images/7.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/S9MF/ShiroScan2/b419d57275c54b094905cc9e46d8a9c0e7d52f45/images/7.png
--------------------------------------------------------------------------------
/images/8.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/S9MF/ShiroScan2/b419d57275c54b094905cc9e46d8a9c0e7d52f45/images/8.png
--------------------------------------------------------------------------------
/images/9.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/S9MF/ShiroScan2/b419d57275c54b094905cc9e46d8a9c0e7d52f45/images/9.png
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.github.pmiaowu
8 | BurpShiroPassiveScan
9 | 2.0.0
10 |
11 |
12 |
13 |
14 | net.portswigger.burp.extender
15 | burp-extender-api
16 | 2.3
17 |
18 |
19 |
20 |
21 | org.yaml
22 | snakeyaml
23 | 1.29
24 |
25 |
26 |
27 |
28 | org.apache.httpcomponents
29 | httpclient
30 | 4.5.13
31 |
32 |
33 |
34 |
35 | org.apache.shiro
36 | shiro-core
37 | 1.2.4
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 | org.apache.maven.plugins
46 | maven-compiler-plugin
47 | 3.8.1
48 |
49 | 1.8
50 | 1.8
51 | UTF-8
52 |
53 |
54 |
55 | org.apache.maven.plugins
56 | maven-assembly-plugin
57 | 3.3.0
58 |
59 |
60 | BurpShiroPassiveScan
61 | false
62 |
63 |
64 | burp.BurpExtender
65 |
66 |
67 |
68 | jar-with-dependencies
69 |
70 |
71 | ${project.build.directory}/BurpShiroPassiveScan
72 |
73 |
74 |
75 |
76 |
77 |
78 | make-assembly
79 | package
80 |
81 | single
82 |
83 |
84 |
85 |
86 |
87 | org.apache.maven.plugins
88 | maven-resources-plugin
89 | 3.2.0
90 |
91 |
92 | copy-resources
93 | package
94 |
95 | copy-resources
96 |
97 |
98 | ${project.build.directory}/BurpShiroPassiveScan/resources
99 |
100 |
101 | src/main/resources
102 |
103 | **/*
104 |
105 | true
106 |
107 |
108 | UTF-8
109 |
110 |
111 |
112 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/src/main/java/burp/Application/ShiroCipherKeyExtension/ExtensionInterface/AShiroCipherKeyExtension.java:
--------------------------------------------------------------------------------
1 | package burp.Application.ShiroCipherKeyExtension.ExtensionInterface;
2 |
3 | import burp.IHttpRequestResponse;
4 |
5 | public abstract class AShiroCipherKeyExtension implements IShiroCipherKeyExtension {
6 | private String extensionName = "";
7 |
8 | private String cipherKey = "";
9 |
10 | private String encryptMethod = "";
11 |
12 | private Boolean isShiroCipherKeyExists = false;
13 |
14 | private IHttpRequestResponse newHttpRequestResponse;
15 |
16 | /**
17 | * 设置扩展名称 (必须的)
18 | *
19 | * @param value
20 | */
21 | protected void setExtensionName(String value) {
22 | if (value == null || value.isEmpty()) {
23 | throw new IllegalArgumentException("shiro加密key检测扩展-扩展名称不能为空");
24 | }
25 | this.extensionName = value;
26 | }
27 |
28 | /**
29 | * 扩展名称检查
30 | * 作用: 让所有不设置扩展名称的扩展无法正常使用, 防止直接调用本类的其他方法, 保证扩展的正常
31 | */
32 | private void extensionNameCheck() {
33 | if (this.extensionName == null || this.extensionName.isEmpty()) {
34 | throw new IllegalArgumentException("请为该shiro加密key检测扩展-设置扩展名称");
35 | }
36 | }
37 |
38 | /**
39 | * 获取扩展名称
40 | *
41 | * @return String
42 | */
43 | @Override
44 | public String getExtensionName() {
45 | this.extensionNameCheck();
46 | return this.extensionName;
47 | }
48 |
49 | /**
50 | * 设置为扫描出了shiro加密的密钥key
51 | */
52 | protected void setShiroCipherKeyExists() {
53 | this.extensionNameCheck();
54 | this.isShiroCipherKeyExists = true;
55 | }
56 |
57 | /**
58 | * 是否存在 shiro加密的密钥key
59 | * true 表示 成功扫描出key
60 | * false 表示 未能成功扫描出key
61 | *
62 | * @return Boolean
63 | */
64 | @Override
65 | public Boolean isShiroCipherKeyExists() {
66 | this.extensionNameCheck();
67 | return this.isShiroCipherKeyExists;
68 | }
69 |
70 | /**
71 | * 设置程序使用的加密方法
72 | */
73 | protected void setEncryptMethod(String value) {
74 | this.extensionNameCheck();
75 | this.encryptMethod = value;
76 | }
77 |
78 | /**
79 | * 获取加密的方法
80 | * 例如返回: cbc, gcm 加密算法
81 | *
82 | * @return String
83 | */
84 | @Override
85 | public String getEncryptMethod() {
86 | this.extensionNameCheck();
87 | return this.encryptMethod;
88 | }
89 |
90 | /**
91 | * 设置加密的密钥key
92 | *
93 | * @param value
94 | */
95 | public void setCipherKey(String value) {
96 | this.extensionNameCheck();
97 | this.cipherKey = value;
98 | }
99 |
100 | /**
101 | * 获取加密的密钥key
102 | *
103 | * @return String
104 | */
105 | @Override
106 | public String getCipherKey() {
107 | this.extensionNameCheck();
108 | return this.cipherKey;
109 | }
110 |
111 | /**
112 | * 设置http请求与响应对象
113 | *
114 | * @param httpRequestResponse
115 | */
116 | protected void setHttpRequestResponse(IHttpRequestResponse httpRequestResponse) {
117 | this.extensionNameCheck();
118 | this.newHttpRequestResponse = httpRequestResponse;
119 | }
120 |
121 | /**
122 | * 获取http请求与响应对象
123 | *
124 | * @return IHttpRequestResponse
125 | */
126 | @Override
127 | public IHttpRequestResponse getHttpRequestResponse() {
128 | this.extensionNameCheck();
129 | return this.newHttpRequestResponse;
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/src/main/java/burp/Application/ShiroCipherKeyExtension/ExtensionInterface/IShiroCipherKeyExtension.java:
--------------------------------------------------------------------------------
1 | package burp.Application.ShiroCipherKeyExtension.ExtensionInterface;
2 |
3 | import burp.IScanIssue;
4 | import burp.IHttpRequestResponse;
5 |
6 | /**
7 | * shiro加密key扩展的公共接口
8 | * 所有的抽象类都要继承它并实现所有的接口
9 | */
10 | public interface IShiroCipherKeyExtension {
11 | String getExtensionName();
12 |
13 | Boolean isShiroCipherKeyExists();
14 |
15 | String getEncryptMethod();
16 |
17 | String getCipherKey();
18 |
19 | IHttpRequestResponse getHttpRequestResponse();
20 |
21 | IScanIssue export();
22 |
23 | void consoleExport();
24 | }
25 |
--------------------------------------------------------------------------------
/src/main/java/burp/Application/ShiroCipherKeyExtension/ExtensionMethod/ShiroCipherKeyScan.java:
--------------------------------------------------------------------------------
1 | package burp.Application.ShiroCipherKeyExtension.ExtensionMethod;
2 |
3 | import java.net.URL;
4 | import java.util.Date;
5 | import java.util.List;
6 | import java.io.IOException;
7 | import java.io.PrintWriter;
8 |
9 | import org.apache.shiro.subject.SimplePrincipalCollection;
10 |
11 | import burp.*;
12 |
13 | import burp.Bootstrap.*;
14 | import burp.Bootstrap.Encrypt.EncryptInterface;
15 |
16 | import burp.Application.ShiroCipherKeyExtension.ExtensionInterface.AShiroCipherKeyExtension;
17 | import burp.Application.ShiroFingerprintExtension.ShiroFingerprint;
18 |
19 | import burp.CustomErrorException.DiffPageException;
20 | import burp.CustomErrorException.TaskTimeoutException;
21 |
22 | public class ShiroCipherKeyScan extends AShiroCipherKeyExtension {
23 | private GlobalVariableReader globalVariableReader;
24 | private GlobalPassiveScanVariableReader globalPassiveScanVariableReader;
25 |
26 | private IBurpExtenderCallbacks callbacks;
27 | private IExtensionHelpers helpers;
28 | private PrintWriter stdout;
29 |
30 | private YamlReader yamlReader;
31 |
32 | private IHttpRequestResponse baseRequestResponse;
33 |
34 | private ShiroFingerprint shiroFingerprint;
35 |
36 | private List payloads;
37 |
38 | private EncryptInterface encryptClass;
39 |
40 | private Date startDate;
41 |
42 | private Integer maxExecutionTime;
43 |
44 | private CustomBurpHelpers customBurpHelpers;
45 |
46 | private double similarityRatio;
47 |
48 | // 相似度匹配算法,匹配失败的次数
49 | private int errorNumber = 0;
50 | private int endErrorNumber = 10;
51 |
52 | private IHttpRequestResponse shiroFingerprintHttpRequestResponse;
53 |
54 | private String rememberMeCookieName;
55 |
56 | private String responseRememberMeCookieValue;
57 |
58 | private String newRequestRememberMeCookieValue;
59 |
60 | public ShiroCipherKeyScan(GlobalVariableReader globalVariableReader,
61 | GlobalPassiveScanVariableReader globalPassiveScanVariableReader,
62 | IBurpExtenderCallbacks callbacks,
63 | YamlReader yamlReader,
64 | IHttpRequestResponse baseRequestResponse,
65 | ShiroFingerprint shiroFingerprint,
66 | List payloads,
67 | EncryptInterface encryptClass,
68 | Date startDate,
69 | Integer maxExecutionTime) throws IOException {
70 | this.globalVariableReader = globalVariableReader;
71 | this.globalPassiveScanVariableReader = globalPassiveScanVariableReader;
72 |
73 | this.callbacks = callbacks;
74 | this.helpers = callbacks.getHelpers();
75 | this.stdout = new PrintWriter(callbacks.getStdout(), true);
76 |
77 | this.yamlReader = yamlReader;
78 | this.baseRequestResponse = baseRequestResponse;
79 | this.shiroFingerprint = shiroFingerprint;
80 | this.payloads = payloads;
81 | this.encryptClass = encryptClass;
82 | this.startDate = startDate;
83 | this.maxExecutionTime = maxExecutionTime;
84 |
85 | this.customBurpHelpers = new CustomBurpHelpers(this.callbacks);
86 |
87 | this.similarityRatio = yamlReader.getDouble("application.shiroCipherKeyExtension.config.similarityRatio");
88 |
89 | this.shiroFingerprintHttpRequestResponse = this.shiroFingerprint.run().getHttpRequestResponse();
90 |
91 | this.rememberMeCookieName = this.shiroFingerprint.run().getResponseDefaultRememberMeCookieName();
92 | this.responseRememberMeCookieValue = this.shiroFingerprint.run().getResponseDefaultRememberMeCookieValue();
93 | this.newRequestRememberMeCookieValue = "";
94 |
95 | this.setExtensionName("ShiroCipherKeyScan");
96 |
97 | this.runExtension();
98 | }
99 |
100 | private void runExtension() throws IOException {
101 | if (this.payloads.size() <= 0) {
102 | throw new IllegalArgumentException("shiro加密key检测扩展-要进行爆破的payloads不能为空, 请检查");
103 | }
104 |
105 | byte[] exp = this.encryptClass.getBytes(new SimplePrincipalCollection());
106 |
107 | // 加密key检测
108 | for (String key : this.payloads) {
109 | // 这个参数为true说明插件已经被卸载,退出所有任务,避免继续扫描
110 | if (this.globalVariableReader.getBooleanData("isExtensionUnload")) {
111 | return;
112 | }
113 |
114 | // 说明别的线程已经扫描到shiro key了,可以退出这个线程了
115 | if (this.globalPassiveScanVariableReader.getBooleanData("isEndShiroCipherKeyTask")) {
116 | return;
117 | }
118 |
119 | // 说明检测到shiro key了
120 | if (this.isShiroCipherKeyExists()) {
121 | return;
122 | }
123 |
124 | // 如果 相似度匹配算法,匹配失败的次数,超过10次,那么就可以退出了
125 | // 因为这种情况下,大概率触发waf规则了, 那么就没必要跑剩下的了
126 | if (this.errorNumber >= this.endErrorNumber) {
127 | // 抛异常结束任务
128 | throw new DiffPageException("shiro key scan too many errors");
129 | }
130 |
131 | // 判断程序是否运行超时
132 | int startTime = CustomHelpers.getSecondTimestamp(this.startDate);
133 | int currentTime = CustomHelpers.getSecondTimestamp(new Date());
134 | int runTime = currentTime - startTime;
135 | if (runTime >= this.maxExecutionTime) {
136 | throw new TaskTimeoutException("shiro key scan task timeout");
137 | }
138 |
139 | this.cipherKeyDetection(key, exp);
140 | }
141 | }
142 |
143 | /**
144 | * 加密key检测
145 | *
146 | * @param key 要爆破的key
147 | * @param exp 加密的算法类byte
148 | */
149 | private void cipherKeyDetection(String key, byte[] exp) {
150 | int shiroFingerprintCookieRememberMeNumber = this.getHttpCookieRememberMeNumber(this.shiroFingerprintHttpRequestResponse);
151 | String shiroFingerprintHttpBody = this.customBurpHelpers.getHttpResponseBody(this.shiroFingerprintHttpRequestResponse.getResponse());
152 |
153 | // 使用当前可能正确的key-发送可能被此shiro框架成功解密的请求
154 | String correctRememberMe = this.encryptClass.encrypt(key, exp);
155 | IHttpRequestResponse newHttpRequestResponse1 = this.getNewHttpRequestResponse(correctRememberMe, 3);
156 |
157 | // 判断shiro指纹的请求与当前可能正确key的请求相似度是否差不多一致
158 | String newHttpBody1 = this.customBurpHelpers.getHttpResponseBody(newHttpRequestResponse1.getResponse());
159 | double htmlSimilarityRatio1 = DiffPage.getRatio(shiroFingerprintHttpBody, newHttpBody1);
160 | if (this.similarityRatio > htmlSimilarityRatio1) {
161 | this.errorNumber++;
162 | return;
163 | }
164 |
165 | // 判断当前可能正确的请求-是否被此shiro框架解密
166 | int newHttpCookieRememberMeNumber1 = this.getHttpCookieRememberMeNumber(newHttpRequestResponse1);
167 | if (newHttpCookieRememberMeNumber1 >= shiroFingerprintCookieRememberMeNumber) {
168 | return;
169 | }
170 |
171 | // 二次验证-这样可以减少因为waf造成的大量误报
172 | // 使用一个必定错误的key-发送一个肯定不会被此shiro框架成功解密的请求
173 | // 密钥 errorKey 然后 aes 加密 == U2FsdGVkX19xgIigFNCsuy2aXwtskOnJV8rQkrT9D5Y=
174 | String errorKey = "U2FsdGVkX19xgIigFNCsuy2aXwtskOnJV8rQkrT9D5Y=";
175 | String errorRememberMe = this.encryptClass.encrypt(errorKey, exp);
176 | IHttpRequestResponse newHttpRequestResponse2 = this.getNewHttpRequestResponse(errorRememberMe, 3);
177 |
178 | // 判断shiro指纹的请求与当前必定错误的请求相似度是否差不多一致
179 | String newHttpBody2 = this.customBurpHelpers.getHttpResponseBody(newHttpRequestResponse2.getResponse());
180 | double htmlSimilarityRatio2 = DiffPage.getRatio(shiroFingerprintHttpBody, newHttpBody2);
181 | if (this.similarityRatio > htmlSimilarityRatio2) {
182 | this.errorNumber++;
183 | return;
184 | }
185 |
186 | // 判断当前必定错误的请求-是否被此shiro框架解密
187 | int newHttpCookieRememberMeNumber2 = this.getHttpCookieRememberMeNumber(newHttpRequestResponse2);
188 | if (newHttpCookieRememberMeNumber2 < shiroFingerprintCookieRememberMeNumber) {
189 | return;
190 | }
191 |
192 | // 设置问题详情
193 | this.setIssuesDetail(newHttpRequestResponse1, key, this.encryptClass.getName(), correctRememberMe);
194 | }
195 |
196 | /**
197 | * 获取http cookie 记住我出现的次数
198 | *
199 | * @param httpRequestResponse
200 | * @return
201 | */
202 | private int getHttpCookieRememberMeNumber(IHttpRequestResponse httpRequestResponse) {
203 | int number = 0;
204 | for (ICookie c : this.helpers.analyzeResponse(httpRequestResponse.getResponse()).getCookies()) {
205 | if (c.getName().equals(this.rememberMeCookieName)) {
206 | if (c.getValue().equals(this.responseRememberMeCookieValue) || c.getValue().equals("deleteMe")) {
207 | number++;
208 | }
209 | }
210 | }
211 | return number;
212 | }
213 |
214 | /**
215 | * 获取新的http请求响应
216 | *
217 | * @param rememberMe
218 | * @param remainingRunNumber 剩余运行次数
219 | * @return IHttpRequestResponse
220 | */
221 | private IHttpRequestResponse getNewHttpRequestResponse(String rememberMe, int remainingRunNumber) {
222 | IHttpService httpService = this.baseRequestResponse.getHttpService();
223 | IParameter newParameter = this.helpers.buildParameter(
224 | this.rememberMeCookieName,
225 | rememberMe,
226 | (byte) 2);
227 | byte[] newRequest = this.helpers.updateParameter(this.baseRequestResponse.getRequest(), newParameter);
228 | IHttpRequestResponse newHttpRequestResponse = this.callbacks.makeHttpRequest(httpService, newRequest);
229 |
230 | if (remainingRunNumber <= 1) {
231 | return newHttpRequestResponse;
232 | }
233 | remainingRunNumber--;
234 |
235 | String shiroFingerprintHttpBody = this.customBurpHelpers.getHttpResponseBody(this.shiroFingerprintHttpRequestResponse.getResponse());
236 | String newHttpBody = this.customBurpHelpers.getHttpResponseBody(newHttpRequestResponse.getResponse());
237 |
238 | double htmlSimilarityRatio = DiffPage.getRatio(shiroFingerprintHttpBody, newHttpBody);
239 | if (this.similarityRatio > htmlSimilarityRatio) {
240 | return this.getNewHttpRequestResponse(rememberMe, remainingRunNumber);
241 | }
242 |
243 | return newHttpRequestResponse;
244 | }
245 |
246 | /**
247 | * 设置问题详情
248 | */
249 | private void setIssuesDetail(
250 | IHttpRequestResponse httpRequestResponse,
251 | String key,
252 | String encryptMethod,
253 | String correctRememberMe) {
254 | this.setShiroCipherKeyExists();
255 | this.setCipherKey(key);
256 | this.setEncryptMethod(encryptMethod);
257 | this.setHttpRequestResponse(httpRequestResponse);
258 | this.setNewRequestRememberMeCookieValue(correctRememberMe);
259 | }
260 |
261 | private void setNewRequestRememberMeCookieValue(String value) {
262 | this.newRequestRememberMeCookieValue = value;
263 | }
264 |
265 | private String getNewRequestRememberMeCookieValue() {
266 | return this.newRequestRememberMeCookieValue;
267 | }
268 |
269 | @Override
270 | public IScanIssue export() {
271 | if (!this.isShiroCipherKeyExists()) {
272 | return null;
273 | }
274 |
275 | IHttpRequestResponse newHttpRequestResponse = this.getHttpRequestResponse();
276 | URL newHttpRequestUrl = this.helpers.analyzeRequest(newHttpRequestResponse).getUrl();
277 |
278 | String str1 = String.format("
=============ShiroCipherKeyDetail============
");
279 | String str2 = String.format("ExtensionMethod: %s
", this.getExtensionName());
280 | String str3 = String.format("EncryptMethod: %s
", this.encryptClass.getName());
281 | String str4 = String.format("CookieName: %s
", this.rememberMeCookieName);
282 | String str5 = String.format("CookieValue: %s
", this.getNewRequestRememberMeCookieValue());
283 | String str6 = String.format("ShiroCipherKey: %s
", this.getCipherKey());
284 | String str7 = String.format("=====================================
");
285 |
286 | String detail = str1 + str2 + str3 + str4 + str5 + str6 + str7;
287 |
288 | String shiroCipherKeyIssueName = this.yamlReader.getString("application.shiroCipherKeyExtension.config.issueName");
289 |
290 | return new CustomScanIssue(
291 | newHttpRequestUrl,
292 | shiroCipherKeyIssueName,
293 | 0,
294 | "High",
295 | "Certain",
296 | null,
297 | null,
298 | detail,
299 | null,
300 | new IHttpRequestResponse[]{newHttpRequestResponse},
301 | newHttpRequestResponse.getHttpService()
302 | );
303 | }
304 |
305 | @Override
306 | public void consoleExport() {
307 | if (!this.isShiroCipherKeyExists()) {
308 | return;
309 | }
310 |
311 | IHttpRequestResponse newHttpRequestResponse = this.getHttpRequestResponse();
312 | URL newHttpRequestUrl = this.helpers.analyzeRequest(newHttpRequestResponse).getUrl();
313 | String newHttpRequestMethod = this.helpers.analyzeRequest(newHttpRequestResponse.getRequest()).getMethod();
314 | int newHttpResponseStatusCode = this.helpers.analyzeResponse(newHttpRequestResponse.getResponse()).getStatusCode();
315 |
316 | this.stdout.println("");
317 | this.stdout.println("===========shiro加密key详情============");
318 | this.stdout.println("你好呀~ (≧ω≦*)喵~");
319 | this.stdout.println("这边检测到有一个站点使用了 shiro框架 喵~");
320 | this.stdout.println(String.format(
321 | "注意: 该检测方法, 正确的时候响应包的 %s 会消失, 这表示当前key是正确的",
322 | this.rememberMeCookieName));
323 | this.stdout.println(String.format("负责检测的插件: %s", this.getExtensionName()));
324 | this.stdout.println(String.format("使用的加密方法: %s", this.encryptClass.getName()));
325 | this.stdout.println(String.format("url: %s", newHttpRequestUrl));
326 | this.stdout.println(String.format("请求方法: %s", newHttpRequestMethod));
327 | this.stdout.println(String.format("页面http状态: %d", newHttpResponseStatusCode));
328 | this.stdout.println(String.format("对应的Cookie键: %s", this.rememberMeCookieName));
329 | this.stdout.println(String.format("对应的Cookie值: %s", this.getNewRequestRememberMeCookieValue()));
330 | this.stdout.println(String.format("Shiro加密key: %s", this.getCipherKey()));
331 | this.stdout.println("详情请查看-Burp Scanner模块-Issue activity界面");
332 | this.stdout.println("===================================");
333 | this.stdout.println("");
334 | }
335 | }
336 |
--------------------------------------------------------------------------------
/src/main/java/burp/Application/ShiroCipherKeyExtension/ShiroCipherKey.java:
--------------------------------------------------------------------------------
1 | package burp.Application.ShiroCipherKeyExtension;
2 |
3 | import java.util.Date;
4 | import java.util.List;
5 | import java.io.PrintWriter;
6 | import java.lang.reflect.Constructor;
7 | import java.lang.reflect.InvocationTargetException;
8 |
9 | import burp.Bootstrap.GlobalPassiveScanVariableReader;
10 | import burp.IHttpRequestResponse;
11 | import burp.IBurpExtenderCallbacks;
12 |
13 | import burp.Bootstrap.YamlReader;
14 | import burp.Bootstrap.GlobalVariableReader;
15 | import burp.Bootstrap.Encrypt.CbcEncrypt;
16 | import burp.Bootstrap.Encrypt.GcmEncrypt;
17 | import burp.Bootstrap.Encrypt.EncryptInterface;
18 |
19 | import burp.Application.ShiroFingerprintExtension.ShiroFingerprint;
20 |
21 | import burp.Application.ShiroCipherKeyExtension.ExtensionInterface.IShiroCipherKeyExtension;
22 |
23 | public class ShiroCipherKey implements Runnable {
24 | private GlobalVariableReader globalVariableReader;
25 | private GlobalPassiveScanVariableReader globalPassiveScanVariableReader;
26 |
27 | private IBurpExtenderCallbacks callbacks;
28 |
29 | private YamlReader yamlReader;
30 |
31 | private IHttpRequestResponse baseRequestResponse;
32 |
33 | private ShiroFingerprint shiroFingerprint;
34 |
35 | private String callClassName;
36 |
37 | private List payloadList;
38 |
39 | /**
40 | * 该模块启动日期
41 | */
42 | private final Date startDate = new Date();
43 |
44 | /**
45 | * 程序最大执行时间,单位为秒
46 | * 注意: 会根据payload的添加而添加
47 | */
48 | private final int maxExecutionTime = 60;
49 |
50 | public ShiroCipherKey(GlobalVariableReader globalVariableReader,
51 | GlobalPassiveScanVariableReader globalPassiveScanVariableReader,
52 | IBurpExtenderCallbacks callbacks,
53 | YamlReader yamlReader,
54 | IHttpRequestResponse baseRequestResponse,
55 | ShiroFingerprint shiroFingerprint,
56 | String callClassName,
57 | List payloadList) {
58 | this.globalVariableReader = globalVariableReader;
59 | this.globalPassiveScanVariableReader = globalPassiveScanVariableReader;
60 |
61 | this.callbacks = callbacks;
62 |
63 | this.yamlReader = yamlReader;
64 |
65 | this.baseRequestResponse = baseRequestResponse;
66 |
67 | this.shiroFingerprint = shiroFingerprint;
68 |
69 | this.callClassName = callClassName;
70 |
71 | this.payloadList = payloadList;
72 | }
73 |
74 | @Override
75 | public void run() {
76 | if (callClassName == null || callClassName.length() <= 0) {
77 | throw new IllegalArgumentException("Application.ShiroCipherKeyExtension-请输入要调用的插件名称");
78 | }
79 |
80 | if (this.payloadList.size() == 0) {
81 | throw new IllegalArgumentException("Application.ShiroCipherKeyExtension-获取的payloads为空,无法正常运行");
82 | }
83 |
84 | try {
85 | Class c = Class.forName("burp.Application.ShiroCipherKeyExtension.ExtensionMethod." + callClassName);
86 | Constructor cConstructor = c.getConstructor(
87 | GlobalVariableReader.class,
88 | GlobalPassiveScanVariableReader.class,
89 | IBurpExtenderCallbacks.class,
90 | YamlReader.class,
91 | IHttpRequestResponse.class,
92 | ShiroFingerprint.class,
93 | List.class,
94 | EncryptInterface.class,
95 | Date.class,
96 | Integer.class);
97 |
98 | Boolean isScanCbcEncrypt = this.yamlReader.getBoolean("application.shiroCipherKeyExtension.config.isScanCbcEncrypt");
99 | if (isScanCbcEncrypt) {
100 | if (this.globalPassiveScanVariableReader.getBooleanData("isEndShiroCipherKeyTask")) {
101 | return;
102 | }
103 |
104 | IShiroCipherKeyExtension shiroCipherKey1 = (IShiroCipherKeyExtension) cConstructor.newInstance(
105 | this.globalVariableReader,
106 | this.globalPassiveScanVariableReader,
107 | this.callbacks,
108 | this.yamlReader,
109 | this.baseRequestResponse,
110 | this.shiroFingerprint,
111 | this.payloadList,
112 | new CbcEncrypt(),
113 | this.startDate,
114 | this.getMaxExecutionTime());
115 |
116 | if (shiroCipherKey1.isShiroCipherKeyExists()) {
117 | this.globalPassiveScanVariableReader.putBooleanData("isEndShiroCipherKeyTask", true);
118 | this.globalPassiveScanVariableReader.putShiroCipherKeyExtensionData("shiroCipherKey", shiroCipherKey1);
119 | }
120 | }
121 |
122 | Boolean isScanGcmEncrypt = this.yamlReader.getBoolean("application.shiroCipherKeyExtension.config.isScanGcmEncrypt");
123 | if (isScanGcmEncrypt) {
124 | if (this.globalPassiveScanVariableReader.getBooleanData("isEndShiroCipherKeyTask")) {
125 | return;
126 | }
127 |
128 | IShiroCipherKeyExtension shiroCipherKey2 = (IShiroCipherKeyExtension) cConstructor.newInstance(
129 | this.globalVariableReader,
130 | this.globalPassiveScanVariableReader,
131 | this.callbacks,
132 | this.yamlReader,
133 | this.baseRequestResponse,
134 | this.shiroFingerprint,
135 | this.payloadList,
136 | new GcmEncrypt(),
137 | this.startDate,
138 | this.getMaxExecutionTime());
139 |
140 | if (shiroCipherKey2.isShiroCipherKeyExists()) {
141 | this.globalPassiveScanVariableReader.putBooleanData("isEndShiroCipherKeyTask", true);
142 | this.globalPassiveScanVariableReader.putShiroCipherKeyExtensionData("shiroCipherKey", shiroCipherKey2);
143 | }
144 | }
145 | } catch (ClassNotFoundException | NoSuchMethodException | InstantiationException | IllegalAccessException | InvocationTargetException e) {
146 | e.printStackTrace(new PrintWriter(this.callbacks.getStderr(), true));
147 | }
148 | }
149 |
150 | /**
151 | * 程序最大执行时间,单位为秒
152 | * 会根据payload的添加而添加
153 | *
154 | * @return
155 | */
156 | private Integer getMaxExecutionTime() {
157 | Integer maxExecutionTime = this.maxExecutionTime;
158 | maxExecutionTime += this.payloadList.size() * 6;
159 | return maxExecutionTime;
160 | }
161 | }
--------------------------------------------------------------------------------
/src/main/java/burp/Application/ShiroCipherKeyExtension/ShiroCipherKeyThread.java:
--------------------------------------------------------------------------------
1 | package burp.Application.ShiroCipherKeyExtension;
2 |
3 | import java.util.List;
4 | import java.util.ArrayList;
5 |
6 | import burp.IHttpRequestResponse;
7 | import burp.IBurpExtenderCallbacks;
8 |
9 | import burp.Bootstrap.YamlReader;
10 | import burp.Bootstrap.CustomHelpers;
11 | import burp.Bootstrap.GlobalVariableReader;
12 | import burp.Bootstrap.GlobalPassiveScanVariableReader;
13 |
14 | import burp.Application.ShiroFingerprintExtension.ShiroFingerprint;
15 |
16 | public class ShiroCipherKeyThread {
17 | private List threadPool = new ArrayList<>();
18 |
19 | public ShiroCipherKeyThread(GlobalVariableReader globalVariableReader,
20 | GlobalPassiveScanVariableReader globalPassiveScanVariableReader,
21 | IBurpExtenderCallbacks callbacks,
22 | YamlReader yamlReader,
23 | IHttpRequestResponse baseRequestResponse,
24 | ShiroFingerprint shiroFingerprint,
25 | String callClassName) {
26 | // 是否结束shiro加密key扩展任务
27 | // 用于多线程,跑到key,把程序快速退出去,避免资源浪费与卡顿
28 | // true = 结束, false = 不结束
29 | globalPassiveScanVariableReader.putBooleanData("isEndShiroCipherKeyTask", false);
30 |
31 | if (callClassName == null || callClassName.length() <= 0) {
32 | throw new IllegalArgumentException("Application.ShiroCipherKeyExtension-请输入要调用的插件名称");
33 | }
34 |
35 | List payloads = yamlReader.getStringList("application.shiroCipherKeyExtension.config.payloads");
36 | if (payloads.size() == 0) {
37 | throw new IllegalArgumentException("Application.ShiroCipherKeyExtension-获取的payloads为空,无法正常运行");
38 | }
39 |
40 | // payload按照配置线程数分块
41 | Integer shiroCipherKeyThreadTotal = yamlReader.getInteger("application.shiroCipherKeyExtension.config.threadTotal");
42 | List> payloadChunk = CustomHelpers.listChunkSplit(payloads, shiroCipherKeyThreadTotal);
43 |
44 | // 建立线程池
45 | for (List payloadList : payloadChunk) {
46 | this.threadPool.add(new Thread(
47 | new ShiroCipherKey(
48 | globalVariableReader, globalPassiveScanVariableReader, callbacks,
49 | yamlReader, baseRequestResponse, shiroFingerprint,
50 | callClassName, payloadList)
51 | ));
52 | }
53 |
54 | // 线程启动
55 | for (int i = 0; i < this.threadPool.size(); i++) {
56 | this.threadPool.get(i).start();
57 | }
58 | }
59 |
60 | /**
61 | * 判断线程任务是否执行完毕
62 | *
63 | * @return
64 | */
65 | public Boolean isTaskComplete() {
66 | // 开启的线程总数
67 | Integer threadCcount = this.threadPool.size();
68 |
69 | // 线程完成数量
70 | Integer threadNum = 0;
71 |
72 | for (Thread t : this.threadPool) {
73 | if (!t.isAlive()) {
74 | threadNum++;
75 | }
76 | }
77 |
78 | if (threadNum.equals(threadCcount)) {
79 | return true;
80 | }
81 |
82 | return false;
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/java/burp/Application/ShiroFingerprintExtension/ExtensionInterface/AShiroFingerprintExtension.java:
--------------------------------------------------------------------------------
1 | package burp.Application.ShiroFingerprintExtension.ExtensionInterface;
2 |
3 | import burp.IHttpRequestResponse;
4 |
5 | /**
6 | * shiro指纹扩展的抽象类
7 | * 所有的shiro指纹检测的方法都要继承它并实现所有的接口
8 | */
9 | public abstract class AShiroFingerprintExtension implements IShiroFingerprintExtension {
10 | private String extensionName = "";
11 |
12 | private Boolean isRunExtension = false;
13 |
14 | private Boolean isShiroFingerprint = false;
15 |
16 | private String requestRememberMeCookieName = "";
17 | private String requestRememberMeCookieValue = "";
18 |
19 | private String responseRememberMeCookieName = "";
20 | private String responseRememberMeCookieValue = "";
21 |
22 | private IHttpRequestResponse newHttpRequestResponse;
23 |
24 | /**
25 | * 设置扩展名称 (必须的)
26 | *
27 | * @param value
28 | */
29 | protected void setExtensionName(String value) {
30 | if (value == null || value.isEmpty()) {
31 | throw new IllegalArgumentException("shiro指纹扫描扩展-扩展名称不能为空");
32 | }
33 | this.extensionName = value;
34 | }
35 |
36 | /**
37 | * 扩展名称检查
38 | * 作用: 让所有不设置扩展名称的扩展无法正常使用, 防止直接调用本类的其他方法, 保证扩展的正常
39 | */
40 | private void extensionNameCheck() {
41 | if (this.extensionName == null || this.extensionName.isEmpty()) {
42 | throw new IllegalArgumentException("请为该shiro指纹扫描扩展-设置扩展名称");
43 | }
44 | }
45 |
46 | /**
47 | * 获取扩展名称
48 | *
49 | * @return String
50 | */
51 | @Override
52 | public String getExtensionName() {
53 | this.extensionNameCheck();
54 | return this.extensionName;
55 | }
56 |
57 | /**
58 | * 注册插件 (必须的)
59 | * 扩展在运行之前必须调用该接口注册, 否则将无法调用本类的其他方法
60 | */
61 | protected void registerExtension() {
62 | this.extensionNameCheck();
63 | this.isRunExtension = true;
64 | }
65 |
66 | /**
67 | * 注册扩展检查
68 | * 作用: 让所有未调用方法 registerExtension() 的接口, 无法使用本类的其他方法, 保证扩展的正常
69 | */
70 | private void registerExtensionCheck() {
71 | if (!this.isRunExtension) {
72 | throw new IllegalArgumentException("注意: 该指纹模块未注册,无法使用");
73 | }
74 | }
75 |
76 | /**
77 | * 是否运行扩展
78 | * true 运行
79 | * false 不运行
80 | *
81 | * @return Boolean
82 | */
83 | @Override
84 | public Boolean isRunExtension() {
85 | return this.isRunExtension;
86 | }
87 |
88 | /**
89 | * 设置为shiro指纹
90 | */
91 | protected void setShiroFingerprint() {
92 | this.registerExtensionCheck();
93 | this.isShiroFingerprint = true;
94 | }
95 |
96 | /**
97 | * 是否shiro框架
98 | *
99 | * @return Boolean
100 | */
101 | @Override
102 | public Boolean isShiroFingerprint() {
103 | this.registerExtensionCheck();
104 | return this.isShiroFingerprint;
105 | }
106 |
107 | /**
108 | * 设置请求默认“记住我”的Cookie名
109 | *
110 | * @param value
111 | */
112 | protected void setRequestDefaultRememberMeCookieName(String value) {
113 | this.registerExtensionCheck();
114 | this.requestRememberMeCookieName = value;
115 | }
116 |
117 | /**
118 | * 获取请求默认“记住我”的Cookie名
119 | *
120 | * @return String
121 | */
122 | @Override
123 | public String getRequestDefaultRememberMeCookieName() {
124 | this.registerExtensionCheck();
125 | return this.requestRememberMeCookieName;
126 | }
127 |
128 | /**
129 | * 设置请求默认“记住我”的Cookie值
130 | *
131 | * @param value
132 | */
133 | protected void setRequestDefaultRememberMeCookieValue(String value) {
134 | this.registerExtensionCheck();
135 | this.requestRememberMeCookieValue = value;
136 | }
137 |
138 | /**
139 | * 获取请求默认“记住我”的Cookie值
140 | *
141 | * @return String
142 | */
143 | @Override
144 | public String getRequestDefaultRememberMeCookieValue() {
145 | this.registerExtensionCheck();
146 | return this.requestRememberMeCookieValue;
147 | }
148 |
149 | /**
150 | * 设置响应默认“记住我”的Cookie名称
151 | *
152 | * @param value
153 | */
154 | protected void setResponseDefaultRememberMeCookieName(String value) {
155 | this.registerExtensionCheck();
156 | this.responseRememberMeCookieName = value;
157 | }
158 |
159 | /**
160 | * 获取响应默认“记住我”的Cookie名称
161 | *
162 | * @return String
163 | */
164 | @Override
165 | public String getResponseDefaultRememberMeCookieName() {
166 | this.registerExtensionCheck();
167 | return this.responseRememberMeCookieName;
168 | }
169 |
170 | /**
171 | * 设置响应默认的“记住我”Cookie值
172 | *
173 | * @param value
174 | */
175 | protected void setResponseDefaultRememberMeCookieValue(String value) {
176 | this.registerExtensionCheck();
177 | this.responseRememberMeCookieValue = value;
178 | }
179 |
180 | /**
181 | * 获取设置响应默认的“记住我”Cookie值
182 | *
183 | * @return
184 | */
185 | @Override
186 | public String getResponseDefaultRememberMeCookieValue() {
187 | this.registerExtensionCheck();
188 | return this.responseRememberMeCookieValue;
189 | }
190 |
191 | /**
192 | * 设置http请求与响应对象
193 | *
194 | * @param httpRequestResponse
195 | */
196 | protected void setHttpRequestResponse(IHttpRequestResponse httpRequestResponse) {
197 | this.registerExtensionCheck();
198 | this.newHttpRequestResponse = httpRequestResponse;
199 | }
200 |
201 | /**
202 | * 获取http请求与响应对象
203 | *
204 | * @return IHttpRequestResponse
205 | */
206 | @Override
207 | public IHttpRequestResponse getHttpRequestResponse() {
208 | this.registerExtensionCheck();
209 | return this.newHttpRequestResponse;
210 | }
211 | }
--------------------------------------------------------------------------------
/src/main/java/burp/Application/ShiroFingerprintExtension/ExtensionInterface/IShiroFingerprintExtension.java:
--------------------------------------------------------------------------------
1 | package burp.Application.ShiroFingerprintExtension.ExtensionInterface;
2 |
3 | import burp.IScanIssue;
4 | import burp.IHttpRequestResponse;
5 |
6 | /**
7 | * shiro指纹扩展的公共接口
8 | * 所有的抽象类都要继承它并实现所有的接口
9 | */
10 | public interface IShiroFingerprintExtension {
11 | String getExtensionName();
12 |
13 | Boolean isRunExtension();
14 |
15 | Boolean isShiroFingerprint();
16 |
17 | String getRequestDefaultRememberMeCookieName();
18 |
19 | String getRequestDefaultRememberMeCookieValue();
20 |
21 | String getResponseDefaultRememberMeCookieName();
22 |
23 | String getResponseDefaultRememberMeCookieValue();
24 |
25 | IHttpRequestResponse getHttpRequestResponse();
26 |
27 | IScanIssue export();
28 |
29 | void consoleExport();
30 | }
31 |
--------------------------------------------------------------------------------
/src/main/java/burp/Application/ShiroFingerprintExtension/ExtensionMethod/ShiroFingerprint1.java:
--------------------------------------------------------------------------------
1 | package burp.Application.ShiroFingerprintExtension.ExtensionMethod;
2 |
3 | import burp.*;
4 | import burp.Application.ShiroFingerprintExtension.ExtensionInterface.AShiroFingerprintExtension;
5 | import burp.Bootstrap.YamlReader;
6 |
7 | import java.io.PrintWriter;
8 | import java.net.URL;
9 |
10 | public class ShiroFingerprint1 extends AShiroFingerprintExtension {
11 | private IBurpExtenderCallbacks callbacks;
12 | private IExtensionHelpers helpers;
13 |
14 | private YamlReader yamlReader;
15 |
16 | private IHttpRequestResponse baseRequestResponse;
17 |
18 | private String rememberMeCookieName = "rememberMe";
19 | private String rememberMeCookieValue = "1";
20 |
21 | public ShiroFingerprint1(IBurpExtenderCallbacks callbacks, YamlReader yamlReader, IHttpRequestResponse baseRequestResponse) {
22 | this.callbacks = callbacks;
23 | this.helpers = callbacks.getHelpers();
24 |
25 | this.yamlReader = yamlReader;
26 |
27 | this.baseRequestResponse = baseRequestResponse;
28 |
29 | this.setExtensionName("ShiroFingerprint1");
30 |
31 | this.runConditionCheck();
32 | }
33 |
34 | private void runConditionCheck() {
35 | this.registerExtension();
36 | }
37 |
38 | public void runExtension() {
39 | if (!this.isRunExtension()) {
40 | return;
41 | }
42 |
43 | IHttpService httpService = this.baseRequestResponse.getHttpService();
44 |
45 | IParameter newParameter = this.helpers.buildParameter(this.rememberMeCookieName, this.rememberMeCookieValue, (byte) 2);
46 | byte[] newRequest = this.helpers.updateParameter(this.baseRequestResponse.getRequest(), newParameter);
47 | IHttpRequestResponse newHttpRequestResponse = this.callbacks.makeHttpRequest(httpService, newRequest);
48 |
49 | this.setHttpRequestResponse(newHttpRequestResponse);
50 |
51 | for (ICookie c : this.helpers.analyzeResponse(newHttpRequestResponse.getResponse()).getCookies()) {
52 | if (c.getName().equals(this.rememberMeCookieName)) {
53 | this.setShiroFingerprint();
54 |
55 | this.setRequestDefaultRememberMeCookieName(this.rememberMeCookieName);
56 | this.setRequestDefaultRememberMeCookieValue(this.rememberMeCookieValue);
57 |
58 | this.setResponseDefaultRememberMeCookieName(c.getName());
59 | this.setResponseDefaultRememberMeCookieValue(c.getValue());
60 | break;
61 | }
62 | }
63 | }
64 |
65 | @Override
66 | public IScanIssue export() {
67 | if (!this.isRunExtension()) {
68 | return null;
69 | }
70 |
71 | if (!this.isShiroFingerprint()) {
72 | return null;
73 | }
74 |
75 | IHttpRequestResponse newHttpRequestResponse = this.getHttpRequestResponse();
76 | URL newHttpRequestUrl = this.helpers.analyzeRequest(newHttpRequestResponse).getUrl();
77 |
78 | String str1 = String.format("
============ShiroFingerprintDetail============
");
79 | String str2 = String.format("ExtensionMethod: %s
", this.getExtensionName());
80 | String str3 = String.format("RequestCookiePayload: %s=%s
",
81 | this.getRequestDefaultRememberMeCookieName(),
82 | this.getRequestDefaultRememberMeCookieValue());
83 | String str4 = String.format("ResponseReturnCookie: %s=%s
",
84 | this.getResponseDefaultRememberMeCookieName(),
85 | this.getResponseDefaultRememberMeCookieValue());
86 | String str5 = String.format("=====================================
");
87 |
88 | String detail = str1 + str2 + str3 + str4 + str5;
89 |
90 | String shiroFingerprintIssueName = this.yamlReader.getString("application.shiroFingerprintExtension.config.issueName");
91 |
92 | return new CustomScanIssue(
93 | newHttpRequestUrl,
94 | shiroFingerprintIssueName,
95 | 0,
96 | "Information",
97 | "Certain",
98 | null,
99 | null,
100 | detail,
101 | null,
102 | new IHttpRequestResponse[]{newHttpRequestResponse},
103 | newHttpRequestResponse.getHttpService()
104 | );
105 | }
106 |
107 | @Override
108 | public void consoleExport() {
109 | if (!this.isRunExtension()) {
110 | return;
111 | }
112 |
113 | if (!this.isShiroFingerprint()) {
114 | return;
115 | }
116 |
117 | IHttpRequestResponse newHttpRequestResponse = this.getHttpRequestResponse();
118 | URL newHttpRequestUrl = this.helpers.analyzeRequest(newHttpRequestResponse).getUrl();
119 | String newHttpRequestMethod = this.helpers.analyzeRequest(newHttpRequestResponse.getRequest()).getMethod();
120 | int newHttpResponseStatusCode = this.helpers.analyzeResponse(newHttpRequestResponse.getResponse()).getStatusCode();
121 |
122 | PrintWriter stdout = new PrintWriter(this.callbacks.getStdout(), true);
123 |
124 | stdout.println("");
125 | stdout.println("==============shiro指纹详情============");
126 | stdout.println("你好呀~ (≧ω≦*)喵~");
127 | stdout.println("这边检测到有一个站点使用了 shiro框架 喵~");
128 | stdout.println(String.format("负责检测的插件: %s", this.getExtensionName()));
129 | stdout.println(String.format("url: %s", newHttpRequestUrl));
130 | stdout.println(String.format("请求方法: %s", newHttpRequestMethod));
131 | stdout.println(String.format("页面http状态: %d", newHttpResponseStatusCode));
132 | stdout.println(String.format("请求对应的cookie: %s=%s",
133 | this.getRequestDefaultRememberMeCookieName(),
134 | this.getRequestDefaultRememberMeCookieValue()));
135 | stdout.println(String.format("响应返回的cookie: %s=%s",
136 | this.getResponseDefaultRememberMeCookieName(),
137 | this.getResponseDefaultRememberMeCookieValue()));
138 | stdout.println("详情请查看-Burp Scanner模块-Issue activity界面");
139 | stdout.println("===================================");
140 | stdout.println("");
141 | }
142 | }
143 |
--------------------------------------------------------------------------------
/src/main/java/burp/Application/ShiroFingerprintExtension/ExtensionMethod/ShiroFingerprint2.java:
--------------------------------------------------------------------------------
1 | package burp.Application.ShiroFingerprintExtension.ExtensionMethod;
2 |
3 | import burp.*;
4 | import burp.Application.ShiroFingerprintExtension.ExtensionInterface.AShiroFingerprintExtension;
5 | import burp.Bootstrap.YamlReader;
6 |
7 | import java.io.PrintWriter;
8 | import java.net.URL;
9 |
10 | public class ShiroFingerprint2 extends AShiroFingerprintExtension {
11 | private IBurpExtenderCallbacks callbacks;
12 | private IExtensionHelpers helpers;
13 |
14 | private YamlReader yamlReader;
15 |
16 | private IHttpRequestResponse baseRequestResponse;
17 |
18 | private String rememberMeCookieValue = "2";
19 |
20 | public ShiroFingerprint2(IBurpExtenderCallbacks callbacks, YamlReader yamlReader, IHttpRequestResponse baseRequestResponse) {
21 | this.callbacks = callbacks;
22 | this.helpers = callbacks.getHelpers();
23 |
24 | this.yamlReader = yamlReader;
25 |
26 | this.baseRequestResponse = baseRequestResponse;
27 |
28 | this.setExtensionName("ShiroFingerprint2");
29 |
30 | this.runConditionCheck();
31 | }
32 |
33 | /**
34 | * 原始请求响应返回 cookie 的 value 带了 deleteMe 则进入该流程
35 | */
36 | private void runConditionCheck() {
37 | for (ICookie c : this.helpers.analyzeResponse(this.baseRequestResponse.getResponse()).getCookies()) {
38 | if (c.getValue().equals("deleteMe")) {
39 | this.registerExtension();
40 | break;
41 | }
42 | }
43 | }
44 |
45 | public void runExtension() {
46 | if (!this.isRunExtension()) {
47 | return;
48 | }
49 |
50 | // 先保存一个基础的请求响应
51 | this.setHttpRequestResponse(this.baseRequestResponse);
52 |
53 | for (ICookie c : this.helpers.analyzeResponse(this.baseRequestResponse.getResponse()).getCookies()) {
54 | if (c.getValue().equals("deleteMe")) {
55 | this.setShiroFingerprint();
56 |
57 | // 通过返回包的key重新构造一个请求发过去
58 | // 这样二次确认过的请求响应, 可以获得最真实的结果
59 | IHttpRequestResponse newHttpRequestResponse = this.getNewHttpRequestResponse(
60 | c.getName(),
61 | this.rememberMeCookieValue);
62 |
63 | // 二次确认的请求确定是shiro框架了
64 | // 保存这个最真实的结果, 覆盖上面那个基础的请求响应
65 | this.setHttpRequestResponse(newHttpRequestResponse);
66 |
67 | this.setRequestDefaultRememberMeCookieName(c.getName());
68 | this.setRequestDefaultRememberMeCookieValue(this.rememberMeCookieValue);
69 |
70 | this.setResponseDefaultRememberMeCookieName(c.getName());
71 | this.setResponseDefaultRememberMeCookieValue(c.getValue());
72 | break;
73 | }
74 | }
75 | }
76 |
77 | /**
78 | * 获取新的http请求响应
79 | *
80 | * @param rememberMeCookieName
81 | * @param rememberMeCookieValue
82 | * @return IHttpRequestResponse
83 | */
84 | private IHttpRequestResponse getNewHttpRequestResponse(String rememberMeCookieName, String rememberMeCookieValue) {
85 | IHttpService httpService = this.baseRequestResponse.getHttpService();
86 | IParameter newParameter = this.helpers.buildParameter(
87 | rememberMeCookieName,
88 | rememberMeCookieValue,
89 | (byte) 2);
90 | byte[] newRequest = this.helpers.updateParameter(this.baseRequestResponse.getRequest(), newParameter);
91 | IHttpRequestResponse newHttpRequestResponse = this.callbacks.makeHttpRequest(httpService, newRequest);
92 | return newHttpRequestResponse;
93 | }
94 |
95 | @Override
96 | public IScanIssue export() {
97 | if (!this.isRunExtension()) {
98 | return null;
99 | }
100 |
101 | if (!this.isShiroFingerprint()) {
102 | return null;
103 | }
104 |
105 | IHttpRequestResponse baseHttpRequestResponse = this.getHttpRequestResponse();
106 | URL newHttpRequestUrl = this.helpers.analyzeRequest(baseHttpRequestResponse).getUrl();
107 |
108 | String str1 = String.format("
============ShiroFingerprintDetail============
");
109 | String str2 = String.format("ExtensionMethod: %s
", this.getExtensionName());
110 | String str3 = String.format("RequestCookiePayload: %s=%s
",
111 | this.getRequestDefaultRememberMeCookieName(),
112 | this.getRequestDefaultRememberMeCookieValue());
113 | String str4 = String.format("ResponseReturnCookie: %s=%s
",
114 | this.getResponseDefaultRememberMeCookieName(),
115 | this.getResponseDefaultRememberMeCookieValue());
116 | String str5 = String.format("=====================================
");
117 |
118 | String detail = str1 + str2 + str3 + str4 + str5;
119 |
120 | String shiroFingerprintIssueName = this.yamlReader.getString("application.shiroFingerprintExtension.config.issueName");
121 |
122 | return new CustomScanIssue(
123 | newHttpRequestUrl,
124 | shiroFingerprintIssueName,
125 | 0,
126 | "Information",
127 | "Certain",
128 | null,
129 | null,
130 | detail,
131 | null,
132 | new IHttpRequestResponse[]{baseHttpRequestResponse},
133 | baseHttpRequestResponse.getHttpService()
134 | );
135 | }
136 |
137 | @Override
138 | public void consoleExport() {
139 | if (!this.isRunExtension()) {
140 | return;
141 | }
142 |
143 | if (!this.isShiroFingerprint()) {
144 | return;
145 | }
146 |
147 | IHttpRequestResponse baseHttpRequestResponse = this.getHttpRequestResponse();
148 | URL baseHttpRequestUrl = this.helpers.analyzeRequest(baseHttpRequestResponse).getUrl();
149 | String baseHttpRequestMethod = this.helpers.analyzeRequest(baseHttpRequestResponse.getRequest()).getMethod();
150 | int baseHttpResponseStatusCode = this.helpers.analyzeResponse(baseHttpRequestResponse.getResponse()).getStatusCode();
151 |
152 | PrintWriter stdout = new PrintWriter(this.callbacks.getStdout(), true);
153 |
154 | stdout.println("");
155 | stdout.println("=============shiro指纹详情============");
156 | stdout.println("你好呀~ (≧ω≦*)喵~");
157 | stdout.println("这边检测到有一个站点使用了 shiro框架 喵~");
158 | stdout.println(String.format("负责检测的插件: %s", this.getExtensionName()));
159 | stdout.println(String.format("url: %s", baseHttpRequestUrl));
160 | stdout.println(String.format("请求方法: %s", baseHttpRequestMethod));
161 | stdout.println(String.format("页面http状态: %d", baseHttpResponseStatusCode));
162 | stdout.println("注意: 原始请求响应返回了 shiro 关键字所以没有发送新请求");
163 | stdout.println(String.format("请求对应的cookie: %s=%s",
164 | this.getRequestDefaultRememberMeCookieName(),
165 | this.getRequestDefaultRememberMeCookieValue()));
166 | stdout.println(String.format("响应返回的cookie: %s=%s",
167 | this.getResponseDefaultRememberMeCookieName(),
168 | this.getResponseDefaultRememberMeCookieValue()));
169 | stdout.println("详情请查看-Burp Scanner模块-Issue activity界面");
170 | stdout.println("===================================");
171 | stdout.println("");
172 | }
173 | }
174 |
--------------------------------------------------------------------------------
/src/main/java/burp/Application/ShiroFingerprintExtension/ExtensionMethod/ShiroFingerprint3.java:
--------------------------------------------------------------------------------
1 | package burp.Application.ShiroFingerprintExtension.ExtensionMethod;
2 |
3 | import burp.*;
4 | import burp.Application.ShiroFingerprintExtension.ExtensionInterface.AShiroFingerprintExtension;
5 | import burp.Bootstrap.YamlReader;
6 |
7 | import java.io.PrintWriter;
8 | import java.net.URL;
9 |
10 | public class ShiroFingerprint3 extends AShiroFingerprintExtension {
11 | private IBurpExtenderCallbacks callbacks;
12 | private IExtensionHelpers helpers;
13 |
14 | private YamlReader yamlReader;
15 |
16 | private IHttpRequestResponse baseRequestResponse;
17 |
18 | private String rememberMeCookieName = "rememberMe";
19 | private String rememberMeCookieValue = "3";
20 |
21 | public ShiroFingerprint3(IBurpExtenderCallbacks callbacks, YamlReader yamlReader, IHttpRequestResponse baseRequestResponse) {
22 | this.callbacks = callbacks;
23 | this.helpers = callbacks.getHelpers();
24 |
25 | this.yamlReader = yamlReader;
26 |
27 | this.baseRequestResponse = baseRequestResponse;
28 |
29 | this.setExtensionName("ShiroFingerprint3");
30 |
31 | this.runConditionCheck();
32 | }
33 |
34 | /**
35 | * 原始请求 cookie 的 key 带了 rememberMe 则进入该流程
36 | */
37 | private void runConditionCheck() {
38 | for (IParameter p : this.helpers.analyzeRequest(this.baseRequestResponse.getRequest()).getParameters()) {
39 | if (p.getType() != 2) {
40 | continue;
41 | }
42 | if (!p.getName().equals(this.rememberMeCookieName)) {
43 | continue;
44 | }
45 | if (p.getValue() == null || p.getValue().length() <= 0) {
46 | continue;
47 | }
48 |
49 | for (ICookie c : this.helpers.analyzeResponse(this.baseRequestResponse.getResponse()).getCookies()) {
50 | if (c.getName().equals(this.rememberMeCookieName)) {
51 | if (c.getValue().equals("deleteMe")) {
52 | this.registerExtension();
53 | return;
54 | }
55 | }
56 | }
57 | }
58 | }
59 |
60 | public void runExtension() {
61 | if (!this.isRunExtension()) {
62 | return;
63 | }
64 |
65 | this.setHttpRequestResponse(this.baseRequestResponse);
66 |
67 | for (ICookie c : this.helpers.analyzeResponse(this.baseRequestResponse.getResponse()).getCookies()) {
68 | if (c.getName().equals(this.rememberMeCookieName)) {
69 | if (c.getValue().equals("deleteMe")) {
70 | this.setShiroFingerprint();
71 |
72 | this.setRequestDefaultRememberMeCookieName(this.rememberMeCookieName);
73 | this.setRequestDefaultRememberMeCookieValue(this.rememberMeCookieValue);
74 |
75 | this.setResponseDefaultRememberMeCookieName(c.getName());
76 | this.setResponseDefaultRememberMeCookieValue(c.getValue());
77 | break;
78 | }
79 | }
80 | }
81 | }
82 |
83 | @Override
84 | public IScanIssue export() {
85 | if (!this.isRunExtension()) {
86 | return null;
87 | }
88 |
89 | if (!this.isShiroFingerprint()) {
90 | return null;
91 | }
92 |
93 | IHttpRequestResponse baseHttpRequestResponse = this.getHttpRequestResponse();
94 | URL newHttpRequestUrl = this.helpers.analyzeRequest(baseHttpRequestResponse).getUrl();
95 |
96 | String str1 = String.format("
============ShiroFingerprintDetail============
");
97 | String str2 = String.format("ExtensionMethod: %s
", this.getExtensionName());
98 | String str3 = String.format("RequestCookiePayload: %s=%s
",
99 | this.getRequestDefaultRememberMeCookieName(),
100 | this.getRequestDefaultRememberMeCookieValue());
101 | String str4 = String.format("ResponseReturnCookie: %s=%s
",
102 | this.getResponseDefaultRememberMeCookieName(),
103 | this.getResponseDefaultRememberMeCookieValue());
104 | String str5 = String.format("=====================================
");
105 |
106 | String detail = str1 + str2 + str3 + str4 + str5;
107 |
108 | String shiroFingerprintIssueName = this.yamlReader.getString("application.shiroFingerprintExtension.config.issueName");
109 |
110 | return new CustomScanIssue(
111 | newHttpRequestUrl,
112 | shiroFingerprintIssueName,
113 | 0,
114 | "Information",
115 | "Certain",
116 | null,
117 | null,
118 | detail,
119 | null,
120 | new IHttpRequestResponse[]{baseHttpRequestResponse},
121 | baseHttpRequestResponse.getHttpService()
122 | );
123 | }
124 |
125 | @Override
126 | public void consoleExport() {
127 | if (!this.isRunExtension()) {
128 | return;
129 | }
130 |
131 | if (!this.isShiroFingerprint()) {
132 | return;
133 | }
134 |
135 | IHttpRequestResponse baseHttpRequestResponse = this.getHttpRequestResponse();
136 | URL baseHttpRequestUrl = this.helpers.analyzeRequest(baseHttpRequestResponse).getUrl();
137 | String baseHttpRequestMethod = this.helpers.analyzeRequest(baseHttpRequestResponse.getRequest()).getMethod();
138 | int baseHttpResponseStatusCode = this.helpers.analyzeResponse(baseHttpRequestResponse.getResponse()).getStatusCode();
139 |
140 | PrintWriter stdout = new PrintWriter(this.callbacks.getStdout(), true);
141 |
142 | stdout.println("");
143 | stdout.println("==============shiro指纹详情============");
144 | stdout.println("你好呀~ (≧ω≦*)喵~");
145 | stdout.println("这边检测到有一个站点使用了 shiro框架 喵~");
146 | stdout.println(String.format("负责检测的插件: %s", this.getExtensionName()));
147 | stdout.println(String.format("url: %s", baseHttpRequestUrl));
148 | stdout.println(String.format("请求方法: %s", baseHttpRequestMethod));
149 | stdout.println(String.format("页面http状态: %d", baseHttpResponseStatusCode));
150 | stdout.println("注意: 原始请求自己添加了 shiro 关键字所以没有发送新请求");
151 | stdout.println(String.format("请求对应的cookie: %s=%s",
152 | this.getRequestDefaultRememberMeCookieName(),
153 | this.getRequestDefaultRememberMeCookieValue()));
154 | stdout.println(String.format("响应返回的cookie: %s=%s",
155 | this.getResponseDefaultRememberMeCookieName(),
156 | this.getResponseDefaultRememberMeCookieValue()));
157 | stdout.println("详情请查看-Burp Scanner模块-Issue activity界面");
158 | stdout.println("===================================");
159 | stdout.println("");
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/src/main/java/burp/Application/ShiroFingerprintExtension/ShiroFingerprint.java:
--------------------------------------------------------------------------------
1 | package burp.Application.ShiroFingerprintExtension;
2 |
3 | import burp.IHttpRequestResponse;
4 | import burp.IBurpExtenderCallbacks;
5 |
6 | import burp.Bootstrap.YamlReader;
7 |
8 | import burp.Application.ShiroFingerprintExtension.ExtensionMethod.ShiroFingerprint1;
9 | import burp.Application.ShiroFingerprintExtension.ExtensionMethod.ShiroFingerprint2;
10 | import burp.Application.ShiroFingerprintExtension.ExtensionMethod.ShiroFingerprint3;
11 |
12 | import burp.Application.ShiroFingerprintExtension.ExtensionInterface.IShiroFingerprintExtension;
13 |
14 | public class ShiroFingerprint {
15 | private IBurpExtenderCallbacks callbacks;
16 |
17 | private YamlReader yamlReader;
18 |
19 | private IHttpRequestResponse baseRequestResponse;
20 |
21 | private IShiroFingerprintExtension shiroFingerprint;
22 |
23 | public ShiroFingerprint(IBurpExtenderCallbacks callbacks, YamlReader yamlReader, IHttpRequestResponse baseRequestResponse) {
24 | this.callbacks = callbacks;
25 |
26 | this.yamlReader = yamlReader;
27 |
28 | this.baseRequestResponse = baseRequestResponse;
29 |
30 | this.shiroFingerprint = setShiroFingerprint();
31 | }
32 |
33 | private IShiroFingerprintExtension setShiroFingerprint() {
34 | // 原始请求 cookie 的 key 带了 rememberMe 则进入该流程
35 | ShiroFingerprint3 shiroFingerprint3 = new ShiroFingerprint3(this.callbacks, this.yamlReader, this.baseRequestResponse);
36 | if (shiroFingerprint3.isRunExtension()) {
37 | shiroFingerprint3.runExtension();
38 | return shiroFingerprint3;
39 | }
40 |
41 | // 原始请求响应返回 cookie 的 value 带了 deleteMe 则进入该流程
42 | ShiroFingerprint2 shiroFingerprint2 = new ShiroFingerprint2(this.callbacks, this.yamlReader, this.baseRequestResponse);
43 | if (shiroFingerprint2.isRunExtension()) {
44 | shiroFingerprint2.runExtension();
45 | return shiroFingerprint2;
46 | }
47 |
48 | // 上面的条件都不满足时,进入该流程
49 | ShiroFingerprint1 shiroFingerprint1 = new ShiroFingerprint1(this.callbacks, this.yamlReader, this.baseRequestResponse);
50 | shiroFingerprint1.runExtension();
51 | return shiroFingerprint1;
52 | }
53 |
54 | public IShiroFingerprintExtension run() {
55 | return this.shiroFingerprint;
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/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 getHttpResponseBody(byte[] response) {
55 | IResponseInfo responseInfo = this.helpers.analyzeResponse(response);
56 |
57 | int httpResponseBodyOffset = responseInfo.getBodyOffset();
58 | int httpResponseBodyLength = response.length - httpResponseBodyOffset;
59 |
60 | String httpResponseBody = null;
61 | try {
62 | httpResponseBody = new String(response, httpResponseBodyOffset, httpResponseBodyLength, "UTF-8");
63 | } catch (UnsupportedEncodingException e) {
64 | throw new RuntimeException(e);
65 | }
66 | return httpResponseBody;
67 | }
68 | }
--------------------------------------------------------------------------------
/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/Bootstrap/CustomHelpers.java:
--------------------------------------------------------------------------------
1 | package burp.Bootstrap;
2 |
3 | import java.util.ArrayList;
4 | import java.util.Date;
5 | import java.util.List;
6 |
7 | public class CustomHelpers {
8 | /**
9 | * 获取精确到秒的时间戳
10 | *
11 | * @param date
12 | * @return Integer
13 | */
14 | public static Integer getSecondTimestamp(Date date) {
15 | if (null == date) {
16 | return 0;
17 | }
18 | String timestamp = String.valueOf(date.getTime() / 1000);
19 | return Integer.valueOf(timestamp);
20 | }
21 |
22 | /**
23 | * 列表块分割函数
24 | * 功能: 把列表按照size分割成指定的list快返回
25 | * 例子1:
26 | * a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
27 | * listChunkSplit(a, 2)
28 | * 返回: [[1, 2, 3, 4, 5], [6, 7, 8, 9]]
29 | * 例子2:
30 | * a = [1, 2, 3, 4, 5, 6, 7, 8, 9]
31 | * listChunkSplit(a, 10)
32 | * 返回: [[1], [2], [3], [4], [5], [6], [7], [8], [9]]
33 | *
34 | * @param dataSource 数据源
35 | * @param groupSize 一个整数, 规定最多分成几个list
36 | * @return List>
37 | */
38 | public static List> listChunkSplit(List dataSource, Integer groupSize) {
39 | List> result = new ArrayList<>();
40 |
41 | if (dataSource.size() == 0 || groupSize == 0) {
42 | return result;
43 | }
44 |
45 | // 偏移量
46 | int offset = 0;
47 |
48 | // 计算 商
49 | int number = dataSource.size() / groupSize;
50 |
51 | // 计算 余数
52 | int remainder = dataSource.size() % groupSize;
53 |
54 | for (int i = 0; i < groupSize; i++) {
55 | List value = null;
56 | if (remainder > 0) {
57 | value = dataSource.subList(i * number + offset, (i + 1) * number + offset + 1);
58 | remainder--;
59 | offset++;
60 | } else {
61 | value = dataSource.subList(i * number + offset, (i + 1) * number + offset);
62 | }
63 |
64 | if (value.size() == 0) {
65 | break;
66 | }
67 |
68 | result.add(value);
69 | }
70 |
71 | return result;
72 | }
73 | }
--------------------------------------------------------------------------------
/src/main/java/burp/Bootstrap/DiffPage.java:
--------------------------------------------------------------------------------
1 | package burp.Bootstrap;
2 |
3 | public class DiffPage {
4 | /**
5 | * 返回经过过滤无用的数据以后两个字符串的相似度
6 | *
7 | * @param str
8 | * @param target
9 | * @return
10 | */
11 | public static double getRatio(String str, String target) {
12 | str = getFilteredPageContent(str);
13 | target = getFilteredPageContent(target);
14 | return getSimilarityRatio(str, target);
15 | }
16 |
17 | /**
18 | * 返回经过过滤的页面内容,不包含脚本、样式和/或注释
19 | * 或所有HTML标签
20 | * 调用 getFilteredPageContent("foobartest")
21 | * 返回内容: foobartest
22 | *
23 | * @param htmlStr
24 | * @return String
25 | */
26 | public static String getFilteredPageContent(String htmlStr) {
27 | // 将实体字符串转义返回 如: "<"="<", ">"=">", """="\"", " "=" ", "&"="&"
28 | htmlStr = htmlStr.replace("<", "<");
29 | htmlStr = htmlStr.replace(">", ">");
30 | htmlStr = htmlStr.replace(""", "\"");
31 | htmlStr = htmlStr.replace(" ", " ");
32 | htmlStr = htmlStr.replace("&", "&");
33 |
34 | //定义script的正则表达式,去除js可以防止注入
35 | String scriptRegex = "