Changeset 322
- Timestamp:
- 05/09/08 09:42:11 (3 months ago)
- Files:
-
- rubygems/tarantula/trunk/lib/relevance/tarantula.rb (modified) (3 diffs)
- rubygems/tarantula/trunk/lib/relevance/tarantula/crawler.rb (modified) (6 diffs)
- rubygems/tarantula/trunk/lib/relevance/tarantula/form.rb (modified) (2 diffs)
- rubygems/tarantula/trunk/lib/relevance/tarantula/form_submission.rb (modified) (4 diffs)
- rubygems/tarantula/trunk/lib/relevance/tarantula/html_document_handler.rb (modified) (3 diffs)
- rubygems/tarantula/trunk/lib/relevance/tarantula/html_reporter.rb (modified) (2 diffs)
- rubygems/tarantula/trunk/lib/relevance/tarantula/html_report_helper.rb (modified) (2 diffs)
- rubygems/tarantula/trunk/lib/relevance/tarantula/rails_integration_proxy.rb (modified) (1 diff)
- rubygems/tarantula/trunk/lib/relevance/tarantula/result.rb (modified) (1 diff)
- rubygems/tarantula/trunk/test/relevance/core_extensions/test_case_test.rb (modified) (1 diff)
- rubygems/tarantula/trunk/test/relevance/tarantula/crawler_test.rb (modified) (3 diffs)
- rubygems/tarantula/trunk/test/relevance/tarantula/form_submission_test.rb (modified) (4 diffs)
- rubygems/tarantula/trunk/test/relevance/tarantula/form_test.rb (modified) (5 diffs)
- rubygems/tarantula/trunk/test/relevance/tarantula/html_document_handler_test.rb (modified) (1 diff)
- rubygems/tarantula/trunk/test/relevance/tarantula/html_reporter_test.rb (modified) (3 diffs)
- rubygems/tarantula/trunk/test/relevance/tarantula/rails_integration_proxy_test.rb (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
rubygems/tarantula/trunk/lib/relevance/tarantula.rb
r287 r322 10 10 require 'active_support' 11 11 require 'action_controller' 12 xss_shield_path = File.join(TARANTULA_ROOT, %w{vendor xss-shield})13 $: << File.join(xss_shield_path, "lib")14 require File.join(xss_shield_path, "init")12 #xss_shield_path = File.join(TARANTULA_ROOT, %w{vendor xss-shield}) 13 #$: << File.join(xss_shield_path, "lib") 14 #require File.join(xss_shield_path, "init") 15 15 16 16 gem 'facets' … … 48 48 require 'relevance/tarantula/html_reporter' 49 49 require 'relevance/tarantula/html_report_helper' 50 require 'relevance/tarantula/io_reporter' 50 51 require 'relevance/tarantula/recording' 51 52 require 'relevance/tarantula/response' … … 57 58 require 'relevance/tarantula/form' 58 59 require 'relevance/tarantula/form_submission' 60 require 'relevance/tarantula/xss_form_submission' 61 require 'relevance/tarantula/xss_document_checker_handler' 59 62 60 63 require 'relevance/tarantula/tidy_handler' if ENV['TIDY_PATH'] rubygems/tarantula/trunk/lib/relevance/tarantula/crawler.rb
r284 r322 8 8 attr_accessor :proxy, :handlers, :skip_uri_patterns, :log_grabber, 9 9 :reporters, :links_to_crawl, :links_queued, :forms_to_crawl, 10 :form_signatures_queued, :max_url_length, :response_code_handler 10 :form_signatures_queued, :max_url_length, :response_code_handler, 11 :times_to_crawl, :fuzzers 11 12 attr_reader :transform_url_patterns, :referrers, :failures, :successes 12 13 … … 21 22 @forms_to_crawl = [] 22 23 @referrers = {} 23 @skip_uri_patterns = [24 @skip_uri_patterns = [ 24 25 /^javascript/, 25 26 /^mailto/, 26 /^http/, 27 /^http/, 27 28 ] 28 29 self.transform_url_patterns = [ 29 30 [/#.*$/, ''] 30 31 ] 31 @reporters = [ ]32 @reporters = [Relevance::Tarantula::IOReporter.new($stderr)] 32 33 @decoder = HTMLEntities.new 33 34 @times_to_crawl = 1 35 @fuzzers = [Relevance::Tarantula::FormSubmission] 34 36 end 35 37 … … 46 48 47 49 def crawl(url = "/") 48 queue_link url 49 do_crawl 50 @times_to_crawl.times do |i| 51 queue_link url 52 do_crawl 53 54 puts "#{(i+1).ordinalize} crawl" if @times_to_crawl > 1 55 56 if i + 1 < @times_to_crawl 57 @links_queued = Set.new 58 @form_signatures_queued = Set.new 59 @referrers = {} 60 end 61 end 50 62 rescue Interrupt 51 63 $stderr.puts "CTRL-C" … … 75 87 76 88 def save_result(result) 77 re turn if result.nil?78 collection = result.success ? successes : failures79 collection << result89 reporters.each do |reporter| 90 reporter.report(result) 91 end 80 92 end 81 93 … … 166 178 167 179 def queue_form(form, referrer = nil) 168 fs = FormSubmission.new(Form.new(form)) 169 fs.action = transform_url(fs.action) 170 return if should_skip_form_submission?(fs) 171 @referrers[fs.action] = referrer if referrer 172 @forms_to_crawl << fs 173 @form_signatures_queued << fs.signature 180 fuzzers.each do |fuzzer| 181 fuzzer.mutate(Form.new(form)).each do |fs| 182 # fs = fuzzer.new(Form.new(form)) 183 fs.action = transform_url(fs.action) 184 return if should_skip_form_submission?(fs) 185 @referrers[fs.action] = referrer if referrer 186 @forms_to_crawl << fs 187 @form_signatures_queued << fs.signature 188 end 189 end 174 190 end 175 191 … … 179 195 180 196 def generate_reports 181 FileUtils.mkdir_p(report_dir)197 errors = [] 182 198 reporters.each do |reporter| 183 reporter.report(report_dir, self) 184 end 185 end 186 187 def report_to_console 188 unless (failures).empty? 189 $stderr.puts "****** FAILURES" 190 failures.each do |failure| 191 $stderr.puts "#{failure.code}: #{failure.url}" 192 end 193 raise "#{failures.size} failures" 199 begin 200 reporter.finish_report 201 rescue RuntimeError => e 202 errors << e 203 end 204 end 205 unless errors.empty? 206 raise errors.map(&:message).join("\n") 194 207 end 195 208 end 196 209 197 210 def report_results 198 puts "Writing results to #{report_dir}"199 211 generate_reports 200 report_to_console201 212 end 202 213 rubygems/tarantula/trunk/lib/relevance/tarantula/form.rb
r132 r322 1 1 class Relevance::Tarantula::Form 2 2 extend Forwardable 3 def_delegators("@tag", : find_all)3 def_delegators("@tag", :search) 4 4 5 5 def initialize(tag) … … 16 16 17 17 def rails_method_hack 18 (tag = @tag. find(:tag => 'input', :attributes => { :name => '_method'})) && tag["value"]18 (tag = @tag.at('input[@name="_method"]')) && tag["value"] 19 19 end 20 20 rubygems/tarantula/trunk/lib/relevance/tarantula/form_submission.rb
r287 r322 5 5 @action = form.action 6 6 @data = mutate_selects(form).merge(mutate_text_areas(form)).merge(mutate_inputs(form)) 7 end 8 9 def self.mutate(form) 10 [self.new(form)] 7 11 end 8 12 … … 18 22 19 23 def create_random_data_for(form, tag_selector) 20 form. find_all(tag_selector).inject({}) do |form_args, input|24 form.search(tag_selector).inject({}) do |form_args, input| 21 25 # TODO: test 22 26 form_args[input['name']] = random_data(input) if input['name'] … … 26 30 27 31 def mutate_inputs(form) 28 create_random_data_for(form, :tag =>'input')32 create_random_data_for(form, 'input') 29 33 end 30 34 31 35 def mutate_text_areas(form) 32 create_random_data_for(form, :tag =>'textarea')36 create_random_data_for(form, 'textarea') 33 37 end 34 38 35 39 def mutate_selects(form) 36 form. find_all(:tag =>'select').inject({}) do |form_args, select|37 options = select. find_all(:tag =>'option')40 form.search('select').inject({}) do |form_args, select| 41 options = select.search('option') 38 42 option = options.rand 39 43 form_args[select['name']] = option['value'] … … 47 51 when /_id$/ : random_whole_number 48 52 when /uploaded_data/ : nil 53 when /^_method$/ : input['value'] 49 54 when nil : input['value'] 50 55 else random_int rubygems/tarantula/trunk/lib/relevance/tarantula/html_document_handler.rb
r233 r322 1 require 'hpricot' 2 1 3 class Relevance::Tarantula::HtmlDocumentHandler 2 4 extend Forwardable … … 11 13 body = nil 12 14 Recording.stderr do 13 body = H TML::Document.newhtml15 body = Hpricot html 14 16 end 15 17 body … … 20 22 return unless response.html? 21 23 body = html_doc_without_stderr_noise(response.body) 22 body. find_all(:tag=>'a').each do |tag|24 body.search('a').each do |tag| 23 25 queue_link(tag['href'], url) 24 26 end 25 body. find_all(:tag=>'link').each do |tag|27 body.search('link').each do |tag| 26 28 queue_link(tag['href'], url) 27 29 end 28 body. find_all(:tag =>'form').each do |form|29 form .attributes['action'] = url unless form.attributes['action']30 body.search('form').each do |form| 31 form['action'] = url unless form['action'] 30 32 queue_form(form, url) 31 33 end rubygems/tarantula/trunk/lib/relevance/tarantula/html_reporter.rb
r296 r322 1 1 class Relevance::Tarantula::HtmlReporter 2 2 3 include Relevance::Tarantula 3 attr_accessor :basedir, :results 4 attr_accessor :basedir, :results 4 5 delegate :successes, :failures, :to => :results 5 def self.report(basedir, results) 6 self.new(basedir, results) 6 7 HtmlResultOverview = Struct.new(:code, :url, :description, :method, :referrer, :file_name) 8 9 def initialize(basedir) 10 @basedir = basedir 11 @results = Struct.new(:successes, :failures).new([], []) 12 FileUtils.mkdir_p(@basedir) 7 13 end 8 9 def initialize(basedir, results) 10 @basedir = basedir 11 @results = results 14 15 def report(result) 16 return if result.nil? 17 18 create_detail_report(result) 19 20 collection = result.success ? results.successes : results.failures 21 collection << HtmlResultOverview.new( 22 result.code, result.url, result.description, result.method, result.referrer, result.file_name 23 ) 24 end 25 26 def finish_report 27 puts "Writing results to #{basedir}" 12 28 copy_styles 13 29 create_index 14 create_detail_reports15 30 end 16 17 def template(name)18 File.read(File.join(File.dirname(__FILE__), name))19 end20 21 def output(name, body)22 File.open(File.join(basedir, name), "w") do |file|23 file.write body24 end25 end26 31 27 32 def copy_styles … … 45 50 output("index.html", template.result(binding)) 46 51 end 47 48 def create_detail_reports 52 53 def template(name) 54 File.read(File.join(File.dirname(__FILE__), name)) 55 end 56 57 def output(name, body) 58 File.open(File.join(basedir, name), "w") do |file| 59 file.write body 60 end 61 end 62 63 def create_detail_report(result) 49 64 template = ERB.new(template("detail.html.erb")) 50 results.successes.each do |result| 51 output(result.file_name, template.result(result.send(:binding))) 52 end 53 results.failures.each do |result| 54 output(result.file_name, template.result(result.send(:binding))) 55 end 65 output(result.file_name, template.result(result.send(:binding))) 56 66 end 57 67 58 68 # CSS class for HTML status codes 59 69 def class_for_code(code) 60 70 "r#{Integer(code)/100}" 61 71 end 72 73 62 74 end rubygems/tarantula/trunk/lib/relevance/tarantula/html_report_helper.rb
r296 r322 1 require "erb" 1 2 module Relevance::Tarantula::HtmlReportHelper 3 include ERB::Util 2 4 include Relevance::Tarantula 3 5 def wrap_in_line_number_table(text, &blk) … … 44 46 def wrap_stack_trace_line(text) 45 47 if text =~ %r{^\s*(/[^:]+):(\d+):([^:]+)$} 46 file = $1.to_s_xss_protected48 file = h($1) # .to_s_xss_protected 47 49 line_number = $2 48 message = $3.to_s_xss_protected49 "<a href='#{textmate_url(file, line_number)}'>#{file}:#{line_number}</a>:#{message}" .mark_as_xss_protected50 message = h($3) # .to_s_xss_protected 51 "<a href='#{textmate_url(file, line_number)}'>#{file}:#{line_number}</a>:#{message}" # .mark_as_xss_protected 50 52 else 51 text.to_s_xss_protected53 h(text) # .to_s_xss_protected 52 54 end 53 55 end rubygems/tarantula/trunk/lib/relevance/tarantula/rails_integration_proxy.rb
r273 r322 19 19 [/^http:\/\/#{integration_test.host}/, ''] # strip full path down to relative 20 20 ] 21 t.reporters << Relevance::Tarantula::HtmlReporter 21 t.reporters << Relevance::Tarantula::HtmlReporter.new(t.report_dir) 22 22 t 23 23 end rubygems/tarantula/trunk/lib/relevance/tarantula/result.rb
r296 r322 31 31 end 32 32 ALLOW_NNN_FOR = /^allow_(\d\d\d)_for$/ 33 class << self33 class << self 34 34 attr_accessor :next_number 35 35 def handle(result) rubygems/tarantula/trunk/test/relevance/core_extensions/test_case_test.rb
r273 r322 5 5 it "can create the crawler" do 6 6 RailsIntegrationProxy.stubs(:rails_root).returns("STUB_RAILS_ROOT") 7 Crawler.any_instance.stubs(:rails_root).returns("STUB_RAILS_ROOT") 7 8 tarantula_crawler(stub_everything) 8 9 end rubygems/tarantula/trunk/test/relevance/tarantula/crawler_test.rb
r284 r322 83 83 it 'queues and remembers forms' do 84 84 crawler = Crawler.new 85 form = H TML::Document.new('<form action="/action" method="post"/>').find(:tag =>'form')85 form = Hpricot('<form action="/action" method="post"/>').at('form') 86 86 signature = FormSubmission.new(Form.new(form)).signature 87 87 crawler.queue_form(form) … … 99 99 100 100 describe 'Relevance::Tarantula::Crawler#report_results' do 101 it "delegates to generate_reports then report_to_console" do 102 crawler = Crawler.new 103 crawler.expects(:report_dir) 104 crawler.expects(:puts) 101 it "delegates to generate_reports" do 102 crawler = Crawler.new 105 103 crawler.expects(:generate_reports) 106 crawler.expects(:report_to_console)107 104 crawler.report_results 108 105 end … … 188 185 end 189 186 190 it "reports errors to stderr and then raises" do191 crawler = Crawler.new192 crawler.failures << stub(:code => "404", :url => "/uh-oh")193 $stderr.expects(:puts).with("****** FAILURES")194 $stderr.expects(:puts).with("404: /uh-oh")195 lambda {crawler.report_to_console}.should.raise RuntimeError196 end197 198 187 it "asks each reporter to write its report in report_dir" do 199 188 crawler = Crawler.new 200 crawler.failures << stub(:code => "404", :url => "/uh-oh")201 189 crawler.stubs(:report_dir).returns(test_output_dir) 202 190 reporter = stub_everything 203 191 reporter.expects(:report) 192 reporter.expects(:finish_report) 204 193 crawler.reporters = [reporter] 194 crawler.save_result stub(:code => "404", :url => "/uh-oh") 205 195 crawler.generate_reports 206 196 end rubygems/tarantula/trunk/test/relevance/tarantula/form_submission_test.rb
r141 r322 5 5 # TODO: add more from field types to this example form as needed 6 6 before do 7 @tag = H TML::Document.new(<<END)7 @tag = Hpricot(<<END) 8 8 <form action="/session" method="post"> 9 9 <input id="email" name="email" size="30" type="text" /> … … 17 17 </form> 18 18 END 19 @form = Relevance::Tarantula::Form.new(@tag. find(:tag =>'form'))19 @form = Relevance::Tarantula::Form.new(@tag.at('form')) 20 20 @fs = Relevance::Tarantula::FormSubmission.new(@form) 21 21 end … … 27 27 28 28 it "can mutate selects" do 29 Array.any_instance.stubs(:rand).returns(stub(:[] => "2006-stub"))29 Hpricot::Elements.any_instance.stubs(:rand).returns(stub(:[] => "2006-stub")) 30 30 @fs.mutate_selects(@form).should == {"foo[opened_on(1i)]" => "2006-stub"} 31 31 end … … 57 57 describe "Relevance::Tarantula::FormSubmission for a crummy form" do 58 58 before do 59 @tag = H TML::Document.new(<<END)59 @tag = Hpricot(<<END) 60 60 <form action="/session" method="post"> 61 61 <input value="no_name" /> 62 62 </form> 63 63 END 64 @form = Relevance::Tarantula::Form.new(@tag. find(:tag =>'form'))64 @form = Relevance::Tarantula::Form.new(@tag.at('form')) 65 65 @fs = Relevance::Tarantula::FormSubmission.new(@form) 66 66 end rubygems/tarantula/trunk/test/relevance/tarantula/form_test.rb
r132 r322 3 3 describe "Relevance::Tarantula::Form large example" do 4 4 before do 5 @tag = H TML::Document.new(<<END)5 @tag = Hpricot(<<END) 6 6 <form action="/session" method="post"> 7 7 <input name="authenticity_token" type="hidden" value="1be0d07c6e13669a87b8f52a3c7e1d1ffa77708d" /> … … 12 12 </form> 13 13 END 14 @form = Relevance::Tarantula::Form.new(@tag. find(:tag =>'form'))14 @form = Relevance::Tarantula::Form.new(@tag.at('form')) 15 15 end 16 16 … … 27 27 describe "A Relevance::Tarantula::Form" do 28 28 it "defaults method to 'get'" do 29 @tag = H TML::Document.new("<form/>")30 @form = Relevance::Tarantula::Form.new(@tag. find(:tag =>'form'))29 @tag = Hpricot("<form/>") 30 @form = Relevance::Tarantula::Form.new(@tag.at('form')) 31 31 @form.method.should == 'get' 32 32 end … … 35 35 describe "A Relevance::Tarantula::Form with a hacked _method" do 36 36 before do 37 @tag = H TML::Document.new(<<END)37 @tag = Hpricot(<<END) 38 38 <form action="/foo"> 39 39 <input name="authenticity_token" type="hidden" value="1be0d07c6e13669a87b8f52a3c7e1d1ffa77708d" /> … … 41 41 </form> 42 42 END 43 @form = Relevance::Tarantula::Form.new(@tag. find(:tag =>'form'))43 @form = Relevance::Tarantula::Form.new(@tag.at('form')) 44 44 end 45 45 rubygems/tarantula/trunk/test/relevance/tarantula/html_document_handler_test.rb
r233 r322 31 31 32 32 it "queues forms" do 33 @handler.expects(:queue_form).with{|tag,referrer| H TML::Tag=== tag}33 @handler.expects(:queue_form).with{|tag,referrer| Hpricot::Elem === tag} 34 34 @handler.handle(Result.new(:response => stub(:html? => true, :body => '<form>stuff</form>'))) 35 35 end rubygems/tarantula/trunk/test/relevance/tarantula/html_reporter_test.rb
r296 r322 7 7 FileUtils.mkdir_p(test_output_dir) 8 8 Relevance::Tarantula::Result.next_number = 0 9 @ results = (1..10).map do |index|9 @success_results = (1..10).map do |index| 10 10 Relevance::Tarantula::Result.new( 11 11 :success => true, … … 13 13 :url => "/widgets/#{index}", 14 14 :response => stub(:code => 200, :body => "<h1>header</h1>\n<p>text</p>"), 15 :referrer => "/random/#{rand(100)}", 16 :log => <<-END, 17 Made-up stack trace: 18 /some_module/some_class.rb:697:in `bad_method' 19 /some_module/other_class.rb:12345677:in `long_method' 20 this link should be <a href="#">escaped</a> 21 blah blah blah 22 END 23 :data => "{:param1 => :value, :param2 => :another_value}" 24 ) 25 end 26 @fail_results = (1..10).map do |index| 27 Relevance::Tarantula::Result.new( 28 :success => false, 29 :method => "get", 30 :url => "/widgets/#{index}", 31 :response => stub(:code => 500, :body => "<h1>header</h1>\n<p>text</p>"), 15 32 :referrer => "/random/#{rand(100)}", 16 33 :log => <<-END, … … 32 49 it "creates a report based on tarantula results" do 33 50 Relevance::Tarantula::Result.any_instance.stubs(:rails_root).returns("STUB_ROOT") 34 results = stub(:successes => @results, :failures => @results) 35 Relevance::Tarantula::HtmlReporter.report(test_output_dir, results) 51 # results = stub(:successes => @results, :failures => @results) 52 reporter = Relevance::Tarantula::HtmlReporter.new(test_output_dir) 53 (@success_results + @fail_results).each {|r| reporter.report(r)} 54 reporter.finish_report 36 55 File.should.exist @index 37 56 File.should.exist @detail rubygems/tarantula/trunk/test/relevance/tarantula/rails_integration_proxy_test.rb
r273 r322 5 5 before { 6 6 Crawler.any_instance.stubs(:crawl) 7 Crawler.any_instance.stubs(:rails_root).returns("STUB_RAILS_ROOT") 7 8 RailsIntegrationProxy.stubs(:rails_root).returns("STUB_RAILS_ROOT") 8 9 }
