buby 1.1.6-java

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,211 @@
1
+ package burp;
2
+
3
+ /*
4
+ * @(#)IBurpExtenderCallbacks.java
5
+ *
6
+ * Copyright 2008 PortSwigger Ltd. All rights reserved.
7
+ * Use is subject to license terms - see http://portswigger.net/
8
+ */
9
+
10
+ /**
11
+ * This interface is used by Burp Suite to pass to implementations of the
12
+ * <code>IBurpExtender</code> interface a set of callback methods which can
13
+ * be used by implementations to perform various actions within Burp Suite.
14
+ *
15
+ * If an implementation of <code>IBurpExtender</code> is loaded then on startup
16
+ * Burp Suite will invoke the implementation's
17
+ * <code>registerExtenderCallbacks</code> method (if present) and pass to
18
+ * the implementation an instance of the <code>IBurpExtenderCallbacks</code>
19
+ * interface. The implementation may then invoke the methods of this instance
20
+ * as it sees fit in order to extend Burp Suite's functionality.<p>
21
+ */
22
+
23
+ public interface IBurpExtenderCallbacks
24
+ {
25
+ /**
26
+ * This method can be used to issue arbitrary HTTP requests and retrieve
27
+ * their responses.
28
+ *
29
+ * @param host The hostname of the remote HTTP server.
30
+ * @param port The port of the remote HTTP server.
31
+ * @param useHttps Flags whether the protocol is HTTPS or HTTP.
32
+ * @param request The full HTTP request.
33
+ * @return The full response retrieved from the remote server.
34
+ */
35
+ public byte[] makeHttpRequest(
36
+ String host,
37
+ int port,
38
+ boolean useHttps,
39
+ byte[] request) throws Exception;
40
+
41
+ /**
42
+ * This method can be used to send an HTTP request to the Burp Repeater
43
+ * tool. The request will be displayed in the user interface, but will not
44
+ * be issued until the user initiates this action.
45
+ *
46
+ * @param host The hostname of the remote HTTP server.
47
+ * @param port The port of the remote HTTP server.
48
+ * @param useHttps Flags whether the protocol is HTTPS or HTTP.
49
+ * @param request The full HTTP request.
50
+ * @param tabCaption An optional caption which will appear on the Repeater
51
+ * tab containing the request. If this value is <code>null</code> then a
52
+ * default tab index will be displayed.
53
+ */
54
+ public void sendToRepeater(
55
+ String host,
56
+ int port,
57
+ boolean useHttps,
58
+ byte[] request,
59
+ String tabCaption) throws Exception;
60
+
61
+ /**
62
+ * This method can be used to send an HTTP request to the Burp Intruder
63
+ * tool. The request will be displayed in the user interface, and markers
64
+ * for attack payloads will be placed into default locations within the
65
+ * request.
66
+ *
67
+ * @param host The hostname of the remote HTTP server.
68
+ * @param port The port of the remote HTTP server.
69
+ * @param useHttps Flags whether the protocol is HTTPS or HTTP.
70
+ * @param request The full HTTP request.
71
+ */
72
+ public void sendToIntruder(
73
+ String host,
74
+ int port,
75
+ boolean useHttps,
76
+ byte[] request) throws Exception;
77
+
78
+ /**
79
+ * This method can be used to send a seed URL to the Burp Spider tool. If
80
+ * the URL is not within the current Spider scope, the user will be asked
81
+ * if they wish to add the URL to the scope. If the Spider is not currently
82
+ * running, it will be started. The seed URL will be requested, and the
83
+ * Spider will process the application's response in the normal way.
84
+ *
85
+ * @param url The new seed URL to begin spidering from.
86
+ */
87
+ public void sendToSpider(
88
+ java.net.URL url) throws Exception;
89
+
90
+ /**
91
+ * This method can be used to send an HTTP request to the Burp Scanner
92
+ * tool to perform an active vulnerability scan. If the request is not
93
+ * within the current active scanning scope, the user will be asked if
94
+ * they wish to proceed with the scan.
95
+ *
96
+ * @param host The hostname of the remote HTTP server.
97
+ * @param port The port of the remote HTTP server.
98
+ * @param useHttps Flags whether the protocol is HTTPS or HTTP.
99
+ * @param request The full HTTP request.
100
+ */
101
+ public void doActiveScan(
102
+ String host,
103
+ int port,
104
+ boolean useHttps,
105
+ byte[] request) throws Exception;
106
+
107
+ /**
108
+ * This method can be used to send an HTTP request to the Burp Scanner
109
+ * tool to perform a passive vulnerability scan.
110
+ *
111
+ * @param host The hostname of the remote HTTP server.
112
+ * @param port The port of the remote HTTP server.
113
+ * @param useHttps Flags whether the protocol is HTTPS or HTTP.
114
+ * @param request The full HTTP request.
115
+ * @param response The full HTTP response.
116
+ */
117
+ public void doPassiveScan(
118
+ String host,
119
+ int port,
120
+ boolean useHttps,
121
+ byte[] request,
122
+ byte[] response) throws Exception;
123
+
124
+ /**
125
+ * This method can be used to query whether a specified URL is within
126
+ * the current Suite-wide scope.
127
+ *
128
+ * @param url The URL to query.
129
+ * @return Returns <code>true</code> if the URL is within the current
130
+ * Suite-wide scope.
131
+ */
132
+ boolean isInScope(java.net.URL url) throws Exception;
133
+
134
+ /**
135
+ * This method can be used to include the specified URL in the Suite-wide
136
+ * scope.
137
+ *
138
+ * @param url The URL to include in the Suite-wide scope.
139
+ */
140
+ void includeInScope(java.net.URL url) throws Exception;
141
+
142
+ /**
143
+ * This method can be used to exclude the specified URL from the Suite-wide
144
+ * scope.
145
+ *
146
+ * @param url The URL to exclude from the Suite-wide scope.
147
+ */
148
+ void excludeFromScope(java.net.URL url) throws Exception;
149
+
150
+ /**
151
+ * This method can be used to display a specified message in the Burp
152
+ * Suite alerts tab.
153
+ *
154
+ * @param message The alert message to display.
155
+ */
156
+ public void issueAlert(String message);
157
+
158
+ /**
159
+ * New stuff added as of v1.2.11.
160
+ * The new IBurpExtenderCallbacks interface adds several new methods
161
+ * which you can invoke to query and update Burp's state, and to parse raw
162
+ * HTTP messages for parameters and headers.
163
+ */
164
+
165
+ /**
166
+ * no javadoc yet from PortSwigger
167
+ */
168
+ public IHttpRequestResponse[] getProxyHistory();
169
+
170
+ /**
171
+ * no javadoc yet from PortSwigger
172
+ */
173
+ public IHttpRequestResponse[] getSiteMap(String urlPrefix);
174
+
175
+ /**
176
+ * This method returns all of the current scan issues for URLs matching
177
+ * the specified literal prefix.
178
+ * The prefix can be null to match all issues.
179
+ *
180
+ * Added in v1.2.15.
181
+ */
182
+ public IScanIssue[] getScanIssues(String urlPrefix);
183
+
184
+ /**
185
+ * no javadoc yet from PortSwigger
186
+ */
187
+ public void restoreState(java.io.File file) throws Exception;
188
+
189
+ /**
190
+ * no javadoc yet from PortSwigger
191
+ */
192
+ public void saveState(java.io.File file) throws Exception;
193
+
194
+ /**
195
+ * no javadoc yet from PortSwigger
196
+ */
197
+ public String[][] getParameters(byte[] request) throws Exception;
198
+
199
+ /**
200
+ * no javadoc yet from PortSwigger
201
+ */
202
+ public String[] getHeaders(byte[] message) throws Exception;
203
+
204
+ /**
205
+ * Shuts down burp programatically. If the method returns, the user
206
+ * cancelled the shutdown prompt.
207
+ *
208
+ * Available in v1.2.17+.
209
+ */
210
+ public void exitSuite(boolean promptUser);
211
+ }
@@ -0,0 +1,32 @@
1
+ package burp;
2
+
3
+ import java.net.URL;
4
+
5
+ public interface IHttpRequestResponse
6
+ {
7
+
8
+ public String getHost();
9
+
10
+ public int getPort();
11
+
12
+ public String getProtocol();
13
+
14
+ public void setHost(String host) throws Exception;
15
+
16
+ public void setPort(int port) throws Exception;
17
+
18
+ public void setProtocol(String protocol) throws Exception;
19
+
20
+ public byte[] getRequest() throws Exception;
21
+
22
+ public java.net.URL getUrl() throws Exception;
23
+
24
+ public void setRequest(byte[] message) throws Exception;
25
+
26
+ public byte[] getResponse() throws Exception;
27
+
28
+ public void setResponse(byte[] message) throws Exception;
29
+
30
+ public short getStatusCode() throws Exception;
31
+
32
+ }
@@ -0,0 +1,32 @@
1
+ package burp;
2
+
3
+ import java.net.URL;
4
+
5
+ public interface IScanIssue
6
+ {
7
+
8
+ public String getHost();
9
+
10
+ public int getPort();
11
+
12
+ public String getProtocol();
13
+
14
+ public java.net.URL getUrl();
15
+
16
+ public String getIssueName();
17
+
18
+ public String getSeverity();
19
+
20
+ public String getConfidence();
21
+
22
+ public String getIssueBackground();
23
+
24
+ public String getRemediationBackground();
25
+
26
+ public String getIssueDetail();
27
+
28
+ public String getRemediationDetail();
29
+
30
+ public IHttpRequestResponse[] getHttpMessages();
31
+
32
+ }
@@ -0,0 +1,20 @@
1
+ package burp;
2
+
3
+ public interface IScanQueueItem
4
+ {
5
+
6
+ public String getStatus();
7
+
8
+ public byte getPercentageComplete();
9
+
10
+ public int getNumRequests();
11
+
12
+ public int getNumErrors();
13
+
14
+ public int getNumInsertionPoints();
15
+
16
+ public void cancel();
17
+
18
+ public IScanIssue[] getIssues();
19
+
20
+ }
@@ -0,0 +1,772 @@
1
+ include Java
2
+
3
+ require 'pp'
4
+ require "buby.jar"
5
+ require 'buby/extends.rb'
6
+
7
+ include_class 'BurpExtender'
8
+
9
+ # Buby is a mash-up of the commercial security testing web proxy PortSwigger
10
+ # Burp Suite(tm) allowing you to add scripting to Burp. Burp is driven from
11
+ # and tied to JRuby with a Java extension using the BurpExtender API.
12
+ #
13
+ # The Buby class is an abstract implementation of a BurpExtender ruby handler.
14
+ # Included are several abstract event handlers used from the BurpExtender
15
+ # java implementation:
16
+ # * evt_extender_init
17
+ # * evt_proxy_message
18
+ # * evt_command_line_args
19
+ # * evt_register_callbacks
20
+ # * evt_application_closing
21
+ #
22
+ # Buby also supports the newer event handlers available in Burp 1.2.09 and up:
23
+ # * evt_http_message
24
+ # * evt_scan_issue
25
+ #
26
+ #
27
+ # This class also exposes several methods to access Burp functionality
28
+ # and user interfaces through the IBurpExtenderCallbacks interface
29
+ # (note, several abbreviated aliases also exist for each):
30
+ # * doActiveScan
31
+ # * doPassiveScan
32
+ # * excludeFromScope
33
+ # * includeInScope
34
+ # * isInScope
35
+ # * issueAlert
36
+ # * makeHttpRequest
37
+ # * sendToIntruder
38
+ # * sendToRepeater
39
+ # * sendToSpider
40
+ #
41
+ # Buby also provides front-end ruby methods for the various callback methods
42
+ # supported by Burp. New callbacks have been cropping up in newer Burp versions
43
+ # frequently.
44
+ #
45
+ # Available since Burp 1.2.09:
46
+ # * getProxyHistory
47
+ # * getSiteMap
48
+ # * restoreState
49
+ # * saveState
50
+ # * getParameters
51
+ # * getHeaders
52
+ #
53
+ # Available since Burp 1.2.15:
54
+ # * getScanIssues
55
+ #
56
+ # Available since Burp 1.2.17:
57
+ # * exitSuite
58
+ #
59
+ # If you wish to access any of the IBurpExtenderCallbacks methods directly.
60
+ # You can use 'burp_callbacks' to obtain a reference.
61
+ #
62
+ # Credit:
63
+ # * Burp and Burp Suite are trade-marks of PortSwigger Ltd.
64
+ # Copyright 2008 PortSwigger Ltd. All rights reserved.
65
+ # See http://portswigger.net for license terms.
66
+ #
67
+ # * This ruby library and the accompanying BurpExtender.java implementation
68
+ # were written by Eric Monti @ Matasano Security.
69
+ #
70
+ # Matasano claims no professional or legal affiliation with PortSwigger LTD.
71
+ # nor do we sell or officially endorse any of their products.
72
+ #
73
+ # However, this author would like to express his personal and professional
74
+ # respect and appreciation for their making available the BurpExtender
75
+ # extension API. The availability of this interface in an already great tool
76
+ # goes a long way to make Burp Suite a truly first-class application.
77
+ #
78
+ # * Forgive the name. It won out over "Burb" and "BurpRub". It's just easier
79
+ # to type and say out-loud. Mike Tracy gets full credit as official
80
+ # Buby-namer.
81
+ #
82
+ class Buby
83
+
84
+ # :stopdoc:
85
+ VERSION = '1.1.6'
86
+ LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
87
+ PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
88
+ # :startdoc:
89
+
90
+ def initialize(other=nil)
91
+ if other
92
+ raise "arg 0 must be another kind of Buby" unless other.is_a? Buby
93
+ @burp_extender = other.burp_extender
94
+ @burp_callbacks = other.burp_callbacks
95
+ end
96
+ end
97
+
98
+ # Makes this handler the active Ruby handler object for the BurpExtender
99
+ # Java runtime. (there can be only one!)
100
+ def activate!
101
+ BurpExtender.set_handler(self)
102
+ end
103
+
104
+ # Returns the internal reference to the BurpExtender instance. This
105
+ # reference gets set from Java through the evt_extender_init method.
106
+ def burp_extender; @burp_extender; end
107
+
108
+ # Returns the internal reference to the IBupExtenderCallbacks instance.
109
+ # This reference gets set from Java through the evt_register_callbacks
110
+ # method. It is exposed to allow you to access the IBurpExtenderCallbacks
111
+ # instance directly if you so choose.
112
+ def burp_callbacks; @burp_callbacks; end
113
+
114
+ # Internal method to check for the existence of the burp_callbacks reference
115
+ # before doing anything with it.
116
+ def _check_cb
117
+ @burp_callbacks or raise "Burp callbacks have not been set"
118
+ end
119
+
120
+ # Send an HTTP request to the Burp Scanner tool to perform an active
121
+ # vulnerability scan.
122
+ # * host = The hostname of the remote HTTP server.
123
+ # * port = The port of the remote HTTP server.
124
+ # * https = Flags whether the protocol is HTTPS or HTTP.
125
+ # * req = The full HTTP request. (String or Java bytes[])
126
+ def doActiveScan(host, port, https, req)
127
+ req = req.to_java_bytes if req.is_a? String
128
+ _check_cb.doActiveScan(host, port, https, req)
129
+ end
130
+ alias do_active_scan doActiveScan
131
+ alias active_scan doActiveScan
132
+
133
+ # Send an HTTP request and response to the Burp Scanner tool to perform a
134
+ # passive vulnerability scan.
135
+ # * host = The hostname of the remote HTTP server.
136
+ # * port = The port of the remote HTTP server.
137
+ # * https = Flags whether the protocol is HTTPS or HTTP.
138
+ # * req = The full HTTP request. (String or Java bytes[])
139
+ # * rsp = The full HTTP response. (String or Java bytes[])
140
+ def doPassiveScan(host, port, https, req, rsp)
141
+ req = req.to_java_bytes if req.is_a? String
142
+ rsp = rsp.to_java_bytes if rsp.is_a? String
143
+ _check_cb.doPassiveScan(host, port, https, req, rsp)
144
+ end
145
+ alias do_passive_scan doPassiveScan
146
+ alias passive_scan doPassiveScan
147
+
148
+ # Exclude the specified URL from the Suite-wide scope.
149
+ # * url = The URL to exclude from the Suite-wide scope.
150
+ def excludeFromScope(url)
151
+ url = java.net.URL.new(url) if url.is_a? String
152
+ _check_cb.excludeFromScope(url)
153
+ end
154
+ alias exclude_from_scope excludeFromScope
155
+ alias exclude_scope excludeFromScope
156
+
157
+ # Include the specified URL in the Suite-wide scope.
158
+ # * url = The URL to exclude in the Suite-wide scope.
159
+ def includeInScope(url)
160
+ url = java.net.URL.new(url) if url.is_a? String
161
+ _check_cb.includeInScope(url)
162
+ end
163
+ alias include_in_scope includeInScope
164
+ alias include_scope includeInScope
165
+
166
+ # Query whether a specified URL is within the current Suite-wide scope.
167
+ # * url = The URL to query
168
+ #
169
+ # Returns: true / false
170
+ def isInScope(url)
171
+ url = java.net.URL.new(url) if url.is_a? String
172
+ _check_cb.isInScope(url)
173
+ end
174
+ alias is_in_scope isInScope
175
+ alias in_scope? isInScope
176
+
177
+ # Display a message in the Burp Suite alerts tab.
178
+ # * msg = The alert message to display.
179
+ def issueAlert(msg)
180
+ _check_cb.issueAlert(msg.to_s)
181
+ end
182
+ alias issue_alert issueAlert
183
+ alias alert issueAlert
184
+
185
+ # Issue an arbitrary HTTP request and retrieve its response
186
+ # * host = The hostname of the remote HTTP server.
187
+ # * port = The port of the remote HTTP server.
188
+ # * https = Flags whether the protocol is HTTPS or HTTP.
189
+ # * req = The full HTTP request. (String or Java bytes[])
190
+ #
191
+ # Returns: The full response retrieved from the remote server.
192
+ def makeHttpRequest(host, port, https, req)
193
+ req = req.to_java_bytes if req.is_a? String
194
+ String.from_java_bytes( _check_cb.makeHttpRequest(host, port, https, req) )
195
+ end
196
+ alias make_http_request makeHttpRequest
197
+ alias make_request makeHttpRequest
198
+
199
+ # Send an HTTP request to the Burp Intruder tool
200
+ # * host = The hostname of the remote HTTP server.
201
+ # * port = The port of the remote HTTP server.
202
+ # * https = Flags whether the protocol is HTTPS or HTTP.
203
+ # * req = The full HTTP request. (String or Java bytes[])
204
+ def sendToIntruder(host, port, https, req)
205
+ req = req.to_java_bytes if req.is_a? String
206
+ _check_cb.sendToIntruder(host, port, https, req)
207
+ end
208
+ alias send_to_intruder sendToIntruder
209
+ alias intruder sendToIntruder
210
+
211
+ # Send an HTTP request to the Burp Repeater tool.
212
+ # * host = The hostname of the remote HTTP server.
213
+ # * port = The port of the remote HTTP server.
214
+ # * https = Flags whether the protocol is HTTPS or HTTP.
215
+ # * req = The full HTTP request. (String or Java bytes[])
216
+ # * tab = The tab caption displayed in Repeater. (default: auto-generated)
217
+ def sendToRepeater(host, port, https, req, tab=nil)
218
+ req = req.to_java_bytes if req.is_a? String
219
+ _check_cb.sendToRepeater(host, port, https, req, tab)
220
+ end
221
+ alias send_to_repeater sendToRepeater
222
+ alias repeater sendToRepeater
223
+
224
+ # Send a seed URL to the Burp Spider tool.
225
+ # * url = The new seed URL to begin spidering from.
226
+ def sendToSpider(url)
227
+ url = java.net.URL.new(url) if url.is_a? String
228
+ _check_cb.includeInScope(url)
229
+ end
230
+ alias send_to_spider sendToSpider
231
+ alias spider sendToSpider
232
+
233
+ # This method is a __send__ callback gate for the IBurpExtenderCallbacks
234
+ # reference. It first checks to see if a method is available before calling
235
+ # with the specified arguments, and raises an exception if it is unavailable.
236
+ #
237
+ # * meth = string or symbol name of method
238
+ # * args = variable length array of arguments to pass to meth
239
+ def _check_and_callback(meth, *args)
240
+ cb = _check_cb
241
+ unless cb.respond_to?(meth)
242
+ raise "#{meth} is not available in your version of Burp"
243
+ end
244
+ cb.__send__ meth, *args
245
+ end
246
+
247
+
248
+ # Returns a Java array of IHttpRequestResponse objects pulled directly from
249
+ # the Burp proxy history.
250
+ def getProxyHistory
251
+ HttpRequestResponseList.new(_check_and_callback(:getProxyHistory))
252
+ end
253
+ alias proxy_history getProxyHistory
254
+ alias get_proxy_history getProxyHistory
255
+
256
+
257
+ # Returns a Java array of IHttpRequestResponse objects pulled directly from
258
+ # the Burp site map for all urls matching the specified literal prefix.
259
+ # The prefix can be nil to return all objects.
260
+ def getSiteMap(urlprefix=nil)
261
+ HttpRequestResponseList.new(_check_and_callback(:getSiteMap, urlprefix))
262
+ end
263
+ alias site_map getSiteMap
264
+ alias get_site_map getSiteMap
265
+
266
+
267
+ # This method returns all of the current scan issues for URLs matching the
268
+ # specified literal prefix. The prefix can be nil to match all issues.
269
+ #
270
+ # IMPORTANT: This method is only available with Burp 1.2.15 and higher.
271
+ def getScanIssues(urlprefix=nil)
272
+ ScanIssuesList.new( _check_and_callback(:getScanIssues, urlprefix) )
273
+ end
274
+ alias scan_issues getScanIssues
275
+ alias get_scan_issues getScanIssues
276
+
277
+
278
+ # Restores Burp session state from a previously saved state file.
279
+ # See also: saveState
280
+ #
281
+ # IMPORTANT: This method is only available with Burp 1.2.09 and higher.
282
+ #
283
+ # * filename = path and filename of the file to restore from
284
+ def restoreState(filename)
285
+ _check_and_callback(:restoreState, java.io.File.new(filename))
286
+ end
287
+ alias restore_state restoreState
288
+
289
+
290
+ # Saves the current Burp session to a state file. See also restoreState.
291
+ #
292
+ # IMPORTANT: This method is only available with Burp 1.2.09 and higher.
293
+ #
294
+ # * filename = path and filename of the file to save to
295
+ def saveState(filename)
296
+ _check_and_callback(:saveState, java.io.File.new(filename))
297
+ end
298
+ alias save_state saveState
299
+
300
+
301
+ # Parses a raw HTTP request message and returns an associative array
302
+ # containing parameters as they are structured in the 'Parameters' tab in the
303
+ # Burp request UI.
304
+ #
305
+ # IMPORTANT: This method is only available with Burp 1.2.09 and higher.
306
+ #
307
+ # req = raw request (String or Java bytes[])
308
+ def getParameters(req)
309
+ req = req.to_java_bytes if req.is_a? String
310
+ _check_and_callback(:getParameters, req)
311
+ end
312
+ alias parameters getParameters
313
+ alias get_parameters getParameters
314
+
315
+
316
+ # Parses a raw HTTP message (request or response ) and returns an associative
317
+ # array containing the headers as they are structured in the 'Headers' tab
318
+ # in the Burp request/response viewer UI.
319
+ #
320
+ # IMPORTANT: This method is only available with Burp 1.2.09 and higher.
321
+ #
322
+ # msg = raw request/response (String or Java bytes[])
323
+ def getHeaders(msg)
324
+ msg = msg.to_java_bytes if msg.is_a? String
325
+ _check_and_callback(:getHeaders, msg)
326
+ end
327
+ alias headers getHeaders
328
+ alias get_headers getHeaders
329
+
330
+ # Shuts down Burp programatically. If the method returns the user cancelled
331
+ # the shutdown prompt.
332
+ def exitSuite(prompt_user=false)
333
+ _check_and_callback(:exitSuite, prompt_user ? true : false)
334
+ end
335
+ alias exit_suite exitSuite
336
+ alias close exitSuite
337
+
338
+ ### Event Handlers ###
339
+
340
+ # This method is called by the BurpExtender java implementation upon
341
+ # initialization of the BurpExtender instance for Burp. The args parameter
342
+ # is passed with a instance of the newly initialized BurpExtender instance
343
+ # so that implementations can access and extend its public interfaces.
344
+ #
345
+ # The return value is ignored.
346
+ def evt_extender_init ext
347
+ @burp_extender = ext
348
+ pp([:got_extender, ext]) if $DEBUG
349
+ end
350
+
351
+ # This method is called by the BurpExtender implementation Burp startup.
352
+ # The args parameter contains main()'s argv command-line arguments array.
353
+ #
354
+ # Note: This maps to the 'setCommandLineArgs' method in the java
355
+ # implementation of BurpExtender.
356
+ #
357
+ # The return value is ignored.
358
+ def evt_command_line_args args
359
+ pp([:got_args, args]) if $DEBUG
360
+ end
361
+
362
+ # This method is called by BurpExtender on startup to register Burp's
363
+ # IBurpExtenderCallbacks interface object.
364
+ #
365
+ # This maps to the 'registerExtenderCallbacks' method in the Java
366
+ # implementation of BurpExtender.
367
+ #
368
+ # The return value is ignored.
369
+ def evt_register_callbacks cb
370
+ @burp_callbacks = cb
371
+ cb.issueAlert("[JRuby::#{self.class}] registered callback")
372
+ pp([:got_callbacks, cb]) if $DEBUG
373
+ end
374
+
375
+ ACTION_FOLLOW_RULES = BurpExtender::ACTION_FOLLOW_RULES
376
+ ACTION_DO_INTERCEPT = BurpExtender::ACTION_DO_INTERCEPT
377
+ ACTION_DONT_INTERCEPT = BurpExtender::ACTION_DONT_INTERCEPT
378
+ ACTION_DROP = BurpExtender::ACTION_DROP
379
+
380
+ # seems we need to specifically render our 'message' to a string here in
381
+ # java. Otherwise there's flakiness when converting certain binary non-ascii
382
+ # sequences. As long as we do it here, it should be fine.
383
+ #
384
+ # This method just handles the conversion to and from evt_proxy_message
385
+ # which expects a message string
386
+ def evt_proxy_message_raw msg_ref, is_req, rhost, rport, is_https, http_meth, url, resourceType, status, req_content_type, message, action
387
+ pp [:evt_proxy_message_raw_hit, msg_ref, is_req, rhost, rport, is_https, http_meth, url, resourceType, status, req_content_type, message, action ] if $DEBUG
388
+ str_msg = String.from_java_bytes(message)
389
+ ret = evt_proxy_message(msg_ref, is_req, rhost, rport, is_https, http_meth, url, resourceType, status, req_content_type, str_msg, action)
390
+ message = ret.to_java_bytes unless ret == str_msg
391
+ return message
392
+ end
393
+
394
+ # This method is called by BurpExtender while proxying HTTP messages and
395
+ # before passing them through the Burp proxy. Implementations can use this
396
+ # method to implement arbitrary processing upon HTTP requests and responses
397
+ # such as interception, logging, modification, and so on.
398
+ #
399
+ # The 'is_req' parameter indicates whether it is a response or request.
400
+ #
401
+ # Note: This method maps to the 'processProxyMessage' method in the java
402
+ # implementation of BurpExtender.
403
+ #
404
+ # Below are the parameters descriptions based on the IBurpExtender
405
+ # javadoc. Where applicable, decriptions have been modified for
406
+ # local parameter naming and other ruby-specific details added.
407
+ #
408
+ # * msg_ref:
409
+ # An identifier which is unique to a single request/response pair. This
410
+ # can be used to correlate details of requests and responses and perform
411
+ # processing on the response message accordingly. This number also
412
+ # corresponds to the Burp UI's proxy "history" # column.
413
+ #
414
+ # * is_req: (true/false)
415
+ # Flags whether the message is a client request or a server response.
416
+ #
417
+ # * rhost:
418
+ # The hostname of the remote HTTP server.
419
+ #
420
+ # * rport:
421
+ # The port of the remote HTTP server.
422
+ #
423
+ # * is_https:
424
+ # Flags whether the protocol is HTTPS or HTTP.
425
+ #
426
+ # * http_meth:
427
+ # The method verb used in the client request.
428
+ #
429
+ # * url:
430
+ # The requested URL. Set in both the request and response.
431
+ #
432
+ # * resourceType:
433
+ # The filetype of the requested resource, or nil if the resource has no
434
+ # filetype.
435
+ #
436
+ # * status:
437
+ # The HTTP status code returned by the server. This value is nil for
438
+ # request messages.
439
+ #
440
+ # * req_content_type:
441
+ # The content-type string returned by the server. This value is nil for
442
+ # request messages.
443
+ #
444
+ # * message:
445
+ # The full HTTP message.
446
+ # **Ruby note:
447
+ # For convenience, the message is received and returned as a ruby
448
+ # String object. Internally within Burp it is handled as a java byte[]
449
+ # array. See also the notes about the return object below.
450
+ #
451
+ # * action:
452
+ # An array containing a single integer, allowing the implementation to
453
+ # communicate back to Burp Proxy a non-default interception action for
454
+ # the message. The default value is ACTION_FOLLOW_RULES (or 0).
455
+ # Possible values include:
456
+ # ACTION_FOLLOW_RULES = 0
457
+ # ACTION_DO_INTERCEPT = 1
458
+ # ACTION_DONT_INTERCEPT = 2
459
+ # ACTION_DROP = 3
460
+ #
461
+ # Refer to the BurpExtender.java source comments for more details.
462
+ #
463
+ #
464
+ # Return Value:
465
+ # Implementations should return either (a) the same object received
466
+ # in the message paramater, or (b) a different object containing a
467
+ # modified message.
468
+ #
469
+ # **IMPORTANT RUBY NOTE:
470
+ # Always be sure to return a new object if making modifications to messages.
471
+ #
472
+ # Explanation:
473
+ # The (a) and (b) convention above is followed rather literally during type
474
+ # conversion on the return value back into the java BurpExtender.
475
+ #
476
+ # When determining whether a change has been made in the message or not,
477
+ # the decision is made based on whether the object returned is the same
478
+ # as the object submitted in the call to evt_proxy_message.
479
+ #
480
+ #
481
+ # So, for example, using in-place modification of the message using range
482
+ # substring assignments or destructive method variations like String.sub!()
483
+ # and String.gsub! alone won't work because the same object gets returned
484
+ # to BurpExtender.
485
+ #
486
+ # In short, this means that if you want modifications to be made, be sure
487
+ # to return a different String than the one you got in your handler.
488
+ #
489
+ # So for example this code won't do anything at all:
490
+ #
491
+ # ...
492
+ # message.sub!(/^GET /, "HEAD ")
493
+ # return message
494
+ #
495
+ # Nor this:
496
+ #
497
+ # message[0..4] = "HEAD "
498
+ # return message
499
+ #
500
+ # But this will
501
+ #
502
+ # ...
503
+ # return message.sub(/^GET /, "HEAD ")
504
+ #
505
+ # And so will this
506
+ #
507
+ # ...
508
+ # message[0..4] = "HEAD "
509
+ # return message.dup
510
+ #
511
+ def evt_proxy_message msg_ref, is_req, rhost, rport, is_https, http_meth, url, resourceType, status, req_content_type, message, action
512
+ pp([ (is_req)? :got_proxy_request : :got_proxy_response,
513
+ [:msg_ref, msg_ref],
514
+ [:is_req, is_req],
515
+ [:rhost, rhost],
516
+ [:rport, rport],
517
+ [:is_https, is_https],
518
+ [:http_meth, http_meth],
519
+ [:url, url],
520
+ [:resourceType, resourceType],
521
+ [:status, status],
522
+ [:req_content_type, req_content_type],
523
+ [:message, message],
524
+ [:action, action[0]] ]) if $DEBUG
525
+
526
+ return message
527
+ end
528
+
529
+
530
+ # This method is invoked whenever any of Burp's tools makes an HTTP request
531
+ # or receives a response. This is effectively a generalised version of the
532
+ # pre-existing evt_proxy_message method, and can be used to intercept and
533
+ # modify the HTTP traffic of all Burp tools.
534
+ #
535
+ # IMPORTANT: This event handler is only used in Burp version 1.2.09 and
536
+ # higher.
537
+ #
538
+ # Note: this method maps to the processHttpMessage BurpExtender Java method.
539
+ #
540
+ # This method should be overridden if you wish to implement functionality
541
+ # relating to generalized requests and responses from any BurpSuite tool.
542
+ #
543
+ # You may want to use evt_proxy_message if you only intend to work on
544
+ # proxied messages. Note, however, the IHttpRequestResponse Java object is
545
+ # not used in evt_proxy_message and gives evt_http_message a somewhat
546
+ # nicer interface to work with.
547
+ #
548
+ # Parameters:
549
+ # * tool_name = a string name of the tool that generated the message
550
+ #
551
+ # * is_request = boolean true = request / false = response
552
+ #
553
+ # * message_info = an instance of the IHttpRequestResponse Java class with
554
+ # methods for accessing and manipulating various attributes of the message.
555
+ #
556
+ def evt_http_message(tool_name, is_request, message_info)
557
+ HttpRequestResponseHelper.implant(message_info)
558
+ pp([:got_http_message, tool_name, is_request, message_info]) if $DEBUG
559
+ end
560
+
561
+ # This method is invoked whenever Burp Scanner discovers a new, unique
562
+ # issue, and can be used to perform customised reporting or logging of
563
+ # detected issues.
564
+ #
565
+ # IMPORTANT: This event handler is only used in Burp version 1.2.09 and
566
+ # higher.
567
+ #
568
+ # Note: this method maps to the BurpExtender Java method.
569
+ #
570
+ # Parameters:
571
+ # * issue = an instance of the IScanIssue Java class with methods for viewing
572
+ # information on the scan issue that was generated.
573
+ def evt_scan_issue(issue)
574
+ ScanIssueHelper.implant(issue)
575
+ pp([:got_scan_issue, issue]) if $DEBUG
576
+ end
577
+
578
+ # This method is called by BurpExtender right before closing the
579
+ # application. Implementations can use this method to perform cleanup
580
+ # tasks such as closing files or databases before exit.
581
+ def evt_application_closing
582
+ pp([:got_app_close]) if $DEBUG
583
+ end
584
+
585
+ ### Sugar/Convenience methods
586
+
587
+ # This is a convenience wrapper which can load a given burp state file and
588
+ # lets its caller to perform actions inside of a block on the site map
589
+ # contained in the loaded session.
590
+ #
591
+ # If a statefile argument isn't specified current burp session state is used.
592
+ #
593
+ # Yields each entry in the site map to a block.
594
+ def with_site_map(urlprefix=nil, statefile=nil)
595
+ with_statefile(statefile) do |this|
596
+ this.site_map(urlprefix).each {|h| yield h }
597
+ end
598
+ end
599
+
600
+ # This is a convenience wrapper which can load a given burp state file and
601
+ # lets its caller to perform actions inside of a block on the proxy history
602
+ # contained in the loaded session.
603
+ #
604
+ # If a statefile argument isn't specified current burp session state is used.
605
+ #
606
+ # Yields each entry in the proxy history to a block.
607
+ def with_proxy_history(statefile=nil)
608
+ with_statefile(statefile) do |this|
609
+ this.proxy_history.each {|h| yield h }
610
+ end
611
+ end
612
+
613
+ # This is a convenience wrapper which loads a given burp statefile and lets
614
+ # its caller perform actions via burp while its loaded on it inside of a
615
+ # block. The old state is restored after the block completes.
616
+ #
617
+ # It can safely be run with a nil statefile argument in which the
618
+ # current burp session state is used.
619
+ def with_statefile(statefile=nil)
620
+ if statefile
621
+ # save current state:
622
+ old_state=".#{$$}.#{Time.now.to_i}.state.bak"
623
+ self.alert "Saving current state to temp statefile: #{old_state}"
624
+ self.save_state(old_state)
625
+ self.alert "Restoring state: #{statefile}"
626
+ self.restore_state(statefile)
627
+ end
628
+
629
+ yield self
630
+
631
+ if statefile
632
+ # restore original state
633
+ self.alert "Restoring temp statefile: #{old_state}"
634
+ self.restore_state old_state
635
+ self.alert "Deleting temp state file: #{old_state}"
636
+ File.unlink old_state
637
+ end
638
+ end
639
+
640
+ # Searches the proxy history for the url's matched by the specified
641
+ # regular expression (returns them all if urlrx is nil).
642
+ #
643
+ # A statefile to search in can optionally be specified or the existing
644
+ # state will be used if statefile is nil.
645
+ #
646
+ # This method also accepts an optional block which is passed each of the
647
+ # matched history members.
648
+ def search_proxy_history(statefile=nil, urlrx=nil)
649
+ ret = []
650
+ with_proxy_history(statefile) do |r|
651
+ if (not urlrx) or r.url.to_s =~ urlrx
652
+ ret << r if (not block_given?) or yield(r)
653
+ end
654
+ end
655
+ return ret
656
+ end
657
+
658
+ # Harvest cookies from a session's proxy history.
659
+ #
660
+ # Params:
661
+ # cookie = optional: name of cookie to harvest
662
+ # urlrx = optional: regular expression to match urls against
663
+ # statefile = optional: filename for a burp session file to temporarily load
664
+ # and harvest from.
665
+ #
666
+ # Takes an optional block as additional 'select' criteria for cookies.
667
+ # The block return value of true/false will determine whether a cookie
668
+ # string is selected.
669
+ def harvest_cookies_from_history(cookie=nil, urlrx=nil, statefile=nil)
670
+ ret = []
671
+ search_proxy_history(statefile, urlrx) do |hrr|
672
+ if heads=hrr.rsp_headers
673
+ ret += heads.select do |h|
674
+ h[0].downcase == 'set-cookie' and (not block_given? or yield(h[1]))
675
+ end.map{|h| h[1]}
676
+ end
677
+ end
678
+ return ret
679
+ end
680
+
681
+ ### Startup stuff
682
+
683
+ # Prepares the java BurpExtender implementation with a reference
684
+ # to self as the module handler and launches burp suite.
685
+ def start_burp(args=[])
686
+ activate!()
687
+ Java::Burp::StartBurp.main(args.to_java(:string))
688
+ return self
689
+ end
690
+
691
+ # Starts burp using a supplied handler class,
692
+ # h_class = Buby or a derived class. instance of which will become handler.
693
+ # args = arguments to Burp
694
+ # init_args = arguments to the handler constructor
695
+ #
696
+ # Returns the handler instance
697
+ def self.start_burp(h_class=nil, init_args=nil, args=nil)
698
+ h_class ||= self
699
+ init_args ||= []
700
+ args ||= []
701
+ h_class.new(*init_args).start_burp(args)
702
+ end
703
+
704
+ # Attempts to load burp with require and confirm it provides the required
705
+ # class in the Java namespace.
706
+ #
707
+ # Returns: true/false depending on whether the required jar provides us
708
+ # the required class
709
+ #
710
+ # Raises: may raise the usual require exceptions if jar_path is bad.
711
+ def self.load_burp(jar_path)
712
+ require jar_path
713
+ return burp_loaded?
714
+ end
715
+
716
+ # Checks the Java namespace to see if Burp has been loaded.
717
+ def self.burp_loaded?
718
+ begin
719
+ include_class 'burp.StartBurp'
720
+ return true
721
+ rescue NameError
722
+ return false
723
+ end
724
+ end
725
+
726
+ ### Extra cruft added by Mr Bones:
727
+
728
+ # Returns the library path for the module. If any arguments are given,
729
+ # they will be joined to the end of the libray path using
730
+ # <tt>File.join</tt>.
731
+ #
732
+ def self.libpath( *args )
733
+ args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
734
+ end
735
+
736
+ # Returns the lpath for the module. If any arguments are given,
737
+ # they will be joined to the end of the path using
738
+ # <tt>File.join</tt>.
739
+ #
740
+ def self.path( *args )
741
+ args.empty? ? PATH : ::File.join(PATH, args.flatten)
742
+ end
743
+
744
+ # Utility method used to require all files ending in .rb that lie in the
745
+ # directory below this file that has the same name as the filename passed
746
+ # in. Optionally, a specific _directory_ name can be passed in such that
747
+ # the _filename_ does not have to be equivalent to the directory.
748
+ #
749
+ def self.require_all_libs_relative_to( fname, dir = nil )
750
+ dir ||= ::File.basename(fname, '.*')
751
+ search_me = ::File.expand_path(
752
+ ::File.join(::File.dirname(fname), dir, '**', '*.rb'))
753
+
754
+ Dir.glob(search_me).sort.each {|rb| require rb}
755
+ end
756
+
757
+ # Returns the version string for the library.
758
+ #
759
+ def self.version
760
+ VERSION
761
+ end
762
+
763
+ end # Buby
764
+
765
+
766
+ # Try requiring 'burp.jar' from the Ruby lib-path
767
+ unless Buby.burp_loaded?
768
+ begin require "burp.jar"
769
+ rescue LoadError
770
+ end
771
+ end
772
+