ronin-web 0.1.3 → 0.2.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.tar.gz.sig +0 -0
- data/History.txt +25 -0
- data/Manifest.txt +36 -4
- data/README.txt +67 -64
- data/Rakefile +12 -3
- data/bin/ronin-web +1 -1
- data/lib/ronin/network/helpers/web.rb +221 -0
- data/lib/ronin/web.rb +1 -2
- data/lib/ronin/web/extensions.rb +0 -2
- data/lib/ronin/web/extensions/nokogiri.rb +0 -23
- data/lib/ronin/web/proxy.rb +3 -103
- data/lib/ronin/web/proxy/app.rb +31 -0
- data/lib/ronin/web/proxy/base.rb +41 -0
- data/lib/ronin/web/proxy/web.rb +42 -0
- data/lib/ronin/web/server.rb +3 -530
- data/lib/ronin/web/server/app.rb +31 -0
- data/lib/ronin/web/server/base.rb +334 -0
- data/lib/ronin/web/server/files.rb +92 -0
- data/lib/ronin/web/server/helpers.rb +25 -0
- data/lib/ronin/web/server/helpers/files.rb +126 -0
- data/lib/ronin/web/server/helpers/hosts.rb +72 -0
- data/lib/ronin/web/server/helpers/proxy.rb +153 -0
- data/lib/ronin/web/server/helpers/rendering.rb +36 -0
- data/lib/ronin/web/server/hosts.rb +86 -0
- data/lib/ronin/web/server/proxy.rb +116 -0
- data/lib/ronin/web/server/web.rb +62 -0
- data/lib/ronin/web/spider.rb +53 -26
- data/lib/ronin/web/version.rb +1 -3
- data/lib/ronin/web/web.rb +253 -95
- data/spec/spec_helper.rb +1 -1
- data/spec/web/proxy/base_spec.rb +9 -0
- data/spec/web/server/base_spec.rb +86 -0
- data/spec/web/server/classes/files/dir/file.txt +1 -0
- data/spec/web/server/classes/files/dir/index.html +1 -0
- data/spec/web/server/classes/files/dir2/file2.txt +1 -0
- data/spec/web/server/classes/files/dir3/page.xml +4 -0
- data/spec/web/server/classes/files/file.txt +1 -0
- data/spec/web/server/classes/files_app.rb +27 -0
- data/spec/web/server/classes/hosts_app.rb +40 -0
- data/spec/web/server/classes/proxy_app.rb +45 -0
- data/spec/web/server/classes/public1/static1.txt +1 -0
- data/spec/web/server/classes/public2/static2.txt +1 -0
- data/spec/web/server/classes/sub_app.rb +13 -0
- data/spec/web/server/classes/test_app.rb +20 -0
- data/spec/web/server/files_spec.rb +74 -0
- data/spec/web/server/helpers/server.rb +42 -0
- data/spec/web/server/hosts_spec.rb +55 -0
- data/spec/web/server/proxy_spec.rb +49 -0
- data/tasks/spec.rb +1 -0
- data/tasks/yard.rb +13 -0
- metadata +76 -17
- metadata.gz.sig +0 -0
- data/TODO.txt +0 -7
- data/lib/ronin/sessions/web.rb +0 -80
- data/lib/ronin/web/fingerprint.rb +0 -76
- data/spec/web/server_spec.rb +0 -142
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,86 @@
|
|
1
|
+
require 'ronin/web/server/base'
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'web/server/classes/test_app'
|
5
|
+
require 'web/server/helpers/server'
|
6
|
+
|
7
|
+
describe Web::Server::Base do
|
8
|
+
include Helpers::Web::Server
|
9
|
+
|
10
|
+
before(:all) do
|
11
|
+
self.app = TestApp
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should define a set of index file-names to search for" do
|
15
|
+
TestApp.indices.should == TestApp::DEFAULT_INDICES.to_set
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should allow for defining new index file-names to search for" do
|
19
|
+
TestApp.index 'index.xml'
|
20
|
+
TestApp.indices.include?('index.xml').should == true
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should find a suitable Rack::Handler for the web server" do
|
24
|
+
TestApp.handler_class.should_not be_nil
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should still bind blocks to paths" do
|
28
|
+
get '/tests/get'
|
29
|
+
|
30
|
+
last_response.should be_ok
|
31
|
+
last_response.body.should == 'block tested'
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should bind a block to a path for all request types" do
|
35
|
+
post '/tests/any'
|
36
|
+
|
37
|
+
last_response.should be_ok
|
38
|
+
last_response.body.should == 'any tested'
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should have a default response" do
|
42
|
+
get '/totally/non/existant/path'
|
43
|
+
|
44
|
+
last_response.should_not be_ok
|
45
|
+
last_response.body.should be_empty
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should allow for defining custom responses" do
|
49
|
+
TestApp.default do
|
50
|
+
halt 404, 'nothing to see here'
|
51
|
+
end
|
52
|
+
|
53
|
+
get '/whats/here'
|
54
|
+
|
55
|
+
last_response.should_not be_ok
|
56
|
+
last_response.body.should == 'nothing to see here'
|
57
|
+
end
|
58
|
+
|
59
|
+
it "should map paths to sub-apps" do
|
60
|
+
get '/tests/subapp/'
|
61
|
+
|
62
|
+
last_response.should be_ok
|
63
|
+
last_response.body.should == 'SubApp'
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should modify the path_info as it maps paths to sub-apps" do
|
67
|
+
get '/tests/subapp/hello'
|
68
|
+
|
69
|
+
last_response.should be_ok
|
70
|
+
last_response.body.should == 'SubApp greets you'
|
71
|
+
end
|
72
|
+
|
73
|
+
it "should host static content from public directories" do
|
74
|
+
get '/static1.txt'
|
75
|
+
|
76
|
+
last_response.should be_ok
|
77
|
+
last_response.body.should == "Static file1.\n"
|
78
|
+
end
|
79
|
+
|
80
|
+
it "should host static content from multiple public directories" do
|
81
|
+
get '/static2.txt'
|
82
|
+
|
83
|
+
last_response.should be_ok
|
84
|
+
last_response.body.should == "Static file2.\n"
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Another file.
|
@@ -0,0 +1 @@
|
|
1
|
+
The index.
|
@@ -0,0 +1 @@
|
|
1
|
+
Second file.
|
@@ -0,0 +1 @@
|
|
1
|
+
A file.
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'ronin/web/server/base'
|
2
|
+
|
3
|
+
class FilesApp < Ronin::Web::Server::Base
|
4
|
+
|
5
|
+
file '/tests/file',
|
6
|
+
File.join(File.dirname(__FILE__),'files','file.txt')
|
7
|
+
|
8
|
+
file '/tests/file/missing', 'should_be_missing'
|
9
|
+
|
10
|
+
get '/tests/content_type/custom' do
|
11
|
+
return_file File.join(File.dirname(__FILE__),'files','dir3','page.xml'),
|
12
|
+
'text/plain'
|
13
|
+
end
|
14
|
+
|
15
|
+
file '/tests/content_type',
|
16
|
+
File.join(File.dirname(__FILE__),'files','dir3','page.xml')
|
17
|
+
|
18
|
+
directory '/tests/directory',
|
19
|
+
File.join(File.dirname(__FILE__),'files','dir')
|
20
|
+
|
21
|
+
directory '/tests/directory',
|
22
|
+
File.join(File.dirname(__FILE__),'files','dir2')
|
23
|
+
|
24
|
+
directory '/tests/directory/no_index',
|
25
|
+
File.join(File.dirname(__FILE__),'files','dir3')
|
26
|
+
|
27
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'ronin/web/server/base'
|
2
|
+
|
3
|
+
class FTPApp < Ronin::Web::Server::Base
|
4
|
+
|
5
|
+
get '/file' do
|
6
|
+
'FTP File'
|
7
|
+
end
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
class WWWApp < Ronin::Web::Server::Base
|
12
|
+
|
13
|
+
get '/file' do
|
14
|
+
'WWW File'
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
class HostsApp < Ronin::Web::Server::Base
|
20
|
+
|
21
|
+
get '/tests/for_host' do
|
22
|
+
for_host('localhost') do
|
23
|
+
'Admin Response'
|
24
|
+
end
|
25
|
+
|
26
|
+
for_host(/downloads/) do
|
27
|
+
'Download Response'
|
28
|
+
end
|
29
|
+
|
30
|
+
'Generic Response'
|
31
|
+
end
|
32
|
+
|
33
|
+
host 'example.com', WWWApp
|
34
|
+
hosts_like /^ftp\./, FTPApp
|
35
|
+
|
36
|
+
get '/file' do
|
37
|
+
'Generic File'
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'ronin/web/server/base'
|
2
|
+
|
3
|
+
class ProxyApp < Ronin::Web::Server::Base
|
4
|
+
|
5
|
+
get '/' do
|
6
|
+
proxy
|
7
|
+
end
|
8
|
+
|
9
|
+
get '/reddit/erlang' do
|
10
|
+
proxy(:host => 'www.reddit.com', :path => '/r/erlang')
|
11
|
+
end
|
12
|
+
|
13
|
+
get '/r/erlang' do
|
14
|
+
proxy do |body|
|
15
|
+
for_host(/reddit\./) do
|
16
|
+
body.gsub(/erlang/i,'Fixed Gear Bicycle')
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
get '/r/ruby' do
|
22
|
+
proxy_doc do |response,doc|
|
23
|
+
for_host(/reddit\.com/) do
|
24
|
+
doc.search('div.link').each do |link|
|
25
|
+
if link.at('a.title').inner_text =~ /rails/i
|
26
|
+
link.remove
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
get '/rss.php' do
|
34
|
+
proxy_doc do |response,doc|
|
35
|
+
for_host('milworm.com') do
|
36
|
+
doc.search('//item').each do |item|
|
37
|
+
if item.inner_text =~ /(XSS|SQLi|SQL\s+Injection)/i
|
38
|
+
item.remove
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
Static file1.
|
@@ -0,0 +1 @@
|
|
1
|
+
Static file2.
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'ronin/web/server/base'
|
2
|
+
|
3
|
+
require 'web/server/classes/sub_app'
|
4
|
+
|
5
|
+
class TestApp < Ronin::Web::Server::Base
|
6
|
+
|
7
|
+
get '/tests/get' do
|
8
|
+
'block tested'
|
9
|
+
end
|
10
|
+
|
11
|
+
any '/tests/any' do
|
12
|
+
'any tested'
|
13
|
+
end
|
14
|
+
|
15
|
+
map '/tests/subapp', SubApp
|
16
|
+
|
17
|
+
public_dir File.join(File.dirname(__FILE__),'public1')
|
18
|
+
public_dir File.join(File.dirname(__FILE__),'public2')
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'ronin/web/server/files'
|
2
|
+
require 'ronin/web/server/base'
|
3
|
+
|
4
|
+
require 'spec_helper'
|
5
|
+
require 'web/server/helpers/server'
|
6
|
+
require 'web/server/classes/files_app'
|
7
|
+
|
8
|
+
describe Web::Server::Files do
|
9
|
+
include Helpers::Web::Server
|
10
|
+
|
11
|
+
before(:all) do
|
12
|
+
self.app = FilesApp
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should host individual files" do
|
16
|
+
get '/tests/file'
|
17
|
+
|
18
|
+
last_response.should be_ok
|
19
|
+
last_response.body.should == "A file.\n"
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should automatically set the content_type for files" do
|
23
|
+
get '/tests/content_type'
|
24
|
+
|
25
|
+
last_response.should be_ok
|
26
|
+
last_response.content_type.should =~ /\/xml$/
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should allow overriding the content_type of files" do
|
30
|
+
get '/tests/content_type/custom'
|
31
|
+
|
32
|
+
last_response.should be_ok
|
33
|
+
last_response.content_type.should == 'text/plain'
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should ignore missing files that are hosted" do
|
37
|
+
get '/test/missing'
|
38
|
+
|
39
|
+
last_response.should_not be_ok
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should host the contents of a directory" do
|
43
|
+
get '/tests/directory/file.txt'
|
44
|
+
|
45
|
+
last_response.should be_ok
|
46
|
+
last_response.body.should == "Another file.\n"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should prevent directory traversal when hosting a directory" do
|
50
|
+
get '/test/directory/./././//..///.///..///./../files_spec.rb'
|
51
|
+
|
52
|
+
last_response.should_not be_ok
|
53
|
+
end
|
54
|
+
|
55
|
+
it "should host the contents of directories that share a common path" do
|
56
|
+
get '/tests/directory/file2.txt'
|
57
|
+
|
58
|
+
last_response.should be_ok
|
59
|
+
last_response.body.should == "Second file.\n"
|
60
|
+
end
|
61
|
+
|
62
|
+
it "should search for index files within a directory" do
|
63
|
+
get '/tests/directory/'
|
64
|
+
|
65
|
+
last_response.should be_ok
|
66
|
+
last_response.body.should == "The index.\n"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "should not return anything if there is no index file was found" do
|
70
|
+
get '/tests/directory/no_index/'
|
71
|
+
|
72
|
+
last_response.should_not be_ok
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
begin
|
2
|
+
require 'spec/interop/test'
|
3
|
+
rescue Gem::LoadError => e
|
4
|
+
raise(e)
|
5
|
+
rescue ::LoadError
|
6
|
+
STDERR.puts "Error: please install the test-unit gem in order to run the spec tests"
|
7
|
+
exit -1
|
8
|
+
end
|
9
|
+
|
10
|
+
begin
|
11
|
+
require 'rack/test'
|
12
|
+
rescue Gem::LoadError => e
|
13
|
+
raise(e)
|
14
|
+
rescue ::LoadError
|
15
|
+
STDERR.puts "Error: please install the rack-test gem in order to run the spec tests"
|
16
|
+
exit -1
|
17
|
+
end
|
18
|
+
|
19
|
+
module Helpers
|
20
|
+
module Web
|
21
|
+
module Server
|
22
|
+
include Rack::Test::Methods
|
23
|
+
|
24
|
+
def app=(server)
|
25
|
+
@app = server
|
26
|
+
@app.set :environment, :test
|
27
|
+
end
|
28
|
+
|
29
|
+
def app
|
30
|
+
@app
|
31
|
+
end
|
32
|
+
|
33
|
+
def get_host(path,host,params={},headers={})
|
34
|
+
get(path,params,headers.merge('HTTP_HOST' => host))
|
35
|
+
end
|
36
|
+
|
37
|
+
def post_host(path,host,params={},headers={})
|
38
|
+
post(path,params,headers.merge('HTTP_HOST' => host))
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'ronin/web/server/hosts'
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
require 'web/server/classes/hosts_app'
|
5
|
+
require 'web/server/helpers/server'
|
6
|
+
|
7
|
+
describe Web::Server::Hosts do
|
8
|
+
include Helpers::Web::Server
|
9
|
+
|
10
|
+
before(:all) do
|
11
|
+
self.app = HostsApp
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should allow routes to respond to specific hosts" do
|
15
|
+
get_host '/tests/for_host', 'localhost'
|
16
|
+
|
17
|
+
last_response.should be_ok
|
18
|
+
last_response.body.should == 'Admin Response'
|
19
|
+
end
|
20
|
+
|
21
|
+
it "should allow routes to respond to hosts matching a pattern" do
|
22
|
+
get_host '/tests/for_host', 'downloads.example.com'
|
23
|
+
|
24
|
+
last_response.should be_ok
|
25
|
+
last_response.body.should == 'Download Response'
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should fallback to the normal response if the host is not recognized" do
|
29
|
+
get '/tests/for_host'
|
30
|
+
|
31
|
+
last_response.should be_ok
|
32
|
+
last_response.body.should == 'Generic Response'
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should route requests for specific hosts" do
|
36
|
+
get_host '/file', 'example.com'
|
37
|
+
|
38
|
+
last_response.should be_ok
|
39
|
+
last_response.body.should == 'WWW File'
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should route requests for hosts matching a pattern" do
|
43
|
+
get_host '/file', 'ftp.example.com'
|
44
|
+
|
45
|
+
last_response.should be_ok
|
46
|
+
last_response.body.should == 'FTP File'
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should not route requests for unrecognized hosts" do
|
50
|
+
get '/file'
|
51
|
+
|
52
|
+
last_response.should be_ok
|
53
|
+
last_response.body.should == 'Generic File'
|
54
|
+
end
|
55
|
+
end
|