ronin-web 0.1.1 → 0.1.2
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 +10 -0
- data/Manifest.txt +1 -0
- data/README.txt +4 -3
- data/Rakefile +1 -1
- data/bin/ronin-web +5 -0
- data/lib/ronin/web/proxy.rb +124 -0
- data/lib/ronin/web/server.rb +24 -23
- data/lib/ronin/web/spider.rb +11 -21
- data/lib/ronin/web/version.rb +1 -1
- data/spec/spec_helper.rb +1 -1
- data/spec/web/helpers/server.rb +8 -0
- data/spec/web/server_spec.rb +11 -11
- metadata +5 -5
data/History.txt
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
=== 0.1.2 / 2009-03-28
|
2
|
+
|
3
|
+
* Added Ronin::Web::Proxy.
|
4
|
+
* Added diagnostic messages to Ronin::Web::Spider.
|
5
|
+
* Fixed Rack 0.9.1 compatibility bugs in Ronin::Web::Server.
|
6
|
+
* Server#response now uses Rack::Response.
|
7
|
+
* Ronin::Web::Server now uses a Rack::Request object instead of the
|
8
|
+
standard env Hash.
|
9
|
+
* Updated specs for Ronin::Web::Server.
|
10
|
+
|
1
11
|
=== 0.1.1 / 2009-02-23
|
2
12
|
|
3
13
|
* Added a git style sub-command (<tt>ronin-web</tt>) which starts the Ronin
|
data/Manifest.txt
CHANGED
@@ -14,6 +14,7 @@ lib/ronin/web/extensions/nokogiri/xml/attr.rb
|
|
14
14
|
lib/ronin/web/extensions/nokogiri/xml/element.rb
|
15
15
|
lib/ronin/web/extensions/nokogiri/xml/document.rb
|
16
16
|
lib/ronin/web/server.rb
|
17
|
+
lib/ronin/web/proxy.rb
|
17
18
|
lib/ronin/web/spider.rb
|
18
19
|
lib/ronin/web/web.rb
|
19
20
|
lib/ronin/web/version.rb
|
data/README.txt
CHANGED
@@ -41,8 +41,9 @@ of Ronin.
|
|
41
41
|
|
42
42
|
* Web access (utilizing Mechanize and Nokogiri).
|
43
43
|
* Integrates Spidr into Ronin::Web::Spider.
|
44
|
-
* Provides Ronin::Web::Server, a customizable Rack
|
45
|
-
path and host-name routing.
|
44
|
+
* Provides Ronin::Web::Server, a customizable Rack based Web Server that
|
45
|
+
supports path and host-name routing.
|
46
|
+
* Provides Ronin::Web::Proxy, a configurable Rack based Web Proxy.
|
46
47
|
|
47
48
|
== REQUIREMENTS:
|
48
49
|
|
@@ -50,7 +51,7 @@ of Ronin.
|
|
50
51
|
* {mechanize}[http://mechanize.rubyforge.org/] >= 0.9.0
|
51
52
|
* {spidr}[http://spidr.rubyforge.org/] >= 0.1.3
|
52
53
|
* {rack}[http://rack.rubyforge.org/] >= 0.9.1
|
53
|
-
* {ronin}[http://ronin.rubyforge.org/] >= 0.
|
54
|
+
* {ronin}[http://ronin.rubyforge.org/] >= 0.2.2
|
54
55
|
|
55
56
|
== INSTALL:
|
56
57
|
|
data/Rakefile
CHANGED
data/bin/ronin-web
CHANGED
@@ -0,0 +1,124 @@
|
|
1
|
+
#
|
2
|
+
#--
|
3
|
+
# Ronin Web - A Ruby library for Ronin that provides support for web
|
4
|
+
# scraping and spidering functionality.
|
5
|
+
#
|
6
|
+
# Copyright (c) 2006-2009 Hal Brodigan (postmodern.mod3 at gmail.com)
|
7
|
+
#
|
8
|
+
# This program is free software; you can redistribute it and/or modify
|
9
|
+
# it under the terms of the GNU General Public License as published by
|
10
|
+
# the Free Software Foundation; either version 2 of the License, or
|
11
|
+
# (at your option) any later version.
|
12
|
+
#
|
13
|
+
# This program is distributed in the hope that it will be useful,
|
14
|
+
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
15
|
+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
16
|
+
# GNU General Public License for more details.
|
17
|
+
#
|
18
|
+
# You should have received a copy of the GNU General Public License
|
19
|
+
# along with this program; if not, write to the Free Software
|
20
|
+
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
21
|
+
#++
|
22
|
+
#
|
23
|
+
|
24
|
+
require 'ronin/web/server'
|
25
|
+
require 'ronin/network/http'
|
26
|
+
|
27
|
+
require 'net/http'
|
28
|
+
|
29
|
+
module Ronin
|
30
|
+
module Web
|
31
|
+
class Proxy < Server
|
32
|
+
|
33
|
+
# The default HTTP Request to use
|
34
|
+
DEFAULT_HTTP_REQUEST = Net::HTTP::Get
|
35
|
+
|
36
|
+
#
|
37
|
+
# Creates a new Web Proxy using the given configuration _block_.
|
38
|
+
#
|
39
|
+
# _options_ may contain the following keys:
|
40
|
+
# <tt>:host</tt>:: The host to bind to.
|
41
|
+
# <tt>:port</tt>:: The port to listen on.
|
42
|
+
# <tt>:config</tt>:: A +Hash+ of configurable variables to be used
|
43
|
+
# in responses.
|
44
|
+
#
|
45
|
+
def initialize(options={},&block)
|
46
|
+
super(options)
|
47
|
+
|
48
|
+
@default = method(:proxy)
|
49
|
+
|
50
|
+
instance_eval(&block) if block
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# Proxies the specified Rack _request_ and returns a corresponding
|
55
|
+
# Rack response.
|
56
|
+
#
|
57
|
+
def proxy(request)
|
58
|
+
server_response = http_response(request)
|
59
|
+
server_headers = server_response.to_hash
|
60
|
+
body = (server_response.body || '')
|
61
|
+
|
62
|
+
return response(body,server_headers)
|
63
|
+
end
|
64
|
+
|
65
|
+
protected
|
66
|
+
|
67
|
+
#
|
68
|
+
# Returns the Net::HTTP Request class that represents the specified
|
69
|
+
# HTTP _request_method_.
|
70
|
+
#
|
71
|
+
# http_class('POST')
|
72
|
+
# # => Net::HTTP::Post
|
73
|
+
#
|
74
|
+
def http_class(request_method)
|
75
|
+
http_method = request_method.downcase.capitalize
|
76
|
+
http_class = DEFAULT_HTTP_REQUEST
|
77
|
+
|
78
|
+
if Net::HTTP.const_defined?(http_method)
|
79
|
+
http_class = Net::HTTP.const_get(http_method)
|
80
|
+
|
81
|
+
unless http_class.kind_of?(Net::HTTPRequest)
|
82
|
+
http_class = DEFAULT_HTTP_REQUEST
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
return http_class
|
87
|
+
end
|
88
|
+
|
89
|
+
#
|
90
|
+
# Converts the Rack headers within the specified _request_ to
|
91
|
+
# Net::HTTP formatted HTTP headers.
|
92
|
+
#
|
93
|
+
def http_headers(request)
|
94
|
+
client_headers = {}
|
95
|
+
|
96
|
+
request.env.each do |name,value|
|
97
|
+
if name =~ /^HTTP_/
|
98
|
+
header_name = name.gsub(/^HTTP_/,'').split('_').map { |word|
|
99
|
+
word.capitalize
|
100
|
+
}.join('-')
|
101
|
+
|
102
|
+
client_headers[header_name] = value
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
return client_headers
|
107
|
+
end
|
108
|
+
|
109
|
+
#
|
110
|
+
# Returns the Net::HTTP response for the specified Rack _request_.
|
111
|
+
#
|
112
|
+
def http_response(request)
|
113
|
+
path = request.fullpath
|
114
|
+
http_method = http_class(request.request_method)
|
115
|
+
client_request = http_method.new(path,http_headers(request))
|
116
|
+
|
117
|
+
Net.http_session(:host => request.host, :port => request.port) do |http|
|
118
|
+
return http.request(client_request)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
data/lib/ronin/web/server.rb
CHANGED
@@ -206,8 +206,8 @@ module Ronin
|
|
206
206
|
#
|
207
207
|
# Returns the HTTP 404 Not Found message for the requested path.
|
208
208
|
#
|
209
|
-
def not_found(
|
210
|
-
path =
|
209
|
+
def not_found(request)
|
210
|
+
path = request.path_info
|
211
211
|
body = %{<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
|
212
212
|
<html>
|
213
213
|
<head>
|
@@ -228,14 +228,14 @@ module Ronin
|
|
228
228
|
# an index file. If no index file can be found or _path_ points to a
|
229
229
|
# non-existant file, a "404 Not Found" response will be returned.
|
230
230
|
#
|
231
|
-
def return_file(path,
|
231
|
+
def return_file(path,request)
|
232
232
|
if !(File.exists?(path))
|
233
|
-
return not_found(
|
233
|
+
return not_found(request)
|
234
234
|
end
|
235
235
|
|
236
236
|
if File.directory?(path)
|
237
237
|
unless (path = index_of(path))
|
238
|
-
return not_found(
|
238
|
+
return not_found(request)
|
239
239
|
end
|
240
240
|
end
|
241
241
|
|
@@ -251,8 +251,8 @@ module Ronin
|
|
251
251
|
#
|
252
252
|
# response("<data>lol</data>", :content_type => 'text/xml')
|
253
253
|
#
|
254
|
-
def response(body=
|
255
|
-
status = (options.delete(:status) || 200)
|
254
|
+
def response(body='',options={},&block)
|
255
|
+
status = (options.delete(:status) || options.delete('Status') || 200)
|
256
256
|
headers = {}
|
257
257
|
|
258
258
|
options.each do |name,value|
|
@@ -263,7 +263,7 @@ module Ronin
|
|
263
263
|
headers[header_name] = value.to_s
|
264
264
|
end
|
265
265
|
|
266
|
-
return Rack::Response.new(body,status,headers,&block)
|
266
|
+
return Rack::Response.new(body,status,headers,&block).finish
|
267
267
|
end
|
268
268
|
|
269
269
|
#
|
@@ -288,7 +288,7 @@ module Ronin
|
|
288
288
|
# Use the given _server_ or _block_ as the default route for all
|
289
289
|
# other requests.
|
290
290
|
#
|
291
|
-
# default do |
|
291
|
+
# default do |request|
|
292
292
|
# [200, {'Content-Type' => 'text/html'}, 'lol train']
|
293
293
|
# end
|
294
294
|
#
|
@@ -302,7 +302,7 @@ module Ronin
|
|
302
302
|
# requests to host names which match the specified _pattern_.
|
303
303
|
#
|
304
304
|
# hosts_like(/^a[0-9]\./) do
|
305
|
-
# map('/download/') do |
|
305
|
+
# map('/download/') do |request|
|
306
306
|
# ...
|
307
307
|
# end
|
308
308
|
# end
|
@@ -315,7 +315,7 @@ module Ronin
|
|
315
315
|
# Registers the given _server_ or _block_ to be called when receiving
|
316
316
|
# requests for paths which match the specified _pattern_.
|
317
317
|
#
|
318
|
-
# paths_like(/\.xml$/) do |
|
318
|
+
# paths_like(/\.xml$/) do |request|
|
319
319
|
# ...
|
320
320
|
# end
|
321
321
|
#
|
@@ -340,7 +340,7 @@ module Ronin
|
|
340
340
|
#
|
341
341
|
# Binds the specified URL _path_ to the given _server_ or _block_.
|
342
342
|
#
|
343
|
-
# bind '/secrets.xml' do |
|
343
|
+
# bind '/secrets.xml' do |request|
|
344
344
|
# [200, {'Content-Type' => 'text/xml'}, "Made you look."]
|
345
345
|
# end
|
346
346
|
#
|
@@ -353,7 +353,7 @@ module Ronin
|
|
353
353
|
# Binds the specified URL directory _path_ to the given
|
354
354
|
# _server_ or _block_.
|
355
355
|
#
|
356
|
-
# map '/downloads' do |
|
356
|
+
# map '/downloads' do |request|
|
357
357
|
# response(
|
358
358
|
# "Your somewhere inside the downloads directory",
|
359
359
|
# :content_type' => 'text/xml'
|
@@ -375,11 +375,11 @@ module Ronin
|
|
375
375
|
file = File.expand_path(file)
|
376
376
|
content_type = (options[:content_type] || content_type_for(file))
|
377
377
|
|
378
|
-
bind(path) do |
|
378
|
+
bind(path) do |request|
|
379
379
|
if File.file?(file)
|
380
|
-
return_file(file,
|
380
|
+
return_file(file,request)
|
381
381
|
else
|
382
|
-
not_found(
|
382
|
+
not_found(request)
|
383
383
|
end
|
384
384
|
end
|
385
385
|
end
|
@@ -394,14 +394,14 @@ module Ronin
|
|
394
394
|
sub_dirs = path.split('/')
|
395
395
|
directory = File.expand_path(directory)
|
396
396
|
|
397
|
-
map(path) do |
|
398
|
-
http_path = File.expand_path(
|
397
|
+
map(path) do |request|
|
398
|
+
http_path = File.expand_path(request.path_info)
|
399
399
|
http_dirs = http_path.split('/')
|
400
400
|
|
401
401
|
sub_path = http_dirs[sub_dirs.length..-1].join('/')
|
402
402
|
absolute_path = File.join(directory,sub_path)
|
403
403
|
|
404
|
-
return_file(absolute_path,
|
404
|
+
return_file(absolute_path,request)
|
405
405
|
end
|
406
406
|
end
|
407
407
|
|
@@ -419,6 +419,7 @@ module Ronin
|
|
419
419
|
def call(env)
|
420
420
|
http_host = env['HTTP_HOST']
|
421
421
|
http_path = File.expand_path(env['PATH_INFO'])
|
422
|
+
request = Rack::Request.new(env)
|
422
423
|
|
423
424
|
if http_host
|
424
425
|
if (server = virtual_host(http_host))
|
@@ -428,12 +429,12 @@ module Ronin
|
|
428
429
|
|
429
430
|
if http_path
|
430
431
|
if (block = @paths[http_path])
|
431
|
-
return block.call(
|
432
|
+
return block.call(request)
|
432
433
|
end
|
433
434
|
|
434
435
|
@path_patterns.each do |pattern,block|
|
435
436
|
if http_path.match(pattern)
|
436
|
-
return block.call(
|
437
|
+
return block.call(request)
|
437
438
|
end
|
438
439
|
end
|
439
440
|
|
@@ -446,11 +447,11 @@ module Ronin
|
|
446
447
|
}.sort.last
|
447
448
|
|
448
449
|
if (sub_dir && (block = @directories[sub_dir]))
|
449
|
-
return block.call(
|
450
|
+
return block.call(request)
|
450
451
|
end
|
451
452
|
end
|
452
453
|
|
453
|
-
return @default.call(
|
454
|
+
return @default.call(request)
|
454
455
|
end
|
455
456
|
|
456
457
|
#
|
data/lib/ronin/web/spider.rb
CHANGED
@@ -22,12 +22,16 @@
|
|
22
22
|
#
|
23
23
|
|
24
24
|
require 'ronin/web/web'
|
25
|
+
require 'ronin/ui/diagnostics'
|
25
26
|
|
26
27
|
require 'spidr/agent'
|
27
28
|
|
28
29
|
module Ronin
|
29
30
|
module Web
|
30
31
|
class Spider < Spidr::Agent
|
32
|
+
|
33
|
+
include UI::Diagnostics
|
34
|
+
|
31
35
|
#
|
32
36
|
# Creates a new Spider object with the given _options_ and
|
33
37
|
# _block_. If a _block_ is given, it will be passed the newly created
|
@@ -52,28 +56,14 @@ module Ronin
|
|
52
56
|
# <tt>:ignore_exts</tt>:: An +Array+ of File extension patterns to not
|
53
57
|
# visit.
|
54
58
|
#
|
55
|
-
def
|
56
|
-
|
57
|
-
end
|
59
|
+
def initialize(options={},&block)
|
60
|
+
super(default_options.merge(options))
|
58
61
|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
# will be passed the newly created Spider object, before the agent
|
63
|
-
# begins spidering.
|
64
|
-
#
|
65
|
-
def self.host(name,options={},&block)
|
66
|
-
super(name,self.default_options.merge(options),&block)
|
67
|
-
end
|
62
|
+
every_url do |url|
|
63
|
+
print_info("Spidering #{url}")
|
64
|
+
end
|
68
65
|
|
69
|
-
|
70
|
-
# Creates a new Spider object with the given _options_ and will begin
|
71
|
-
# spidering the host of the specified _url_. If a _block_ is
|
72
|
-
# given it will be passed the newly created Spider object, before
|
73
|
-
# the agent begins spidering.
|
74
|
-
#
|
75
|
-
def self.site(url,options={},&block)
|
76
|
-
super(url,self.default_options.merge(options),&block)
|
66
|
+
block.call(self) if block
|
77
67
|
end
|
78
68
|
|
79
69
|
protected
|
@@ -81,7 +71,7 @@ module Ronin
|
|
81
71
|
#
|
82
72
|
# Returns the default options for Spider.
|
83
73
|
#
|
84
|
-
def
|
74
|
+
def default_options
|
85
75
|
{:proxy => Web.proxy, :user_agent => Web.user_agent}
|
86
76
|
end
|
87
77
|
end
|
data/lib/ronin/web/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
data/spec/web/helpers/server.rb
CHANGED
data/spec/web/server_spec.rb
CHANGED
@@ -75,68 +75,68 @@ describe Web::Server do
|
|
75
75
|
it "should have a default response for un-matched paths" do
|
76
76
|
path = '/test/default'
|
77
77
|
|
78
|
-
@server
|
78
|
+
get_path(@server,path).body.should == ['This is default.']
|
79
79
|
end
|
80
80
|
|
81
81
|
it "should bind a path to a certain response" do
|
82
82
|
path = '/test/bind.xml'
|
83
83
|
|
84
|
-
@server
|
84
|
+
get_path(@server,path).body.should == ['<secret/>']
|
85
85
|
end
|
86
86
|
|
87
87
|
it "should match paths with patterns" do
|
88
88
|
path = '/test/path_patterns/secret.pdf'
|
89
89
|
|
90
|
-
@server
|
90
|
+
get_path(@server,path).body.should == ['No secrets here.']
|
91
91
|
end
|
92
92
|
|
93
93
|
it "should match paths to sub-directories" do
|
94
94
|
path = '/test/map/impossible.html'
|
95
95
|
|
96
|
-
@server
|
96
|
+
get_path(@server,path).body.should == ['mapped']
|
97
97
|
end
|
98
98
|
|
99
99
|
it "should return a response for a file" do
|
100
100
|
path = '/test/file.txt'
|
101
101
|
|
102
|
-
@server
|
102
|
+
get_path(@server,path).body.should == ["This is a test.\n"]
|
103
103
|
end
|
104
104
|
|
105
105
|
it "should return files from bound directories" do
|
106
106
|
path = '/test/directory/test.txt'
|
107
107
|
|
108
|
-
@server
|
108
|
+
get_path(@server,path).body.should == ["This is a test.\n"]
|
109
109
|
end
|
110
110
|
|
111
111
|
it "should return the index file for a bound directory" do
|
112
112
|
path = '/test/directory/'
|
113
113
|
|
114
|
-
@server
|
114
|
+
get_path(@server,path).body.should == ["Index of files.\n"]
|
115
115
|
end
|
116
116
|
|
117
117
|
it "should match virtual hosts" do
|
118
118
|
url = 'http://virtual.host.com/test/virtual_host.xml'
|
119
119
|
|
120
|
-
@server
|
120
|
+
get_url(@server,url).body.should == ['<virtual/>']
|
121
121
|
end
|
122
122
|
|
123
123
|
it "should match virtual hosts with patterns" do
|
124
124
|
url = 'http://virtual0.host.com/test/virtual_host_patterns.xml'
|
125
125
|
|
126
|
-
@server
|
126
|
+
get_url(@server,url).body.should == ['<virtual-patterns/>']
|
127
127
|
end
|
128
128
|
|
129
129
|
it "should provide access to servers via their host-names" do
|
130
130
|
virtual_host = @server.virtual_host('virtual.host.com')
|
131
131
|
url = 'http://virtual.host.com/test/virtual_host.xml'
|
132
132
|
|
133
|
-
virtual_host
|
133
|
+
get_url(virtual_host,url).body.should == ['<virtual/>']
|
134
134
|
end
|
135
135
|
|
136
136
|
it "should provide access to servers via their host-names that match virtual host patterns" do
|
137
137
|
virtual_host = @server.virtual_host('virtual1.host.com')
|
138
138
|
url = 'http://virtual0.host.com/test/virtual_host_patterns.xml'
|
139
139
|
|
140
|
-
virtual_host
|
140
|
+
get_url(virtual_host,url).body.should == ['<virtual-patterns/>']
|
141
141
|
end
|
142
142
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ronin-web
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Postmodern
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-03-28 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -60,7 +60,7 @@ dependencies:
|
|
60
60
|
requirements:
|
61
61
|
- - ">="
|
62
62
|
- !ruby/object:Gem::Version
|
63
|
-
version: 0.2.
|
63
|
+
version: 0.2.2
|
64
64
|
version:
|
65
65
|
- !ruby/object:Gem::Dependency
|
66
66
|
name: hoe
|
@@ -70,7 +70,7 @@ dependencies:
|
|
70
70
|
requirements:
|
71
71
|
- - ">="
|
72
72
|
- !ruby/object:Gem::Version
|
73
|
-
version: 1.
|
73
|
+
version: 1.11.0
|
74
74
|
version:
|
75
75
|
description: Ronin Web is a Ruby library for Ronin that provides support for web scraping and spidering functionality. Ronin is a Ruby platform designed for information security and data exploration tasks. Ronin allows for the rapid development and distribution of code over many of the common Source-Code-Management (SCM) systems.
|
76
76
|
email:
|
@@ -83,7 +83,6 @@ extra_rdoc_files:
|
|
83
83
|
- History.txt
|
84
84
|
- Manifest.txt
|
85
85
|
- README.txt
|
86
|
-
- spec/web/helpers/root/test.txt
|
87
86
|
files:
|
88
87
|
- History.txt
|
89
88
|
- Manifest.txt
|
@@ -101,6 +100,7 @@ files:
|
|
101
100
|
- lib/ronin/web/extensions/nokogiri/xml/element.rb
|
102
101
|
- lib/ronin/web/extensions/nokogiri/xml/document.rb
|
103
102
|
- lib/ronin/web/server.rb
|
103
|
+
- lib/ronin/web/proxy.rb
|
104
104
|
- lib/ronin/web/spider.rb
|
105
105
|
- lib/ronin/web/web.rb
|
106
106
|
- lib/ronin/web/version.rb
|