relevance-tarantula 0.2.1 → 0.3.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +3 -4
- data/Rakefile +8 -4
- data/VERSION.yml +2 -2
- data/examples/example_helper.rb +9 -0
- data/examples/relevance/tarantula/attack_handler_example.rb +1 -1
- data/examples/relevance/tarantula/basic_attack_example.rb +12 -0
- data/examples/relevance/tarantula/crawler_example.rb +66 -77
- data/examples/relevance/tarantula/form_example.rb +3 -3
- data/examples/relevance/tarantula/form_submission_example.rb +157 -57
- data/examples/relevance/tarantula/link_example.rb +24 -7
- data/lib/relevance/tarantula/attack.rb +3 -0
- data/lib/relevance/tarantula/attack_handler.rb +1 -1
- data/lib/relevance/tarantula/basic_attack.rb +40 -0
- data/lib/relevance/tarantula/crawler.rb +33 -46
- data/lib/relevance/tarantula/form.rb +4 -2
- data/lib/relevance/tarantula/form_submission.rb +47 -30
- data/lib/relevance/tarantula/link.rb +24 -4
- data/lib/relevance/tarantula/rails_integration_proxy.rb +1 -1
- data/lib/relevance/tarantula.rb +1 -1
- metadata +7 -7
- data/examples/relevance/tarantula/attack_form_submission_example.rb +0 -79
- data/lib/relevance/tarantula/attack_form_submission.rb +0 -76
@@ -4,47 +4,64 @@ describe "Relevance::Tarantula::Link" do
|
|
4
4
|
include ActionView::Helpers::UrlHelper
|
5
5
|
|
6
6
|
it "does not raise an error when initializing without href attribtue" do
|
7
|
-
link =
|
7
|
+
link = make_link(Hpricot('<a="/foo">foo</a>').at('a'))
|
8
8
|
link.href.should == nil
|
9
9
|
link.method.should == :get
|
10
10
|
end
|
11
11
|
|
12
12
|
it "parses anchor tags" do
|
13
|
-
link =
|
13
|
+
link = make_link(Hpricot('<a href="/foo">foo</a>').at('a'))
|
14
14
|
link.href.should == '/foo'
|
15
15
|
link.method.should == :get
|
16
16
|
end
|
17
17
|
|
18
18
|
it "parses anchor tags with POST 'method'" do
|
19
|
-
link =
|
19
|
+
link = make_link(Hpricot(%Q{<a href="/foo" onclick="#{method_javascript_function(:post)}">foo</a>}).at('a'))
|
20
20
|
link.href.should == '/foo'
|
21
21
|
link.method.should == :post
|
22
22
|
end
|
23
23
|
|
24
24
|
it "parses anchor tags with PUT 'method'" do
|
25
|
-
link =
|
25
|
+
link = make_link(Hpricot(%Q{<a href="/foo" onclick="#{method_javascript_function(:put)}">foo</a>}).at('a'))
|
26
26
|
link.href.should == '/foo'
|
27
27
|
link.method.should == :put
|
28
28
|
end
|
29
29
|
|
30
30
|
it "parses anchor tags with DELETE 'method'" do
|
31
|
-
link =
|
31
|
+
link = make_link(Hpricot(%Q{<a href="/foo" onclick="#{method_javascript_function(:delete)}">foo</a>}).at('a'))
|
32
32
|
link.href.should == '/foo'
|
33
33
|
link.method.should == :delete
|
34
34
|
end
|
35
35
|
|
36
36
|
it "parses link tags with text" do
|
37
|
-
link =
|
37
|
+
link = make_link(Hpricot('<link href="/bar">bar</a>').at('link'))
|
38
38
|
link.href.should == '/bar'
|
39
39
|
link.method.should == :get
|
40
40
|
end
|
41
41
|
|
42
42
|
it "parses link tags without text" do
|
43
|
-
link =
|
43
|
+
link = make_link(Hpricot('<link href="/bar" />').at('link'))
|
44
44
|
link.href.should == '/bar'
|
45
45
|
link.method.should == :get
|
46
46
|
end
|
47
47
|
|
48
|
+
it 'remembers link referrer if there is one' do
|
49
|
+
link = make_link('/url', stub_everything, '/some-referrer')
|
50
|
+
link.referrer.should == '/some-referrer'
|
51
|
+
end
|
52
|
+
|
53
|
+
it "does two things when crawled: follow, log, and handle" do
|
54
|
+
crawler = Relevance::Tarantula::Crawler.new
|
55
|
+
link = make_link('/foo', crawler)
|
56
|
+
|
57
|
+
response = stub(:code => "200")
|
58
|
+
crawler.expects(:follow).returns(response)
|
59
|
+
link.expects(:log)
|
60
|
+
crawler.expects(:handle_link_results)
|
61
|
+
|
62
|
+
link.crawl
|
63
|
+
end
|
64
|
+
|
48
65
|
# method_javascript_function needs this method
|
49
66
|
def protect_against_forgery?
|
50
67
|
false
|
@@ -0,0 +1,40 @@
|
|
1
|
+
class Relevance::Tarantula::BasicAttack
|
2
|
+
ATTRS = [:name, :output, :description]
|
3
|
+
|
4
|
+
attr_reader *ATTRS
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@name = "Tarantula Basic Fuzzer"
|
8
|
+
@output = nil
|
9
|
+
@description = "Supplies purely random but simplistically generated form input."
|
10
|
+
end
|
11
|
+
|
12
|
+
def ==(other)
|
13
|
+
Relevance::Tarantula::BasicAttack === other && ATTRS.all? { |attr| send(attr) == other.send(attr)}
|
14
|
+
end
|
15
|
+
|
16
|
+
def input(input_field)
|
17
|
+
case input_field['name']
|
18
|
+
when /amount/ then random_int
|
19
|
+
when /_id$/ then random_whole_number
|
20
|
+
when /uploaded_data/ then nil
|
21
|
+
when nil then input['value']
|
22
|
+
else
|
23
|
+
random_int
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def big_number
|
28
|
+
10000 # arbitrary
|
29
|
+
end
|
30
|
+
|
31
|
+
def random_int
|
32
|
+
rand(big_number) - (big_number/2)
|
33
|
+
end
|
34
|
+
|
35
|
+
def random_whole_number
|
36
|
+
rand(big_number)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
|
@@ -10,7 +10,7 @@ class Relevance::Tarantula::Crawler
|
|
10
10
|
class CrawlTimeout < RuntimeError; end
|
11
11
|
|
12
12
|
attr_accessor :proxy, :handlers, :skip_uri_patterns, :log_grabber,
|
13
|
-
:reporters, :
|
13
|
+
:reporters, :crawl_queue, :links_queued,
|
14
14
|
:form_signatures_queued, :max_url_length, :response_code_handler,
|
15
15
|
:times_to_crawl, :fuzzers, :test_name, :crawl_timeout
|
16
16
|
attr_reader :transform_url_patterns, :referrers, :failures, :successes, :crawl_start_times, :crawl_end_times
|
@@ -22,8 +22,7 @@ class Relevance::Tarantula::Crawler
|
|
22
22
|
@handlers = [@response_code_handler = Result]
|
23
23
|
@links_queued = Set.new
|
24
24
|
@form_signatures_queued = Set.new
|
25
|
-
@
|
26
|
-
@forms_to_crawl = []
|
25
|
+
@crawl_queue = []
|
27
26
|
@crawl_start_times, @crawl_end_times = [], []
|
28
27
|
@crawl_timeout = 20.minutes
|
29
28
|
@referrers = {}
|
@@ -55,8 +54,7 @@ class Relevance::Tarantula::Crawler
|
|
55
54
|
def crawl(url = "/")
|
56
55
|
orig_links_queued = @links_queued.dup
|
57
56
|
orig_form_signatures_queued = @form_signatures_queued.dup
|
58
|
-
|
59
|
-
orig_forms_to_crawl = @forms_to_crawl.dup
|
57
|
+
orig_crawl_queue = @crawl_queue.dup
|
60
58
|
@times_to_crawl.times do |num|
|
61
59
|
queue_link url
|
62
60
|
|
@@ -71,8 +69,7 @@ class Relevance::Tarantula::Crawler
|
|
71
69
|
if num + 1 < @times_to_crawl
|
72
70
|
@links_queued = orig_links_queued
|
73
71
|
@form_signatures_queued = orig_form_signatures_queued
|
74
|
-
@
|
75
|
-
@forms_to_crawl = orig_forms_to_crawl
|
72
|
+
@crawl_queue = orig_crawl_queue
|
76
73
|
@referrers = {}
|
77
74
|
end
|
78
75
|
end
|
@@ -83,23 +80,20 @@ class Relevance::Tarantula::Crawler
|
|
83
80
|
end
|
84
81
|
|
85
82
|
def finished?
|
86
|
-
@
|
83
|
+
@crawl_queue.empty?
|
87
84
|
end
|
88
85
|
|
89
86
|
def do_crawl(number)
|
90
87
|
while (!finished?)
|
91
88
|
@crawl_start_times << Time.now
|
92
|
-
|
93
|
-
crawl_queued_forms(number)
|
89
|
+
crawl_the_queue(number)
|
94
90
|
@crawl_end_times << Time.now
|
95
91
|
end
|
96
92
|
end
|
97
93
|
|
98
|
-
def
|
99
|
-
while (
|
100
|
-
|
101
|
-
log "Response #{response.code} for #{link}"
|
102
|
-
handle_link_results(link, response)
|
94
|
+
def crawl_the_queue(number = 0)
|
95
|
+
while (request = @crawl_queue.pop)
|
96
|
+
request.crawl
|
103
97
|
blip(number)
|
104
98
|
end
|
105
99
|
end
|
@@ -110,15 +104,10 @@ class Relevance::Tarantula::Crawler
|
|
110
104
|
end
|
111
105
|
end
|
112
106
|
|
113
|
-
def handle_link_results(link,
|
107
|
+
def handle_link_results(link, result)
|
114
108
|
handlers.each do |h|
|
115
109
|
begin
|
116
|
-
save_result h.handle(
|
117
|
-
:url => link.href,
|
118
|
-
:response => response,
|
119
|
-
:log => grab_log!,
|
120
|
-
:referrer => referrers[link],
|
121
|
-
:test_name => test_name).freeze)
|
110
|
+
save_result h.handle(result)
|
122
111
|
rescue Exception => e
|
123
112
|
log "error handling #{link} #{e.message}"
|
124
113
|
# TODO: pass to results
|
@@ -126,23 +115,14 @@ class Relevance::Tarantula::Crawler
|
|
126
115
|
end
|
127
116
|
end
|
128
117
|
|
129
|
-
def
|
130
|
-
|
131
|
-
log "Response #{response.code} for #{form}"
|
132
|
-
response
|
133
|
-
rescue ActiveRecord::RecordNotFound => e
|
134
|
-
log "Skipping #{form.action}, presumed ok that record is missing"
|
135
|
-
Relevance::Tarantula::Response.new(:code => "404", :body => e.message, :content_type => "text/plain")
|
136
|
-
end
|
137
|
-
|
138
|
-
def crawl_queued_forms(number = 0)
|
139
|
-
while (form = @forms_to_crawl.pop)
|
140
|
-
response = crawl_form(form)
|
141
|
-
handle_form_results(form, response)
|
142
|
-
blip(number)
|
143
|
-
end
|
118
|
+
def follow(method, url, data=nil)
|
119
|
+
proxy.send(method, url, data)
|
144
120
|
end
|
145
121
|
|
122
|
+
def submit(method, action, data)
|
123
|
+
proxy.send(method, action, data)
|
124
|
+
end
|
125
|
+
|
146
126
|
def elasped_time_for_pass(num)
|
147
127
|
Time.now - crawl_start_times[num]
|
148
128
|
end
|
@@ -150,6 +130,14 @@ class Relevance::Tarantula::Crawler
|
|
150
130
|
def grab_log!
|
151
131
|
@log_grabber && @log_grabber.grab!
|
152
132
|
end
|
133
|
+
|
134
|
+
def make_result(options)
|
135
|
+
defaults = {
|
136
|
+
:log => grab_log!,
|
137
|
+
:test_name => test_name
|
138
|
+
}
|
139
|
+
Result.new(defaults.merge(options)).freeze
|
140
|
+
end
|
153
141
|
|
154
142
|
def handle_form_results(form, response)
|
155
143
|
handlers.each do |h|
|
@@ -193,23 +181,21 @@ class Relevance::Tarantula::Crawler
|
|
193
181
|
end
|
194
182
|
|
195
183
|
def queue_link(dest, referrer = nil)
|
196
|
-
dest = Link.new(dest)
|
197
|
-
dest.href = transform_url(dest.href)
|
184
|
+
dest = Link.new(dest, self, referrer)
|
198
185
|
return if should_skip_link?(dest)
|
199
|
-
@
|
200
|
-
@links_to_crawl << dest
|
186
|
+
@crawl_queue << dest
|
201
187
|
@links_queued << dest
|
202
188
|
dest
|
203
189
|
end
|
204
190
|
|
205
191
|
def queue_form(form, referrer = nil)
|
206
192
|
fuzzers.each do |fuzzer|
|
207
|
-
fuzzer.mutate(Form.new(form)).each do |fs|
|
208
|
-
# fs = fuzzer.new(Form.new(form))
|
193
|
+
fuzzer.mutate(Form.new(form, self, referrer)).each do |fs|
|
194
|
+
# fs = fuzzer.new(Form.new(form, self, referrer))
|
209
195
|
fs.action = transform_url(fs.action)
|
210
196
|
return if should_skip_form_submission?(fs)
|
211
197
|
@referrers[fs.action] = referrer if referrer
|
212
|
-
@
|
198
|
+
@crawl_queue << fs
|
213
199
|
@form_signatures_queued << fs.signature
|
214
200
|
end
|
215
201
|
end
|
@@ -234,6 +220,7 @@ class Relevance::Tarantula::Crawler
|
|
234
220
|
end
|
235
221
|
|
236
222
|
def report_results
|
223
|
+
puts "Crawled #{total_links_count} links and forms."
|
237
224
|
generate_reports
|
238
225
|
end
|
239
226
|
|
@@ -242,7 +229,7 @@ class Relevance::Tarantula::Crawler
|
|
242
229
|
end
|
243
230
|
|
244
231
|
def links_remaining_count
|
245
|
-
@
|
232
|
+
@crawl_queue.size
|
246
233
|
end
|
247
234
|
|
248
235
|
def links_completed_count
|
@@ -251,7 +238,7 @@ class Relevance::Tarantula::Crawler
|
|
251
238
|
|
252
239
|
def blip(number = 0)
|
253
240
|
unless verbose
|
254
|
-
print "\r #{links_completed_count} of #{total_links_count} links completed "
|
241
|
+
print "\r #{links_completed_count} of #{total_links_count} links completed " if $stdout.tty?
|
255
242
|
timeout_if_too_long(number)
|
256
243
|
end
|
257
244
|
end
|
@@ -2,8 +2,10 @@ class Relevance::Tarantula::Form
|
|
2
2
|
extend Forwardable
|
3
3
|
def_delegators("@tag", :search)
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
attr_accessor :crawler, :referrer
|
6
|
+
|
7
|
+
def initialize(tag, crawler, referrer)
|
8
|
+
@tag, @crawler, @referrer = tag, crawler, referrer
|
7
9
|
end
|
8
10
|
|
9
11
|
def action
|
@@ -1,25 +1,58 @@
|
|
1
1
|
class Relevance::Tarantula::FormSubmission
|
2
|
-
|
3
|
-
|
2
|
+
include Relevance::Tarantula
|
3
|
+
attr_accessor :method, :action, :data, :attack, :form
|
4
|
+
|
5
|
+
class << self
|
6
|
+
def attacks
|
7
|
+
# normalize from hash input to Attack
|
8
|
+
@attacks = @attacks.map do |val|
|
9
|
+
Hash === val ? Relevance::Tarantula::Attack.new(val) : val
|
10
|
+
end
|
11
|
+
@attacks
|
12
|
+
end
|
13
|
+
def attacks=(atts)
|
14
|
+
# normalize from hash input to Attack
|
15
|
+
@attacks = atts.map do |val|
|
16
|
+
Hash === val ? Relevance::Tarantula::Attack.new(val) : val
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
@attacks = [Relevance::Tarantula::BasicAttack.new]
|
21
|
+
|
22
|
+
def initialize(form, attack = Relevance::Tarantula::BasicAttack.new)
|
23
|
+
@form = form
|
4
24
|
@method = form.method
|
5
25
|
@action = form.action
|
26
|
+
@attack = attack
|
6
27
|
@data = mutate_selects(form).merge(mutate_text_areas(form)).merge(mutate_inputs(form))
|
7
28
|
end
|
8
29
|
|
30
|
+
def crawl
|
31
|
+
begin
|
32
|
+
response = form.crawler.submit(method, action, data)
|
33
|
+
log "Response #{response.code} for #{self}"
|
34
|
+
rescue ActiveRecord::RecordNotFound => e
|
35
|
+
log "Skipping #{action}, presumed ok that record is missing"
|
36
|
+
response = Relevance::Tarantula::Response.new(:code => "404", :body => e.message, :content_type => "text/plain")
|
37
|
+
end
|
38
|
+
form.crawler.handle_form_results(self, response)
|
39
|
+
response
|
40
|
+
end
|
41
|
+
|
9
42
|
def self.mutate(form)
|
10
|
-
|
43
|
+
attacks.map{|attack| new(form, attack)} if attacks
|
11
44
|
end
|
12
|
-
|
45
|
+
|
13
46
|
def to_s
|
14
|
-
"#{action} #{method} #{data.inspect}"
|
47
|
+
"#{action} #{method} #{data.inspect} #{attack.inspect}"
|
15
48
|
end
|
16
|
-
|
49
|
+
|
17
50
|
# a form's signature is what makes it unique (e.g. action + fields)
|
18
51
|
# used to keep track of which forms we have submitted already
|
19
52
|
def signature
|
20
|
-
[action, data.keys.sort]
|
53
|
+
[action, data.keys.sort, attack.name]
|
21
54
|
end
|
22
|
-
|
55
|
+
|
23
56
|
def create_random_data_for(form, tag_selector)
|
24
57
|
form.search(tag_selector).inject({}) do |form_args, input|
|
25
58
|
# TODO: test
|
@@ -35,37 +68,21 @@ class Relevance::Tarantula::FormSubmission
|
|
35
68
|
def mutate_text_areas(form)
|
36
69
|
create_random_data_for(form, 'textarea')
|
37
70
|
end
|
38
|
-
|
71
|
+
|
39
72
|
def mutate_selects(form)
|
40
73
|
form.search('select').inject({}) do |form_args, select|
|
41
74
|
options = select.search('option')
|
42
75
|
option = options.rand
|
43
|
-
form_args[select['name']] = option['value']
|
76
|
+
form_args[select['name']] = option['value']
|
44
77
|
form_args
|
45
78
|
end
|
46
79
|
end
|
47
|
-
|
80
|
+
|
48
81
|
def random_data(input)
|
49
82
|
case input['name']
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
when /^_method$/ then input['value']
|
54
|
-
when nil then input['value']
|
55
|
-
else
|
56
|
-
random_int
|
83
|
+
when /^_method$/ then input['value']
|
84
|
+
else
|
85
|
+
attack.input(input)
|
57
86
|
end
|
58
87
|
end
|
59
|
-
|
60
|
-
def big_number
|
61
|
-
10000 # arbitrary
|
62
|
-
end
|
63
|
-
|
64
|
-
def random_int
|
65
|
-
rand(big_number) - (big_number/2)
|
66
|
-
end
|
67
|
-
|
68
|
-
def random_whole_number
|
69
|
-
rand(big_number)
|
70
|
-
end
|
71
88
|
end
|
@@ -1,4 +1,5 @@
|
|
1
1
|
class Relevance::Tarantula::Link
|
2
|
+
include Relevance::Tarantula
|
2
3
|
|
3
4
|
class << self
|
4
5
|
include ActionView::Helpers::UrlHelper
|
@@ -17,18 +18,33 @@ class Relevance::Tarantula::Link
|
|
17
18
|
METHOD_REGEXPS[m] = /#{s}/
|
18
19
|
end
|
19
20
|
|
20
|
-
attr_accessor :href
|
21
|
+
attr_accessor :href, :crawler, :referrer
|
21
22
|
|
22
|
-
def initialize(link)
|
23
|
+
def initialize(link, crawler, referrer)
|
24
|
+
@crawler, @referrer = crawler, referrer
|
25
|
+
|
23
26
|
if String === link || link.nil?
|
24
|
-
@href = link
|
27
|
+
@href = transform_url(link)
|
25
28
|
@method = :get
|
26
29
|
else # should be a tag
|
27
|
-
@href = link['href'] ? link['href'].downcase : nil
|
30
|
+
@href = link['href'] ? transform_url(link['href'].downcase) : nil
|
28
31
|
@tag = link
|
29
32
|
end
|
30
33
|
end
|
31
34
|
|
35
|
+
def crawl
|
36
|
+
response = crawler.follow(method, href)
|
37
|
+
log "Response #{response.code} for #{self}"
|
38
|
+
crawler.handle_link_results(self, make_result(response))
|
39
|
+
end
|
40
|
+
|
41
|
+
def make_result(response)
|
42
|
+
crawler.make_result(:method => method,
|
43
|
+
:url => href,
|
44
|
+
:response => response,
|
45
|
+
:referrer => referrer)
|
46
|
+
end
|
47
|
+
|
32
48
|
def method
|
33
49
|
@method ||= begin
|
34
50
|
(@tag &&
|
@@ -39,6 +55,10 @@ class Relevance::Tarantula::Link
|
|
39
55
|
end
|
40
56
|
end
|
41
57
|
|
58
|
+
def transform_url(link)
|
59
|
+
crawler.transform_url(link)
|
60
|
+
end
|
61
|
+
|
42
62
|
def ==(obj)
|
43
63
|
obj.respond_to?(:href) && obj.respond_to?(:method) &&
|
44
64
|
self.href.to_s == obj.href.to_s && self.method.to_s == obj.method.to_s
|
@@ -41,7 +41,7 @@ class Relevance::Tarantula::RailsIntegrationProxy
|
|
41
41
|
if response.code == '404'
|
42
42
|
if File.exist?(static_content_path(url))
|
43
43
|
case ext = File.extension(url)
|
44
|
-
when /html|te?xt|css|js|jpe?g|gif|psd|png|eps|pdf/
|
44
|
+
when /html|te?xt|css|js|jpe?g|gif|psd|png|eps|pdf|ico/
|
45
45
|
response.body = static_content_file(url)
|
46
46
|
response.headers["type"] = "text/#{ext}" # readable as response.content_type
|
47
47
|
response.meta.attr_accessor :code
|
data/lib/relevance/tarantula.rb
CHANGED
@@ -49,10 +49,10 @@ require File.expand_path(File.join(File.dirname(__FILE__), "tarantula", "log_gra
|
|
49
49
|
require File.expand_path(File.join(File.dirname(__FILE__), "tarantula", "invalid_html_handler"))
|
50
50
|
require File.expand_path(File.join(File.dirname(__FILE__), "tarantula", "transform"))
|
51
51
|
require File.expand_path(File.join(File.dirname(__FILE__), "tarantula", "crawler"))
|
52
|
+
require File.expand_path(File.join(File.dirname(__FILE__), "tarantula", "basic_attack"))
|
52
53
|
require File.expand_path(File.join(File.dirname(__FILE__), "tarantula", "form"))
|
53
54
|
require File.expand_path(File.join(File.dirname(__FILE__), "tarantula", "form_submission"))
|
54
55
|
require File.expand_path(File.join(File.dirname(__FILE__), "tarantula", "attack"))
|
55
|
-
require File.expand_path(File.join(File.dirname(__FILE__), "tarantula", "attack_form_submission"))
|
56
56
|
require File.expand_path(File.join(File.dirname(__FILE__), "tarantula", "attack_handler"))
|
57
57
|
require File.expand_path(File.join(File.dirname(__FILE__), "tarantula", "link"))
|
58
58
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: relevance-tarantula
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2
|
4
|
+
version: 0.3.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Relevance, Inc.
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-09-24 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
@@ -51,8 +51,8 @@ files:
|
|
51
51
|
- examples/relevance/core_extensions/file_example.rb
|
52
52
|
- examples/relevance/core_extensions/response_example.rb
|
53
53
|
- examples/relevance/core_extensions/test_case_example.rb
|
54
|
-
- examples/relevance/tarantula/attack_form_submission_example.rb
|
55
54
|
- examples/relevance/tarantula/attack_handler_example.rb
|
55
|
+
- examples/relevance/tarantula/basic_attack_example.rb
|
56
56
|
- examples/relevance/tarantula/crawler_example.rb
|
57
57
|
- examples/relevance/tarantula/form_example.rb
|
58
58
|
- examples/relevance/tarantula/form_submission_example.rb
|
@@ -84,8 +84,8 @@ files:
|
|
84
84
|
- lib/relevance/core_extensions/test_case.rb
|
85
85
|
- lib/relevance/tarantula.rb
|
86
86
|
- lib/relevance/tarantula/attack.rb
|
87
|
-
- lib/relevance/tarantula/attack_form_submission.rb
|
88
87
|
- lib/relevance/tarantula/attack_handler.rb
|
88
|
+
- lib/relevance/tarantula/basic_attack.rb
|
89
89
|
- lib/relevance/tarantula/crawler.rb
|
90
90
|
- lib/relevance/tarantula/detail.html.erb
|
91
91
|
- lib/relevance/tarantula/form.rb
|
@@ -107,7 +107,7 @@ files:
|
|
107
107
|
- lib/relevance/tarantula/transform.rb
|
108
108
|
- tasks/tarantula_tasks.rake
|
109
109
|
- template/tarantula_test.rb
|
110
|
-
has_rdoc:
|
110
|
+
has_rdoc: false
|
111
111
|
homepage: http://github.com/relevance/tarantula
|
112
112
|
licenses:
|
113
113
|
post_install_message:
|
@@ -132,7 +132,7 @@ requirements: []
|
|
132
132
|
rubyforge_project: thinkrelevance
|
133
133
|
rubygems_version: 1.3.5
|
134
134
|
signing_key:
|
135
|
-
specification_version:
|
135
|
+
specification_version: 3
|
136
136
|
summary: A big hairy fuzzy spider that crawls your site, wreaking havoc
|
137
137
|
test_files:
|
138
138
|
- examples/example_helper.rb
|
@@ -140,8 +140,8 @@ test_files:
|
|
140
140
|
- examples/relevance/core_extensions/file_example.rb
|
141
141
|
- examples/relevance/core_extensions/response_example.rb
|
142
142
|
- examples/relevance/core_extensions/test_case_example.rb
|
143
|
-
- examples/relevance/tarantula/attack_form_submission_example.rb
|
144
143
|
- examples/relevance/tarantula/attack_handler_example.rb
|
144
|
+
- examples/relevance/tarantula/basic_attack_example.rb
|
145
145
|
- examples/relevance/tarantula/crawler_example.rb
|
146
146
|
- examples/relevance/tarantula/form_example.rb
|
147
147
|
- examples/relevance/tarantula/form_submission_example.rb
|
@@ -1,79 +0,0 @@
|
|
1
|
-
require File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "example_helper.rb"))
|
2
|
-
|
3
|
-
describe "Relevance::Tarantula::AttackFormSubmission" do
|
4
|
-
|
5
|
-
# TODO: add more from field types to this example form as needed
|
6
|
-
before do
|
7
|
-
@tag = Hpricot(<<END)
|
8
|
-
<form action="/session" method="post">
|
9
|
-
<input id="email" name="email" size="30" type="text" />
|
10
|
-
<textarea id="comment" name="comment"value="1" />
|
11
|
-
<input name="commit" type="submit" value="Postit" />
|
12
|
-
<input name="secret" type="hidden" value="secret" />
|
13
|
-
<select id="foo_opened_on_1i" name="foo[opened_on(1i)]">
|
14
|
-
<option value="2003">2003</option>
|
15
|
-
<option value="2004">2004</option>
|
16
|
-
</select>
|
17
|
-
</form>
|
18
|
-
END
|
19
|
-
@form = Relevance::Tarantula::Form.new(@tag.at('form'))
|
20
|
-
@fs = Relevance::Tarantula::AttackFormSubmission.new(@form, Relevance::Tarantula::Attack.new({:name => 'foo_name', :input => 'foo_code', :output => 'foo_code'}))
|
21
|
-
end
|
22
|
-
|
23
|
-
it "can mutate text areas" do
|
24
|
-
@fs.mutate_text_areas(@form).should == {"comment" => "foo_code"}
|
25
|
-
end
|
26
|
-
|
27
|
-
it "can mutate selects" do
|
28
|
-
Hpricot::Elements.any_instance.stubs(:rand).returns(stub(:[] => "2006-stub"))
|
29
|
-
@fs.mutate_selects(@form).should == {"foo[opened_on(1i)]" => "2006-stub"}
|
30
|
-
end
|
31
|
-
|
32
|
-
it "can mutate inputs" do
|
33
|
-
@fs.mutate_inputs(@form).should == {"commit"=>"foo_code", "secret"=>"foo_code", "email"=>"foo_code"}
|
34
|
-
end
|
35
|
-
|
36
|
-
it "has a signature based on action, fields, and attack name" do
|
37
|
-
@fs.signature.should == ['/session', [
|
38
|
-
"comment",
|
39
|
-
"commit",
|
40
|
-
"email",
|
41
|
-
"foo[opened_on(1i)]",
|
42
|
-
"secret"],
|
43
|
-
"foo_name"
|
44
|
-
]
|
45
|
-
end
|
46
|
-
|
47
|
-
it "has a friendly to_s" do
|
48
|
-
@fs.to_s.should =~ %r{^/session post}
|
49
|
-
end
|
50
|
-
|
51
|
-
it "processes all its attacks" do
|
52
|
-
Relevance::Tarantula::AttackFormSubmission.stubs(:attacks).returns([
|
53
|
-
Relevance::Tarantula::Attack.new({:name => 'foo_name1', :input => 'foo_input', :output => 'foo_output'}),
|
54
|
-
Relevance::Tarantula::Attack.new({:name => 'foo_name2', :input => 'foo_input', :output => 'foo_output'}),
|
55
|
-
])
|
56
|
-
Relevance::Tarantula::AttackFormSubmission.mutate(@form).size.should == 2
|
57
|
-
end
|
58
|
-
|
59
|
-
it "maps hash attacks to Attack instances" do
|
60
|
-
Relevance::Tarantula::AttackFormSubmission.instance_variable_set("@attacks", [{ :name => "attack name"}])
|
61
|
-
Relevance::Tarantula::AttackFormSubmission.attacks.should == [Relevance::Tarantula::Attack.new({:name => "attack name"})]
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
describe "Relevance::Tarantula::AttackFormSubmission for a crummy form" do
|
66
|
-
before do
|
67
|
-
@tag = Hpricot(<<END)
|
68
|
-
<form action="/session" method="post">
|
69
|
-
<input value="no_name" />
|
70
|
-
</form>
|
71
|
-
END
|
72
|
-
@form = Relevance::Tarantula::Form.new(@tag.at('form'))
|
73
|
-
@fs = Relevance::Tarantula::AttackFormSubmission.new(@form, {:name => 'foo_name', :input => 'foo_code', :output => 'foo_code'})
|
74
|
-
end
|
75
|
-
|
76
|
-
it "ignores unnamed inputs" do
|
77
|
-
@fs.mutate_inputs(@form).should == {}
|
78
|
-
end
|
79
|
-
end
|