emonti-buby 1.0.0
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.
- data/History.txt +4 -0
- data/README.rdoc +278 -0
- data/Rakefile +33 -0
- data/bin/buby +16 -0
- data/buby.gemspec +37 -0
- data/java/buby.jar +0 -0
- data/java/src/BurpExtender.java +247 -0
- data/java/src/burp/IBurpExtender.java +136 -0
- data/java/src/burp/IBurpExtenderCallbacks.java +157 -0
- data/lib/buby.rb +462 -0
- data/samples/basic.rb +42 -0
- data/spec/buby_spec.rb +7 -0
- data/spec/spec_helper.rb +16 -0
- data/tasks/ann.rake +80 -0
- data/tasks/bones.rake +20 -0
- data/tasks/gem.rake +201 -0
- data/tasks/git.rake +40 -0
- data/tasks/notes.rake +27 -0
- data/tasks/post_load.rake +34 -0
- data/tasks/rdoc.rake +51 -0
- data/tasks/rubyforge.rake +55 -0
- data/tasks/setup.rb +292 -0
- data/tasks/spec.rake +54 -0
- data/tasks/svn.rake +47 -0
- data/tasks/test.rake +40 -0
- data/tasks/zentest.rake +36 -0
- data/test/test_buby.rb +0 -0
- metadata +92 -0
data/lib/buby.rb
ADDED
@@ -0,0 +1,462 @@
|
|
1
|
+
include Java
|
2
|
+
|
3
|
+
require 'pp'
|
4
|
+
require "buby.jar"
|
5
|
+
|
6
|
+
include_class 'BurpExtender'
|
7
|
+
|
8
|
+
# Buby is a mash-up of the commercial security testing web proxy PortSwigger
|
9
|
+
# Burp Suite(tm) allowing you to add scripting to Burp. Burp is driven from
|
10
|
+
# and tied to JRuby with a Java extension using the BurpExtender API.
|
11
|
+
#
|
12
|
+
# The Buby class is an abstract implementation of a BurpExtender ruby handler.
|
13
|
+
# Included are several abstract event handlers used from the BurpExtender
|
14
|
+
# java implementation:
|
15
|
+
# * evt_extender_init
|
16
|
+
# * evt_proxy_message
|
17
|
+
# * evt_command_line_args
|
18
|
+
# * evt_register_callbacks
|
19
|
+
# * evt_application_closing
|
20
|
+
#
|
21
|
+
# This class also exposes several methods used to access Burp functionality
|
22
|
+
# and user interfaces (note also, abbreviated aliases exist for each):
|
23
|
+
# * doActiveScan
|
24
|
+
# * doPassiveScan
|
25
|
+
# * excludeFromScope
|
26
|
+
# * includeInScope
|
27
|
+
# * isInScope
|
28
|
+
# * issueAlert
|
29
|
+
# * makeHttpRequest
|
30
|
+
# * sendToIntruder
|
31
|
+
# * sendToRepeater
|
32
|
+
# * sendToSpider
|
33
|
+
#
|
34
|
+
# Credit:
|
35
|
+
# * Burp and Burp Suite are trade-marks of PortSwigger Ltd.
|
36
|
+
# Copyright 2008 PortSwigger Ltd. All rights reserved.
|
37
|
+
# See http://portswigger.net for license terms.
|
38
|
+
#
|
39
|
+
# * This ruby library and the accompanying BurpExtender.java implementation
|
40
|
+
# were written by Eric Monti @ Matasano Security.
|
41
|
+
#
|
42
|
+
# Matasano claims no professional or legal affiliation with PortSwigger LTD.
|
43
|
+
# nor do we sell or officially endorse their products.
|
44
|
+
#
|
45
|
+
# However, this author would like to express his personal and professional
|
46
|
+
# respect and appreciation for their making available the IBurpExtender
|
47
|
+
# extension API. The availability of this interface in an already great tool
|
48
|
+
# goes a long way to make Burp Suite a truly first-class application.
|
49
|
+
#
|
50
|
+
# * Forgive the name. It won out over "Burb" and "BurpRub". It's just easier
|
51
|
+
# to type and say out-loud. Mike Tracy gets full credit as official
|
52
|
+
# Buby-namer.
|
53
|
+
#
|
54
|
+
class Buby
|
55
|
+
|
56
|
+
# :stopdoc:
|
57
|
+
VERSION = '1.0.0'
|
58
|
+
LIBPATH = ::File.expand_path(::File.dirname(__FILE__)) + ::File::SEPARATOR
|
59
|
+
PATH = ::File.dirname(LIBPATH) + ::File::SEPARATOR
|
60
|
+
# :startdoc:
|
61
|
+
|
62
|
+
# Returns the internal reference to the BurpExtender instance. This
|
63
|
+
# reference gets set from Java through the evt_extender_init method.
|
64
|
+
def burp_extender; @burp_extender; end
|
65
|
+
|
66
|
+
# Returns the internal reference to the IBupExtenderCallbacks instance.
|
67
|
+
# This reference gets set from Java through the evt_register_callbacks
|
68
|
+
# method.
|
69
|
+
def burp_callbacks; @burp_callbacks; end
|
70
|
+
|
71
|
+
def _check_cb
|
72
|
+
@burp_callbacks or raise "Burp callbacks have not been set"
|
73
|
+
end
|
74
|
+
|
75
|
+
# Send an HTTP request to the Burp Scanner tool to perform an active
|
76
|
+
# vulnerability scan.
|
77
|
+
# * host = The hostname of the remote HTTP server.
|
78
|
+
# * port = The port of the remote HTTP server.
|
79
|
+
# * https = Flags whether the protocol is HTTPS or HTTP.
|
80
|
+
# * req = The full HTTP request.
|
81
|
+
def doActiveScan(host, port, https, req)
|
82
|
+
_check_cb.doActiveScan(host, port, https, req.to_java_bytes)
|
83
|
+
end
|
84
|
+
|
85
|
+
alias do_active_scan doActiveScan
|
86
|
+
alias active_scan doActiveScan
|
87
|
+
|
88
|
+
# Send an HTTP request and response to the Burp Scanner tool to perform a
|
89
|
+
# passive vulnerability scan.
|
90
|
+
# * host = The hostname of the remote HTTP server.
|
91
|
+
# * port = The port of the remote HTTP server.
|
92
|
+
# * https = Flags whether the protocol is HTTPS or HTTP.
|
93
|
+
# * req = The full HTTP request.
|
94
|
+
# * rsp = The full HTTP response.
|
95
|
+
def doPassiveScan(host, port, https, req, rsp)
|
96
|
+
_check_cb.doPassiveScan(host, port, https, req.to_java_bytes, rsp.to_java_bytes)
|
97
|
+
end
|
98
|
+
|
99
|
+
alias do_passive_scan doPassiveScan
|
100
|
+
alias passive_scan doPassiveScan
|
101
|
+
|
102
|
+
# Exclude the specified URL from the Suite-wide scope.
|
103
|
+
# * url = The URL to exclude from the Suite-wide scope.
|
104
|
+
def excludeFromScope(url)
|
105
|
+
_check_cb.excludeFromScope(java.net.URL.new(url.to_s))
|
106
|
+
end
|
107
|
+
|
108
|
+
alias exclude_from_scope excludeFromScope
|
109
|
+
alias exclude_scope excludeFromScope
|
110
|
+
|
111
|
+
# Include the specified URL in the Suite-wide scope.
|
112
|
+
# * url = The URL to exclude in the Suite-wide scope.
|
113
|
+
def includeInScope(url)
|
114
|
+
_check_cb.includeInScope(java.net.URL.new(url.to_s))
|
115
|
+
end
|
116
|
+
|
117
|
+
alias include_in_scope includeInScope
|
118
|
+
alias include_scope includeInScope
|
119
|
+
|
120
|
+
# Query whether a specified URL is within the current Suite-wide scope.
|
121
|
+
# * url = The URL to query
|
122
|
+
#
|
123
|
+
# Returns: true / false
|
124
|
+
def isInScope(url)
|
125
|
+
_check_cb.isInScope(java.net.URL.new(url.to_s))
|
126
|
+
end
|
127
|
+
|
128
|
+
alias is_in_scope isInScope
|
129
|
+
alias in_scope? isInScope
|
130
|
+
|
131
|
+
# Display a message in the Burp Suite alerts tab.
|
132
|
+
# * msg = The alert message to display.
|
133
|
+
def issueAlert(msg)
|
134
|
+
_check_cb.issueAlert(msg.to_s)
|
135
|
+
end
|
136
|
+
|
137
|
+
alias issue_alert issueAlert
|
138
|
+
alias alert issueAlert
|
139
|
+
|
140
|
+
# Issue an arbitrary HTTP request and retrieve its response
|
141
|
+
# * host = The hostname of the remote HTTP server.
|
142
|
+
# * port = The port of the remote HTTP server.
|
143
|
+
# * https = Flags whether the protocol is HTTPS or HTTP.
|
144
|
+
# * req = The full HTTP request.
|
145
|
+
#
|
146
|
+
# Returns: The full response retrieved from the remote server.
|
147
|
+
def makeHttpRequest(host, port, https, req)
|
148
|
+
String.from_java_bytes(
|
149
|
+
_check_cb.makeHttpRequest(host, port, https, req.to_java_bytes)
|
150
|
+
)
|
151
|
+
end
|
152
|
+
|
153
|
+
alias make_http_request makeHttpRequest
|
154
|
+
alias make_request makeHttpRequest
|
155
|
+
|
156
|
+
# Send an HTTP request to the Burp Intruder tool
|
157
|
+
# * host = The hostname of the remote HTTP server.
|
158
|
+
# * port = The port of the remote HTTP server.
|
159
|
+
# * https = Flags whether the protocol is HTTPS or HTTP.
|
160
|
+
# * req = The full HTTP request.
|
161
|
+
def sendToIntruder(host, port, https, req)
|
162
|
+
_check_cb.sendToIntruder(host, port, https, req.to_java_bytes)
|
163
|
+
end
|
164
|
+
|
165
|
+
alias send_to_intruder sendToIntruder
|
166
|
+
alias intruder sendToIntruder
|
167
|
+
|
168
|
+
# Send an HTTP request to the Burp Repeater tool.
|
169
|
+
# * host = The hostname of the remote HTTP server.
|
170
|
+
# * port = The port of the remote HTTP server.
|
171
|
+
# * https = Flags whether the protocol is HTTPS or HTTP.
|
172
|
+
# * req = The full HTTP request.
|
173
|
+
# * tab = The tab caption displayed in Repeater. (default: auto-generated)
|
174
|
+
def sendToRepeater(host, port, https, req, tab=nil)
|
175
|
+
_check_cb.sendToRepeater(host, port, https, req.to_java_bytes, tab)
|
176
|
+
end
|
177
|
+
|
178
|
+
alias send_to_repeater sendToRepeater
|
179
|
+
alias repeater sendToRepeater
|
180
|
+
|
181
|
+
# Send a seed URL to the Burp Spider tool.
|
182
|
+
# * url = The new seed URL to begin spidering from.
|
183
|
+
def sendToSpider(url)
|
184
|
+
_check_cb.includeInScope(java.net.URL.new(url.to_s))
|
185
|
+
end
|
186
|
+
|
187
|
+
alias send_to_spider sendToSpider
|
188
|
+
alias spider sendToSpider
|
189
|
+
|
190
|
+
|
191
|
+
### Event Handlers ###
|
192
|
+
|
193
|
+
# This method is called by the BurpExtender java implementation upon
|
194
|
+
# initialization of the BurpExtender instance for Burp. The args parameter
|
195
|
+
# is passed with a instance of the newly initialized BurpExtender instance
|
196
|
+
# so that implementations can access and extend its public interfaces.
|
197
|
+
#
|
198
|
+
# The return value is ignored.
|
199
|
+
def evt_extender_init ext
|
200
|
+
@burp_extender = ext
|
201
|
+
pp([:got_extender, ext]) if $DEBUG
|
202
|
+
end
|
203
|
+
|
204
|
+
# This method is called by the BurpExtender implementation Burp startup.
|
205
|
+
# The args parameter contains main()'s argv command-line arguments array.
|
206
|
+
#
|
207
|
+
# Note: This maps to the 'setCommandLineArgs' method in the java
|
208
|
+
# implementation of BurpExtender.
|
209
|
+
#
|
210
|
+
# The return value is ignored.
|
211
|
+
def evt_command_line_args args
|
212
|
+
pp([:got_args, args]) if $DEBUG
|
213
|
+
end
|
214
|
+
|
215
|
+
# This method is called by BurpExtender on startup to register Burp's
|
216
|
+
# IBurpExtenderCallbacks interface object.
|
217
|
+
#
|
218
|
+
# This maps to the 'registerExtenderCallbacks' method in the Java
|
219
|
+
# implementation of BurpExtender.
|
220
|
+
#
|
221
|
+
# The return value is ignored.
|
222
|
+
def evt_register_callbacks cb
|
223
|
+
@burp_callbacks = cb
|
224
|
+
cb.issueAlert("[JRuby::#{self.class}] registered callback")
|
225
|
+
pp([:got_callbacks, cb]) if $DEBUG
|
226
|
+
end
|
227
|
+
|
228
|
+
ACTION_FOLLOW_RULES = BurpExtender::ACTION_FOLLOW_RULES
|
229
|
+
ACTION_DO_INTERCEPT = BurpExtender::ACTION_DO_INTERCEPT
|
230
|
+
ACTION_DONT_INTERCEPT = BurpExtender::ACTION_DONT_INTERCEPT
|
231
|
+
ACTION_DROP = BurpExtender::ACTION_DROP
|
232
|
+
|
233
|
+
# This method is called by BurpExtender while proxying HTTP messages and
|
234
|
+
# before passing them through the Burp proxy. Implementations can use this
|
235
|
+
# method to implement arbitrary processing upon HTTP requests and responses
|
236
|
+
# such as interception, logging, modification, and so on.
|
237
|
+
#
|
238
|
+
# The 'is_req' parameter indicates whether it is a response or request.
|
239
|
+
#
|
240
|
+
# Note: This method maps to the 'processProxyMessage' method in the java
|
241
|
+
# implementation of BurpExtender.
|
242
|
+
#
|
243
|
+
# Below are the parameters descriptions based on the IBurpExtender
|
244
|
+
# javadoc. Where applicable, decriptions have been modified for
|
245
|
+
# local parameter naming and other ruby-specific details added.
|
246
|
+
#
|
247
|
+
# * msg_ref:
|
248
|
+
# An identifier which is unique to a single request/response pair. This
|
249
|
+
# can be used to correlate details of requests and responses and perform
|
250
|
+
# processing on the response message accordingly. This number also
|
251
|
+
# corresponds to the Burp UI's proxy "history" # column.
|
252
|
+
#
|
253
|
+
# * is_req: (true/false)
|
254
|
+
# Flags whether the message is a client request or a server response.
|
255
|
+
#
|
256
|
+
# * rhost:
|
257
|
+
# The hostname of the remote HTTP server.
|
258
|
+
#
|
259
|
+
# * rport:
|
260
|
+
# The port of the remote HTTP server.
|
261
|
+
#
|
262
|
+
# * is_https:
|
263
|
+
# Flags whether the protocol is HTTPS or HTTP.
|
264
|
+
#
|
265
|
+
# * http_meth:
|
266
|
+
# The method verb used in the client request.
|
267
|
+
#
|
268
|
+
# * url:
|
269
|
+
# The requested URL. Set in both the request and response.
|
270
|
+
#
|
271
|
+
# * resourceType:
|
272
|
+
# The filetype of the requested resource, or a zero-length string if the
|
273
|
+
# resource has no filetype.
|
274
|
+
#
|
275
|
+
# * status:
|
276
|
+
# The HTTP status code returned by the server. This value is nil for
|
277
|
+
# request messages.
|
278
|
+
#
|
279
|
+
# * req_content_type:
|
280
|
+
# The content-type string returned by the server. This value is nil for
|
281
|
+
# request messages.
|
282
|
+
#
|
283
|
+
# * message:
|
284
|
+
# The full HTTP message.
|
285
|
+
# **Ruby note:
|
286
|
+
# For convenience, the message is received and returned as a ruby
|
287
|
+
# String object. Internally within Burp it is handled as a java byte[]
|
288
|
+
# array. See also the notes about the return object below.
|
289
|
+
#
|
290
|
+
# * action:
|
291
|
+
# An array containing a single integer, allowing the implementation to
|
292
|
+
# communicate back to Burp Proxy a non-default interception action for
|
293
|
+
# the message. The default value is ACTION_FOLLOW_RULES (or 0).
|
294
|
+
# Possible values include:
|
295
|
+
# ACTION_FOLLOW_RULES = 0
|
296
|
+
# ACTION_DO_INTERCEPT = 1
|
297
|
+
# ACTION_DONT_INTERCEPT = 2
|
298
|
+
# ACTION_DROP = 3
|
299
|
+
#
|
300
|
+
# Refer to the BurpExtender.java source comments for more details.
|
301
|
+
#
|
302
|
+
#
|
303
|
+
# Return Value:
|
304
|
+
# Implementations should return either (a) the same object received
|
305
|
+
# in the message paramater, or (b) a different object containing a
|
306
|
+
# modified message.
|
307
|
+
#
|
308
|
+
# **IMPORTANT RUBY NOTE:
|
309
|
+
# Always be sure to return a new object if making modifications to messages.
|
310
|
+
#
|
311
|
+
# Explanation:
|
312
|
+
# The (a) and (b) convention above is followed rather literally during type
|
313
|
+
# conversion on the return value back into the java BurpExtender.
|
314
|
+
#
|
315
|
+
# When determining whether a change has been made in the message or not,
|
316
|
+
# the decision is made based on whether the object returned is the same
|
317
|
+
# as the object submitted in the call to evt_proxy_message.
|
318
|
+
#
|
319
|
+
#
|
320
|
+
# So, for example, using in-place modification of the message using range
|
321
|
+
# substring assignments or destructive method variations like String.sub!()
|
322
|
+
# and String.gsub! alone won't work because the same object gets returned
|
323
|
+
# to BurpExtender.
|
324
|
+
#
|
325
|
+
# In short, this means that if you want modifications to be made, be sure
|
326
|
+
# to return a different String than the one you got in your handler.
|
327
|
+
#
|
328
|
+
# So for example this code won't do anything at all:
|
329
|
+
#
|
330
|
+
# ...
|
331
|
+
# message.sub!(/^GET /, "HEAD ")
|
332
|
+
# return message
|
333
|
+
#
|
334
|
+
# Nor this:
|
335
|
+
#
|
336
|
+
# message[0..4] = "HEAD "
|
337
|
+
# return message
|
338
|
+
#
|
339
|
+
# But this will
|
340
|
+
#
|
341
|
+
# ...
|
342
|
+
# return message.sub(/^GET /, "HEAD ")
|
343
|
+
#
|
344
|
+
# And so will this
|
345
|
+
#
|
346
|
+
# ...
|
347
|
+
# message[0..4] = "HEAD "
|
348
|
+
# return message.dup
|
349
|
+
#
|
350
|
+
def evt_proxy_message msg_ref, is_req, rhost, rport, is_https, http_meth, url, resourceType, status, req_content_type, message, action
|
351
|
+
pp([ (is_req)? :got_proxy_request : :got_proxy_response,
|
352
|
+
[:msg_ref, msg_ref],
|
353
|
+
[:is_req, is_req],
|
354
|
+
[:rhost, rhost],
|
355
|
+
[:rport, rport],
|
356
|
+
[:is_https, is_https],
|
357
|
+
[:http_meth, http_meth],
|
358
|
+
[:url, url],
|
359
|
+
[:resourceType, resourceType],
|
360
|
+
[:status, status],
|
361
|
+
[:req_content_type, req_content_type],
|
362
|
+
[:message, message],
|
363
|
+
[:action, action[0]] ]) if $DEBUG
|
364
|
+
|
365
|
+
return message
|
366
|
+
end
|
367
|
+
|
368
|
+
# This method is called by BurpExtender right before closing the
|
369
|
+
# application. Implementations can use this method to perform cleanup
|
370
|
+
# tasks such as closing files or databases before exit.
|
371
|
+
def evt_application_closing
|
372
|
+
pp([:got_app_close]) if $DEBUG
|
373
|
+
end
|
374
|
+
|
375
|
+
# Prepares the java BurpExtender implementation with a reference
|
376
|
+
# to self as the module handler and launches burp suite.
|
377
|
+
def start(args=[])
|
378
|
+
BurpExtender.set_handler(self)
|
379
|
+
Java::Burp::StartBurp.main(args.to_java(:string))
|
380
|
+
return self
|
381
|
+
end
|
382
|
+
|
383
|
+
# Starts burp using a supplied handler class,
|
384
|
+
# h_class = Buby or a derived class. instance of which will become handler.
|
385
|
+
# args = arguments to Burp
|
386
|
+
# init_args = arguments to the handler constructor
|
387
|
+
#
|
388
|
+
# Returns the handler instance
|
389
|
+
def self.start_burp(h_class=nil, init_args=nil, args=nil)
|
390
|
+
h_class ||= self
|
391
|
+
init_args ||= []
|
392
|
+
args ||= []
|
393
|
+
h_class.new(*init_args).start(args)
|
394
|
+
end
|
395
|
+
|
396
|
+
# Attempts to load burp with require and confirm it provides the required
|
397
|
+
# class in the Java namespace.
|
398
|
+
#
|
399
|
+
# Returns: true/false depending on whether the required jar provides us
|
400
|
+
# the required class
|
401
|
+
#
|
402
|
+
# Raises: may raise the usual require exceptions if jar_path is bad.
|
403
|
+
def self.load_burp(jar_path)
|
404
|
+
require jar_path
|
405
|
+
return burp_loaded?
|
406
|
+
end
|
407
|
+
|
408
|
+
# Checks the Java namespace to see if Burp has been loaded.
|
409
|
+
def self.burp_loaded?
|
410
|
+
begin
|
411
|
+
include_class 'burp.StartBurp'
|
412
|
+
return true
|
413
|
+
rescue
|
414
|
+
return false
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
### Extra cruft added by Mr Bones:
|
419
|
+
|
420
|
+
# Returns the library path for the module. If any arguments are given,
|
421
|
+
# they will be joined to the end of the libray path using
|
422
|
+
# <tt>File.join</tt>.
|
423
|
+
#
|
424
|
+
def self.libpath( *args )
|
425
|
+
args.empty? ? LIBPATH : ::File.join(LIBPATH, args.flatten)
|
426
|
+
end
|
427
|
+
|
428
|
+
# Returns the lpath for the module. If any arguments are given,
|
429
|
+
# they will be joined to the end of the path using
|
430
|
+
# <tt>File.join</tt>.
|
431
|
+
#
|
432
|
+
def self.path( *args )
|
433
|
+
args.empty? ? PATH : ::File.join(PATH, args.flatten)
|
434
|
+
end
|
435
|
+
|
436
|
+
# Utility method used to require all files ending in .rb that lie in the
|
437
|
+
# directory below this file that has the same name as the filename passed
|
438
|
+
# in. Optionally, a specific _directory_ name can be passed in such that
|
439
|
+
# the _filename_ does not have to be equivalent to the directory.
|
440
|
+
#
|
441
|
+
def self.require_all_libs_relative_to( fname, dir = nil )
|
442
|
+
dir ||= ::File.basename(fname, '.*')
|
443
|
+
search_me = ::File.expand_path(
|
444
|
+
::File.join(::File.dirname(fname), dir, '**', '*.rb'))
|
445
|
+
|
446
|
+
Dir.glob(search_me).sort.each {|rb| require rb}
|
447
|
+
end
|
448
|
+
|
449
|
+
# Returns the version string for the library.
|
450
|
+
#
|
451
|
+
def self.version
|
452
|
+
VERSION
|
453
|
+
end
|
454
|
+
end
|
455
|
+
|
456
|
+
# Try requiring 'burp.jar' from the Ruby lib-path
|
457
|
+
unless Buby.burp_loaded?
|
458
|
+
begin require "burp.jar"
|
459
|
+
rescue LoadError
|
460
|
+
end
|
461
|
+
end
|
462
|
+
|
data/samples/basic.rb
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
#!/usr/bin/env jruby
|
2
|
+
$: << File.join(File.dirname(__FILE__), %w[.. lib])
|
3
|
+
|
4
|
+
require 'buby'
|
5
|
+
$DEBUG = true
|
6
|
+
Buby.load_burp("/path/to/burp.jar") if not Buby.burp_loaded?
|
7
|
+
buby = Buby.start_burp()
|
8
|
+
|
9
|
+
require 'net/http'
|
10
|
+
p = Net::HTTP::Proxy("localhost", 8080).start("www.google.com")
|
11
|
+
|
12
|
+
# Note: I'm using 'instance_eval' here only to stay with the flow of the
|
13
|
+
# existing IRB session. Normally, you'd probably want to implement this as
|
14
|
+
# an override in your Buby-derived class.
|
15
|
+
|
16
|
+
buby.instance_eval do
|
17
|
+
|
18
|
+
def evt_proxy_message(*param)
|
19
|
+
msg_ref, is_req, rhost, rport, is_https, http_meth, url, resourceType,
|
20
|
+
status, req_content_type, message, action = param
|
21
|
+
|
22
|
+
if is_req and http_meth=="GET"
|
23
|
+
# Change the HTTP request verb to something silly
|
24
|
+
message[0,3] = "PET"
|
25
|
+
|
26
|
+
# Forcibly disable interception in the Burp UI
|
27
|
+
action[0] = Buby::ACTION_DONT_INTERCEPT
|
28
|
+
|
29
|
+
# Return a new instance and still get $DEBUG info
|
30
|
+
return super(*param).dup
|
31
|
+
else
|
32
|
+
# Just get $DEBUG info for all other requests
|
33
|
+
return super(*param)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
# Now, make another request using the Net::HTTP client
|
40
|
+
p.get("/")
|
41
|
+
|
42
|
+
|
data/spec/buby_spec.rb
ADDED
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
|
2
|
+
require File.expand_path(
|
3
|
+
File.join(File.dirname(__FILE__), %w[.. lib buby]))
|
4
|
+
|
5
|
+
Spec::Runner.configure do |config|
|
6
|
+
# == Mock Framework
|
7
|
+
#
|
8
|
+
# RSpec uses it's own mocking framework by default. If you prefer to
|
9
|
+
# use mocha, flexmock or RR, uncomment the appropriate line:
|
10
|
+
#
|
11
|
+
# config.mock_with :mocha
|
12
|
+
# config.mock_with :flexmock
|
13
|
+
# config.mock_with :rr
|
14
|
+
end
|
15
|
+
|
16
|
+
# EOF
|
data/tasks/ann.rake
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
|
2
|
+
begin
|
3
|
+
require 'bones/smtp_tls'
|
4
|
+
rescue LoadError
|
5
|
+
require 'net/smtp'
|
6
|
+
end
|
7
|
+
require 'time'
|
8
|
+
|
9
|
+
namespace :ann do
|
10
|
+
|
11
|
+
# A prerequisites task that all other tasks depend upon
|
12
|
+
task :prereqs
|
13
|
+
|
14
|
+
file PROJ.ann.file do
|
15
|
+
ann = PROJ.ann
|
16
|
+
puts "Generating #{ann.file}"
|
17
|
+
File.open(ann.file,'w') do |fd|
|
18
|
+
fd.puts("#{PROJ.name} version #{PROJ.version}")
|
19
|
+
fd.puts(" by #{Array(PROJ.authors).first}") if PROJ.authors
|
20
|
+
fd.puts(" #{PROJ.url}") if PROJ.url.valid?
|
21
|
+
fd.puts(" (the \"#{PROJ.release_name}\" release)") if PROJ.release_name
|
22
|
+
fd.puts
|
23
|
+
fd.puts("== DESCRIPTION")
|
24
|
+
fd.puts
|
25
|
+
fd.puts(PROJ.description)
|
26
|
+
fd.puts
|
27
|
+
fd.puts(PROJ.changes.sub(%r/^.*$/, '== CHANGES'))
|
28
|
+
fd.puts
|
29
|
+
ann.paragraphs.each do |p|
|
30
|
+
fd.puts "== #{p.upcase}"
|
31
|
+
fd.puts
|
32
|
+
fd.puts paragraphs_of(PROJ.readme_file, p).join("\n\n")
|
33
|
+
fd.puts
|
34
|
+
end
|
35
|
+
fd.puts ann.text if ann.text
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
desc "Create an announcement file"
|
40
|
+
task :announcement => ['ann:prereqs', PROJ.ann.file]
|
41
|
+
|
42
|
+
desc "Send an email announcement"
|
43
|
+
task :email => ['ann:prereqs', PROJ.ann.file] do
|
44
|
+
ann = PROJ.ann
|
45
|
+
from = ann.email[:from] || Array(PROJ.authors).first || PROJ.email
|
46
|
+
to = Array(ann.email[:to])
|
47
|
+
|
48
|
+
### build a mail header for RFC 822
|
49
|
+
rfc822msg = "From: #{from}\n"
|
50
|
+
rfc822msg << "To: #{to.join(',')}\n"
|
51
|
+
rfc822msg << "Subject: [ANN] #{PROJ.name} #{PROJ.version}"
|
52
|
+
rfc822msg << " (#{PROJ.release_name})" if PROJ.release_name
|
53
|
+
rfc822msg << "\n"
|
54
|
+
rfc822msg << "Date: #{Time.new.rfc822}\n"
|
55
|
+
rfc822msg << "Message-Id: "
|
56
|
+
rfc822msg << "<#{"%.8f" % Time.now.to_f}@#{ann.email[:domain]}>\n\n"
|
57
|
+
rfc822msg << File.read(ann.file)
|
58
|
+
|
59
|
+
params = [:server, :port, :domain, :acct, :passwd, :authtype].map do |key|
|
60
|
+
ann.email[key]
|
61
|
+
end
|
62
|
+
|
63
|
+
params[3] = PROJ.email if params[3].nil?
|
64
|
+
|
65
|
+
if params[4].nil?
|
66
|
+
STDOUT.write "Please enter your e-mail password (#{params[3]}): "
|
67
|
+
params[4] = STDIN.gets.chomp
|
68
|
+
end
|
69
|
+
|
70
|
+
### send email
|
71
|
+
Net::SMTP.start(*params) {|smtp| smtp.sendmail(rfc822msg, from, to)}
|
72
|
+
end
|
73
|
+
end # namespace :ann
|
74
|
+
|
75
|
+
desc 'Alias to ann:announcement'
|
76
|
+
task :ann => 'ann:announcement'
|
77
|
+
|
78
|
+
CLOBBER << PROJ.ann.file
|
79
|
+
|
80
|
+
# EOF
|
data/tasks/bones.rake
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
if HAVE_BONES
|
3
|
+
|
4
|
+
namespace :bones do
|
5
|
+
|
6
|
+
desc 'Show the PROJ open struct'
|
7
|
+
task :debug do |t|
|
8
|
+
atr = if t.application.top_level_tasks.length == 2
|
9
|
+
t.application.top_level_tasks.pop
|
10
|
+
end
|
11
|
+
|
12
|
+
if atr then Bones::Debug.show_attr(PROJ, atr)
|
13
|
+
else Bones::Debug.show PROJ end
|
14
|
+
end
|
15
|
+
|
16
|
+
end # namespace :bones
|
17
|
+
|
18
|
+
end # HAVE_BONES
|
19
|
+
|
20
|
+
# EOF
|