ronin 0.2.3 → 0.2.4
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 +2 -0
- data/History.txt +43 -0
- data/Manifest.txt +27 -10
- data/README.txt +2 -1
- data/Rakefile +12 -11
- data/TODO.txt +8 -0
- data/bin/{ronin-ls → ronin-list} +2 -2
- data/bin/{ronin-rm → ronin-remove} +2 -2
- data/lib/ronin/cacheable.rb +25 -4
- data/lib/ronin/code/reference.rb +0 -9
- data/lib/ronin/code/symbol_table.rb +5 -5
- data/lib/ronin/code/token.rb +1 -1
- data/lib/ronin/database/database.rb +3 -1
- data/lib/ronin/extensions/kernel.rb +25 -3
- data/lib/ronin/formatting/extensions/binary/file.rb +60 -0
- data/lib/ronin/formatting/extensions/text.rb +1 -0
- data/lib/ronin/formatting/extensions/text/array.rb +67 -0
- data/lib/ronin/model.rb +1 -40
- data/lib/ronin/{has_license.rb → model/has_description.rb} +16 -18
- data/lib/ronin/model/has_license.rb +53 -0
- data/lib/ronin/model/has_name.rb +49 -0
- data/lib/ronin/model/has_version.rb +46 -0
- data/lib/ronin/model/model.rb +64 -0
- data/lib/ronin/network/extensions/http/net.rb +580 -99
- data/lib/ronin/network/http.rb +54 -6
- data/lib/ronin/os.rb +7 -7
- data/lib/ronin/platform/extension.rb +4 -6
- data/lib/ronin/platform/maintainer.rb +1 -1
- data/lib/ronin/platform/object_cache.rb +10 -2
- data/lib/ronin/platform/overlay_cache.rb +1 -1
- data/lib/ronin/platform/platform.rb +5 -3
- data/lib/ronin/platform/ronin.rb +3 -3
- data/lib/ronin/scanners.rb +25 -0
- data/lib/ronin/scanners/exceptions.rb +24 -0
- data/lib/ronin/scanners/exceptions/unknown_category.rb +29 -0
- data/lib/ronin/scanners/scanner.rb +239 -0
- data/lib/ronin/sessions/http.rb +548 -7
- data/lib/ronin/{translators.rb → templates.rb} +1 -1
- data/lib/ronin/templates/erb.rb +56 -0
- data/lib/ronin/ui/command_line/command_line.rb +10 -1
- data/lib/ronin/ui/command_line/commands/{ls.rb → list.rb} +1 -1
- data/lib/ronin/ui/command_line/commands/{rm.rb → remove.rb} +1 -1
- data/lib/ronin/ui/command_line/commands/uninstall.rb +2 -2
- data/lib/ronin/ui/console.rb +66 -17
- data/lib/ronin/ui/shell.rb +16 -36
- data/lib/ronin/version.rb +1 -1
- data/spec/cacheable_spec.rb +1 -1
- data/spec/code/classes/thing.rb +4 -0
- data/spec/code/reference_spec.rb +4 -0
- data/spec/code/symbol_table_spec.rb +5 -1
- data/spec/extensions/kernel_spec.rb +45 -5
- data/spec/extensions/string_spec.rb +4 -0
- data/spec/formatting/binary/integer_spec.rb +3 -3
- data/spec/formatting/binary/string_spec.rb +5 -5
- data/spec/formatting/digest/string_spec.rb +5 -9
- data/spec/formatting/http/string_spec.rb +5 -9
- data/spec/formatting/text/array_spec.rb +64 -0
- data/spec/formatting/text/string_spec.rb +3 -3
- data/spec/model/classes/licensed_model.rb +12 -0
- data/spec/{has_license_spec.rb → model/has_license_spec.rb} +5 -5
- data/spec/network/http_spec.rb +197 -0
- data/spec/os_spec.rb +2 -5
- data/spec/platform/maintainer_spec.rb +30 -0
- data/spec/platform/ronin_spec.rb +2 -2
- data/spec/scanners/classes/another_scanner.rb +16 -0
- data/spec/scanners/classes/example_scanner.rb +22 -0
- data/spec/scanners/scanner_spec.rb +148 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/templates/classes/uses_erb.rb +11 -0
- data/spec/templates/erb_spec.rb +20 -0
- data/static/ronin/platform/overlay.xsl +128 -49
- metadata +83 -30
- metadata.gz.sig +0 -0
- data/lib/ronin/translators/translator.rb +0 -75
- data/spec/classes/licensed_model.rb +0 -12
- data/spec/translators/translator_spec.rb +0 -61
data/lib/ronin/network/http.rb
CHANGED
@@ -79,6 +79,42 @@ module Ronin
|
|
79
79
|
@@http_user_agent = agent
|
80
80
|
end
|
81
81
|
|
82
|
+
#
|
83
|
+
# Expands the given HTTP _options_.
|
84
|
+
#
|
85
|
+
def HTTP.expand_options(options={})
|
86
|
+
new_options = options.dup
|
87
|
+
|
88
|
+
if new_options[:url]
|
89
|
+
url = URI(new_options.delete(:url).to_s)
|
90
|
+
|
91
|
+
new_options[:host] = url.host
|
92
|
+
new_options[:port] = url.port
|
93
|
+
|
94
|
+
new_options[:user] = url.user if url.user
|
95
|
+
new_options[:password] = url.password if url.password
|
96
|
+
|
97
|
+
unless url.path.empty?
|
98
|
+
new_options[:path] = url.path
|
99
|
+
else
|
100
|
+
new_options[:path] = '/'
|
101
|
+
end
|
102
|
+
|
103
|
+
new_options[:path] << "?#{url.query}" if url.query
|
104
|
+
else
|
105
|
+
new_options[:port] ||= ::Net::HTTP.default_port
|
106
|
+
new_options[:path] ||= '/'
|
107
|
+
end
|
108
|
+
|
109
|
+
if (proxy = new_options[:proxy])
|
110
|
+
proxy[:port] ||= Ronin::Network::HTTP.default_proxy_port
|
111
|
+
else
|
112
|
+
new_options[:proxy] = Ronin::Network::HTTP.proxy
|
113
|
+
end
|
114
|
+
|
115
|
+
return new_options
|
116
|
+
end
|
117
|
+
|
82
118
|
#
|
83
119
|
# Returns Ronin HTTP headers created from the given _options_.
|
84
120
|
#
|
@@ -91,7 +127,7 @@ module Ronin
|
|
91
127
|
|
92
128
|
if options
|
93
129
|
options.each do |name,value|
|
94
|
-
header_name = name.to_s.split(
|
130
|
+
header_name = name.to_s.split(/[\s+_-]/).map { |word|
|
95
131
|
word.capitalize
|
96
132
|
}.join('-')
|
97
133
|
|
@@ -107,18 +143,30 @@ module Ronin
|
|
107
143
|
# given _options_. If type does not represent the name of an Net:HTTP
|
108
144
|
# Request Class an UnknownRequest exception will be raised.
|
109
145
|
#
|
110
|
-
def HTTP.request(
|
111
|
-
|
146
|
+
def HTTP.request(options={})
|
147
|
+
unless options[:method]
|
148
|
+
raise(ArgumentError,"the :method option must be specified",caller)
|
149
|
+
end
|
150
|
+
|
151
|
+
name = options[:method].to_s.capitalize
|
112
152
|
|
113
153
|
unless Net::HTTP.const_defined?(name)
|
114
154
|
raise(UnknownRequest,"unknown HTTP request type #{name.dump}",caller)
|
115
155
|
end
|
116
156
|
|
117
157
|
headers = HTTP.headers(options[:headers])
|
118
|
-
|
158
|
+
path = (options[:path] || '/').to_s
|
159
|
+
|
160
|
+
request = Net::HTTP.const_get(name).new(path,headers)
|
161
|
+
|
162
|
+
if (user = options.delete(:user))
|
163
|
+
user = user.to_s
|
164
|
+
|
165
|
+
if (password = options.delete(:password))
|
166
|
+
password = password.to_s
|
167
|
+
end
|
119
168
|
|
120
|
-
|
121
|
-
request.basic_auth(options[:user].to_s,options[:password].to_s)
|
169
|
+
request.basic_auth(user,password)
|
122
170
|
end
|
123
171
|
|
124
172
|
return request
|
data/lib/ronin/os.rb
CHANGED
@@ -41,7 +41,7 @@ module Ronin
|
|
41
41
|
property :version, String, :index => true
|
42
42
|
|
43
43
|
# Validates
|
44
|
-
validates_present :name
|
44
|
+
validates_present :name
|
45
45
|
|
46
46
|
#
|
47
47
|
# Returns the String form of the os.
|
@@ -66,12 +66,12 @@ module Ronin
|
|
66
66
|
name = name.to_s
|
67
67
|
method_name = name.snake_case
|
68
68
|
|
69
|
-
meta_def(method_name) do
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
69
|
+
meta_def(method_name) do |*arguments|
|
70
|
+
if (version = arguments.first)
|
71
|
+
OS.first_or_create(:name => name, :version => version.to_s)
|
72
|
+
else
|
73
|
+
OS.new(:name => name)
|
74
|
+
end
|
75
75
|
end
|
76
76
|
|
77
77
|
return nil
|
@@ -24,7 +24,9 @@
|
|
24
24
|
require 'ronin/platform/exceptions/extension_not_found'
|
25
25
|
require 'ronin/platform/extension_cache'
|
26
26
|
require 'ronin/platform/platform'
|
27
|
+
require 'ronin/extensions/kernel'
|
27
28
|
require 'ronin/static/finders'
|
29
|
+
require 'ronin/ui/diagnostics'
|
28
30
|
|
29
31
|
require 'contextify'
|
30
32
|
|
@@ -34,6 +36,7 @@ module Ronin
|
|
34
36
|
|
35
37
|
include Contextify
|
36
38
|
include Static::Finders
|
39
|
+
include UI::Diagnostics
|
37
40
|
|
38
41
|
contextify :ronin_extension
|
39
42
|
|
@@ -141,12 +144,7 @@ module Ronin
|
|
141
144
|
context_block = Extension.load_context_block(extension_file)
|
142
145
|
|
143
146
|
if context_block
|
144
|
-
|
145
|
-
instance_eval(&context_block)
|
146
|
-
rescue SyntaxError, RuntimeError, StandardError => e
|
147
|
-
STDERR.puts "#{e.class}: #{e}"
|
148
|
-
e.backtrace.each { |trace| STDERR.puts "\t#{trace}" }
|
149
|
-
end
|
147
|
+
catch_all { instance_eval(&context_block) }
|
150
148
|
end
|
151
149
|
end
|
152
150
|
|
@@ -21,7 +21,9 @@
|
|
21
21
|
#++
|
22
22
|
#
|
23
23
|
|
24
|
+
require 'ronin/database'
|
24
25
|
require 'ronin/cacheable'
|
26
|
+
require 'ronin/extensions/kernel'
|
25
27
|
|
26
28
|
module Ronin
|
27
29
|
module Platform
|
@@ -56,8 +58,10 @@ module Ronin
|
|
56
58
|
# _directory_.
|
57
59
|
#
|
58
60
|
def ObjectCache.cache(directory)
|
61
|
+
Database.setup unless Database.setup?
|
62
|
+
|
59
63
|
ObjectCache.paths(directory).each do |path|
|
60
|
-
Cacheable.
|
64
|
+
catch_all { Cacheable.cache_all(path) }
|
61
65
|
end
|
62
66
|
|
63
67
|
return true
|
@@ -71,10 +75,12 @@ module Ronin
|
|
71
75
|
def ObjectCache.sync(directory)
|
72
76
|
new_paths = ObjectCache.paths(directory)
|
73
77
|
|
78
|
+
Database.setup unless Database.setup?
|
79
|
+
|
74
80
|
ObjectCache.each(directory) do |obj|
|
75
81
|
new_paths.delete(obj.cached_path)
|
76
82
|
|
77
|
-
obj.sync!
|
83
|
+
catch_all { obj.sync! }
|
78
84
|
end
|
79
85
|
|
80
86
|
# cache the remaining new paths
|
@@ -87,6 +93,8 @@ module Ronin
|
|
87
93
|
# _directory_.
|
88
94
|
#
|
89
95
|
def ObjectCache.clean(directory)
|
96
|
+
Database.setup unless Database.setup?
|
97
|
+
|
90
98
|
ObjectCache.each(directory) { |obj| obj.destroy }
|
91
99
|
return true
|
92
100
|
end
|
@@ -26,6 +26,8 @@ require 'ronin/platform/overlay_cache'
|
|
26
26
|
require 'ronin/platform/object_cache'
|
27
27
|
require 'ronin/platform/extension_cache'
|
28
28
|
|
29
|
+
require 'uri'
|
30
|
+
|
29
31
|
module Ronin
|
30
32
|
module Platform
|
31
33
|
#
|
@@ -145,11 +147,11 @@ module Ronin
|
|
145
147
|
# has been uninstalled.
|
146
148
|
#
|
147
149
|
def Platform.uninstall(name,&block)
|
148
|
-
Platform.
|
149
|
-
ObjectCache.
|
150
|
+
Platform.overlays.uninstall(name) do |overlay|
|
151
|
+
ObjectCache.clean(overlay.objects_dir)
|
150
152
|
end
|
151
153
|
|
152
|
-
block.call if block
|
154
|
+
block.call() if block
|
153
155
|
return nil
|
154
156
|
end
|
155
157
|
|
data/lib/ronin/platform/ronin.rb
CHANGED
@@ -48,14 +48,14 @@ module Ronin
|
|
48
48
|
#
|
49
49
|
# Provides transparent access to Platform.extension via methods.
|
50
50
|
#
|
51
|
-
#
|
51
|
+
# shellcode
|
52
52
|
# # => #<Ronin::Platform::Extension: ...>
|
53
53
|
#
|
54
|
-
#
|
54
|
+
# shellcode do |ext|
|
55
55
|
# ...
|
56
56
|
# end
|
57
57
|
#
|
58
|
-
def
|
58
|
+
def method_missing(sym,*args,&block)
|
59
59
|
if args.length == 0
|
60
60
|
name = sym.id2name
|
61
61
|
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#
|
2
|
+
#--
|
3
|
+
# Ronin - A Ruby platform designed for information security and data
|
4
|
+
# exploration tasks.
|
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/scanners/exceptions'
|
25
|
+
require 'ronin/scanners/scanner'
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#
|
2
|
+
#--
|
3
|
+
# Ronin - A Ruby platform designed for information security and data
|
4
|
+
# exploration tasks.
|
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/scanners/exceptions/unknown_category'
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#
|
2
|
+
#--
|
3
|
+
# Ronin - A Ruby platform designed for information security and data
|
4
|
+
# exploration tasks.
|
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
|
+
module Ronin
|
25
|
+
module Scanners
|
26
|
+
class UnknownCategory < StandardError
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,239 @@
|
|
1
|
+
#
|
2
|
+
#--
|
3
|
+
# Ronin - A Ruby platform designed for information security and data
|
4
|
+
# exploration tasks.
|
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/scanners/exceptions/unknown_category'
|
25
|
+
require 'ronin/extensions/meta'
|
26
|
+
|
27
|
+
require 'set'
|
28
|
+
|
29
|
+
module Ronin
|
30
|
+
module Scanners
|
31
|
+
module Scanner
|
32
|
+
def self.included(base)
|
33
|
+
base.metaclass_eval do
|
34
|
+
#
|
35
|
+
# Returns the +Hash+ of the categories and the scanners defined
|
36
|
+
# for the class.
|
37
|
+
#
|
38
|
+
def scanners
|
39
|
+
@scanners ||= {}
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# Returns the category names of all defined scanners.
|
44
|
+
#
|
45
|
+
def scans_for
|
46
|
+
names = Set[]
|
47
|
+
|
48
|
+
ancestors.each do |ancestor|
|
49
|
+
if ancestor.include?(Ronin::Scanners::Scanner)
|
50
|
+
names += ancestor.scanners.keys
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
return names
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
# Returns +true+ if there is a scanner with the specified category
|
59
|
+
# _name_ was defined, returns +false+ otherwise.
|
60
|
+
#
|
61
|
+
def scans_for?(name)
|
62
|
+
name = name.to_sym
|
63
|
+
|
64
|
+
ancestors.each do |ancestor|
|
65
|
+
if ancestor.include?(Ronin::Scanners::Scanner)
|
66
|
+
return true if ancestor.scanners.has_key?(name)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
return false
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# Returns all scanner tests in the specified _category_.
|
75
|
+
#
|
76
|
+
def scanners_in(name)
|
77
|
+
name = name.to_sym
|
78
|
+
|
79
|
+
unless scans_for?(name)
|
80
|
+
raise(Ronin::Scanners::UnknownCategory,"unknown scanner category #{name}",caller)
|
81
|
+
end
|
82
|
+
|
83
|
+
tests = []
|
84
|
+
|
85
|
+
ancestors.each do |ancestor|
|
86
|
+
if ancestor.include?(Ronin::Scanners::Scanner)
|
87
|
+
if ancestor.scanners.has_key?(name)
|
88
|
+
tests += ancestor.scanners[name]
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
return tests
|
94
|
+
end
|
95
|
+
|
96
|
+
#
|
97
|
+
# Defines a scanner with the specified category _name_ and
|
98
|
+
# _block_.
|
99
|
+
#
|
100
|
+
# When scanning against a target, a callback for saving results
|
101
|
+
# and the target object to be scanned will be passed to the
|
102
|
+
# _block_.
|
103
|
+
#
|
104
|
+
# scanner(:lfi) do |url,results|
|
105
|
+
# ...
|
106
|
+
# end
|
107
|
+
#
|
108
|
+
# If the scanner accepts a 3rd argument, it will be passed a
|
109
|
+
# +Hash+ of configuration options when the scanner is called.
|
110
|
+
#
|
111
|
+
# scanner(:sqli) do |url,results,options|
|
112
|
+
# ...
|
113
|
+
# end
|
114
|
+
#
|
115
|
+
def scanner(name,&block)
|
116
|
+
method_name = name.to_s.downcase.gsub(/[\s\._-]+/,'_')
|
117
|
+
name = name.to_sym
|
118
|
+
|
119
|
+
(scanners[name] ||= []) << block
|
120
|
+
|
121
|
+
class_def("first_#{method_name}") do |*arguments|
|
122
|
+
options = case arguments.length
|
123
|
+
when 1
|
124
|
+
arguments.first
|
125
|
+
when 0
|
126
|
+
true
|
127
|
+
else
|
128
|
+
raise(ArgumentError,"wrong number of arguments (#{arguments.length} for 1)",caller)
|
129
|
+
end
|
130
|
+
|
131
|
+
first_result = nil
|
132
|
+
|
133
|
+
scan(name => options) do |category,result|
|
134
|
+
first_result = result
|
135
|
+
break
|
136
|
+
end
|
137
|
+
|
138
|
+
return first_result
|
139
|
+
end
|
140
|
+
|
141
|
+
class_def("has_#{method_name}?") do |*arguments|
|
142
|
+
!(self.send("first_#{method_name}",*arguments).nil?)
|
143
|
+
end
|
144
|
+
|
145
|
+
name = name.to_s
|
146
|
+
|
147
|
+
module_eval %{
|
148
|
+
def #{method_name}_scan(options=true,&block)
|
149
|
+
results = scan(:#{name.dump} => options) do |category,result|
|
150
|
+
block.call(result) if block
|
151
|
+
end
|
152
|
+
|
153
|
+
return results[:#{name.dump}]
|
154
|
+
end
|
155
|
+
}
|
156
|
+
|
157
|
+
return true
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
#
|
163
|
+
# Runs the scanners in the given _categories_ against each_target.
|
164
|
+
# If _categories_ is not specified, all categories will be ran
|
165
|
+
# against each_target. Returns a +Hash+ of results grouped by
|
166
|
+
# scanner category.
|
167
|
+
#
|
168
|
+
# If a _block_ is given, it will be passed each result and the
|
169
|
+
# category the result belongs to.
|
170
|
+
#
|
171
|
+
# url.scan(:rfi => true)
|
172
|
+
#
|
173
|
+
# url.scan(:lfi => true, :sqli => {:params => ['id', 'catid']})
|
174
|
+
#
|
175
|
+
# url.scan(:lfi => true, :rfi => true) do |category,result|
|
176
|
+
# puts "[#{category}] #{result.inspect}"
|
177
|
+
# end
|
178
|
+
#
|
179
|
+
def scan(categories={},&block)
|
180
|
+
tests = {}
|
181
|
+
options = {}
|
182
|
+
results = {}
|
183
|
+
|
184
|
+
if categories.empty?
|
185
|
+
self.class.scans_for.each { |name| categories[name] = true }
|
186
|
+
end
|
187
|
+
|
188
|
+
categories.each do |name,opts|
|
189
|
+
name = name.to_sym
|
190
|
+
|
191
|
+
if opts
|
192
|
+
tests[name] = self.class.scanners_in(name)
|
193
|
+
|
194
|
+
options[name] = if opts.kind_of?(Hash)
|
195
|
+
opts
|
196
|
+
else
|
197
|
+
{}
|
198
|
+
end
|
199
|
+
|
200
|
+
results[name] = []
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
current_category = nil
|
205
|
+
result_callback = lambda { |result|
|
206
|
+
results[current_category] << result
|
207
|
+
block.call(current_category,result) if block
|
208
|
+
}
|
209
|
+
|
210
|
+
each_target do |target|
|
211
|
+
tests.each do |name,scanners|
|
212
|
+
current_category = name
|
213
|
+
|
214
|
+
scanners.each do |scanner|
|
215
|
+
if scanner.arity == 3
|
216
|
+
scanner.call(target,result_callback,options[name])
|
217
|
+
else
|
218
|
+
scanner.call(target,result_callback)
|
219
|
+
end
|
220
|
+
end
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
return results
|
225
|
+
end
|
226
|
+
|
227
|
+
protected
|
228
|
+
|
229
|
+
#
|
230
|
+
# A place holder method which will call the specified _block_ with
|
231
|
+
# each target object to be scanned. By default, the method will call
|
232
|
+
# the specified _block_ once, simply passing it the +self+ object.
|
233
|
+
#
|
234
|
+
def each_target(&block)
|
235
|
+
block.call(self)
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
end
|