class Sekureco::WebCrawler
Constants
- MAX_DIST_FROM_SOURCE_PAGE
Public Class Methods
new(url, username = nil, password = nil, app_token = 'foo')
click to toggle source
# File lib/sekureco/web_crawler.rb, line 21 def initialize url, username = nil, password = nil, app_token = 'foo' @uri = URI url @http_client = HttpClient.new @source_page = HtmlPage.new @http_client.get(@uri).body @visited = {} @default_username = username @default_password = password @black_list = [] @app_token = app_token end
Public Instance Methods
crawl()
click to toggle source
# File lib/sekureco/web_crawler.rb, line 32 def crawl @queue = [@source_page] mark_as_visited @source_page @distance = { @source_page => 0 } until @queue.empty? @current_page = @queue.shift @current_page.log unless too_deep? @current_page test_forms_of @current_page if @current_page.has_forms? @current_page.links.each do |current_link| begin next_link = URI.join(@uri.to_s, URI::encode(parse(current_link))) next if next_link.path.include? 'logout' response = if current_link["data-method"] @http_client.post(next_link, { '_method' => current_link['data-method'], 'authenticity_token' => @current_page.csrf_token }) else @http_client.get(next_link) end next_page = HtmlPage.new(response.body) unless already_visited?(next_page) next_page.log mark_as_visited next_page update_distance next_page @queue << next_page end rescue Sekureco.logger.warn "Invalid URI: #{current_link}" end end end if detect_embedded_scripts_in(@current_page) Sekureco.logger.info "Successfully applied XSS attack" @vulnerabilities_found = true confirm_attack end end clear_visited_pages end
test_application()
click to toggle source
# File lib/sekureco/web_crawler.rb, line 97 def test_application 2.times { self.crawl } clear_temporary_files @vulnerabilities_found end
test_forms_of(html_page)
click to toggle source
# File lib/sekureco/web_crawler.rb, line 72 def test_forms_of html_page html_page.forms.each do |form| params = {} form.css("input, textarea").each do |input| field_name = input['name'] next if field_name.nil? if possible_login_fields.any? { |s| field_name.include? s } params[field_name] = @default_username || random_string elsif possible_password_fields.any? { |s| field_name.include? s } params[field_name] = @default_password || random_string else params[field_name] = input['value'] || input['content'] || xss_attack end end response = @http_client.post(URI.join(@uri.to_s, form['action']), params) next_page = HtmlPage.new(response.body) unless already_visited?(next_page) next_page.log mark_as_visited next_page update_distance next_page @queue << next_page end end end
Private Instance Methods
already_visited?(page)
click to toggle source
# File lib/sekureco/web_crawler.rb, line 113 def already_visited? page @visited[page.parsed_body] end
clear_temporary_files()
click to toggle source
# File lib/sekureco/web_crawler.rb, line 167 def clear_temporary_files system "wmctrl -c Firefox" end
clear_visited_pages()
click to toggle source
# File lib/sekureco/web_crawler.rb, line 109 def clear_visited_pages @visited = {} end
confirm_attack()
click to toggle source
# File lib/sekureco/web_crawler.rb, line 145 def confirm_attack File.open(current_page_file_path, "w+") { |f| f.write(@current_page) } system "xdg-open #{current_page_file_path}" end
current_page_file_path()
click to toggle source
# File lib/sekureco/web_crawler.rb, line 163 def current_page_file_path "#{Dir.pwd}/log/current_page_#{@app_token}.html" end
detect_embedded_scripts_in(html_page)
click to toggle source
# File lib/sekureco/web_crawler.rb, line 150 def detect_embedded_scripts_in html_page html_page.scripts_with(@app_token).any? end
mark_as_visited(page)
click to toggle source
# File lib/sekureco/web_crawler.rb, line 105 def mark_as_visited page @visited[page.parsed_body] = true end
parse(link)
click to toggle source
# File lib/sekureco/web_crawler.rb, line 154 def parse link uri = URI::parse(link["href"]) if uri.query uri.path + "?" + uri.query else uri.path end end
possible_login_fields()
click to toggle source
# File lib/sekureco/web_crawler.rb, line 125 def possible_login_fields %w(username user name email login uid) end
possible_password_fields()
click to toggle source
# File lib/sekureco/web_crawler.rb, line 129 def possible_password_fields %w(password passwd pw) end
random_string()
click to toggle source
# File lib/sekureco/web_crawler.rb, line 133 def random_string @random_string ||= (0..(1 + rand(16))).map { ('a'..'z').to_a[rand(26)] }.join end
too_deep?(page)
click to toggle source
# File lib/sekureco/web_crawler.rb, line 121 def too_deep? page @distance[page] >= MAX_DIST_FROM_SOURCE_PAGE end
update_distance(page)
click to toggle source
# File lib/sekureco/web_crawler.rb, line 117 def update_distance page @distance[page] = @distance[@current_page] + 1 end
xss_attack()
click to toggle source
# File lib/sekureco/web_crawler.rb, line 137 def xss_attack "<script class='#{@app_token}'> let image = new Image(); image.src = 'http://localhost:4000/confirm/#{@app_token}'; alert('Successfully applied XSS attack!'); </script>" end