buby 1.1.6-java

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+