-
Notifications
You must be signed in to change notification settings - Fork 16
Expand file tree
/
Copy pathBurpExtender.java
More file actions
222 lines (191 loc) · 6.64 KB
/
BurpExtender.java
File metadata and controls
222 lines (191 loc) · 6.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
package burp;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
public class BurpExtender implements IBurpExtender, IScannerCheck
{
private IBurpExtenderCallbacks callbacks;
private IExtensionHelpers helpers;
// test / grep strings
private static final byte[] GREP_STRING = "Page generated by:".getBytes();
private static final byte[] INJ_TEST = "|".getBytes();
private static final byte[] INJ_ERROR = "Unexpected pipe".getBytes();
//
// implement IBurpExtender
//
@Override
public void registerExtenderCallbacks(final IBurpExtenderCallbacks callbacks)
{
// keep a reference to our callbacks object
this.callbacks = callbacks;
// obtain an extension helpers object
helpers = callbacks.getHelpers();
// set our extension name
callbacks.setExtensionName("Custom scanner checks");
// register ourselves as a custom scanner check
callbacks.registerScannerCheck(this);
}
// helper method to search a response for occurrences of a literal match string
// and return a list of start/end offsets
private List<int[]> getMatches(byte[] response, byte[] match)
{
List<int[]> matches = new ArrayList<int[]>();
int start = 0;
while (start < response.length)
{
start = helpers.indexOf(response, match, true, start, response.length);
if (start == -1)
break;
matches.add(new int[] { start, start + match.length });
start += match.length;
}
return matches;
}
//
// implement IScannerCheck
//
@Override
public List<IScanIssue> doPassiveScan(IHttpRequestResponse baseRequestResponse)
{
// look for matches of our passive check grep string
List<int[]> matches = getMatches(baseRequestResponse.getResponse(), GREP_STRING);
if (matches.size() > 0)
{
// report the issue
List<IScanIssue> issues = new ArrayList<>(1);
issues.add(new CustomScanIssue(
baseRequestResponse.getHttpService(),
helpers.analyzeRequest(baseRequestResponse).getUrl(),
new IHttpRequestResponse[] { callbacks.applyMarkers(baseRequestResponse, null, matches) },
"CMS Info Leakage",
"The response contains the string: " + helpers.bytesToString(GREP_STRING),
"Information"));
return issues;
}
else return null;
}
@Override
public List<IScanIssue> doActiveScan(IHttpRequestResponse baseRequestResponse, IScannerInsertionPoint insertionPoint)
{
// make a request containing our injection test in the insertion point
byte[] checkRequest = insertionPoint.buildRequest(INJ_TEST);
IHttpRequestResponse checkRequestResponse = callbacks.makeHttpRequest(
baseRequestResponse.getHttpService(), checkRequest);
// look for matches of our active check grep string
List<int[]> matches = getMatches(checkRequestResponse.getResponse(), INJ_ERROR);
if (matches.size() > 0)
{
// get the offsets of the payload within the request, for in-UI highlighting
List<int[]> requestHighlights = new ArrayList<>(1);
requestHighlights.add(insertionPoint.getPayloadOffsets(INJ_TEST));
// report the issue
List<IScanIssue> issues = new ArrayList<>(1);
issues.add(new CustomScanIssue(
baseRequestResponse.getHttpService(),
helpers.analyzeRequest(baseRequestResponse).getUrl(),
new IHttpRequestResponse[] { callbacks.applyMarkers(checkRequestResponse, requestHighlights, matches) },
"Pipe injection",
"Submitting a pipe character returned the string: " + helpers.bytesToString(INJ_ERROR),
"High"));
return issues;
}
else return null;
}
@Override
public int consolidateDuplicateIssues(IScanIssue existingIssue, IScanIssue newIssue)
{
// This method is called when multiple issues are reported for the same URL
// path by the same extension-provided check. The value we return from this
// method determines how/whether Burp consolidates the multiple issues
// to prevent duplication
//
// Since the issue name is sufficient to identify our issues as different,
// if both issues have the same name, only report the existing issue
// otherwise report both issues
if (existingIssue.getIssueName().equals(newIssue.getIssueName()))
return -1;
else return 0;
}
}
//
// class implementing IScanIssue to hold our custom scan issue details
//
class CustomScanIssue implements IScanIssue
{
private IHttpService httpService;
private URL url;
private IHttpRequestResponse[] httpMessages;
private String name;
private String detail;
private String severity;
public CustomScanIssue(
IHttpService httpService,
URL url,
IHttpRequestResponse[] httpMessages,
String name,
String detail,
String severity)
{
this.httpService = httpService;
this.url = url;
this.httpMessages = httpMessages;
this.name = name;
this.detail = detail;
this.severity = severity;
}
@Override
public URL getUrl()
{
return url;
}
@Override
public String getIssueName()
{
return name;
}
@Override
public int getIssueType()
{
return 0;
}
@Override
public String getSeverity()
{
return severity;
}
@Override
public String getConfidence()
{
return "Certain";
}
@Override
public String getIssueBackground()
{
return null;
}
@Override
public String getRemediationBackground()
{
return null;
}
@Override
public String getIssueDetail()
{
return detail;
}
@Override
public String getRemediationDetail()
{
return null;
}
@Override
public IHttpRequestResponse[] getHttpMessages()
{
return httpMessages;
}
@Override
public IHttpService getHttpService()
{
return httpService;
}
}