rspec tests for bruteforcer

This commit is contained in:
Christian Mehlmauer
2012-09-21 20:53:31 +02:00
parent 8998b41191
commit 7a224a078b
5 changed files with 90 additions and 8 deletions

View File

@@ -24,16 +24,17 @@ module BruteForce
hydra = Browser.instance.hydra hydra = Browser.instance.hydra
number_of_passwords = BruteForce.lines_in_file(wordlist_path) number_of_passwords = BruteForce.lines_in_file(wordlist_path)
login_url = login_url() login_url = login_url()
found = []
logins.each do |login| logins.each do |login|
queue_count = 0 queue_count = 0
request_count = 0 request_count = 0
password_found = false password_found = false
File.open(wordlist_path, 'r').each do |password| File.open(wordlist_path, "r").each do |password|
# ignore file comments, but will miss passwords if they start with a hash... # ignore file comments, but will miss passwords if they start with a hash...
next if password[0,1] == '#' next if password[0,1] == "#"
# keep a count of the amount of requests to be sent # keep a count of the amount of requests to be sent
request_count += 1 request_count += 1
@@ -61,18 +62,20 @@ module BruteForce
puts "\nIncorrect username and/or password." if @verbose puts "\nIncorrect username and/or password." if @verbose
elsif response.code == 302 elsif response.code == 302
puts "\n [SUCCESS] Username : #{username} Password : #{password}\n" puts "\n [SUCCESS] Username : #{username} Password : #{password}\n"
found << { :name => username, :password => password }
password_found = true password_found = true
elsif response.timed_out? elsif response.timed_out?
puts "ERROR: Request timed out." puts "ERROR: Request timed out."
elsif response.code == 0 elsif response.code == 0
puts "ERROR: No response from remote server. WAF/IPS?" puts "ERROR: No response from remote server. WAF/IPS?"
elsif response.code =~ /^50/ # code is a fixnum, needs a string for regex
elsif response.code.to_s =~ /^50/
puts "ERROR: Server error, try reducing the number of threads." puts "ERROR: Server error, try reducing the number of threads."
else else
puts "\nERROR: We recieved an unknown response for #{password}..." puts "\nERROR: We recieved an unknown response for #{password}..."
if @verbose if @verbose
puts 'Code: ' + response.code.to_s puts "Code: #{response.code.to_s}"
puts 'Body: ' + response.body puts "Body: #{response.body}"
puts puts
end end
end end
@@ -102,7 +105,7 @@ module BruteForce
# run all of the remaining requests # run all of the remaining requests
hydra.run hydra.run
end end
found
end end
# Counts the number of lines in the wordlist # Counts the number of lines in the wordlist
@@ -110,7 +113,7 @@ module BruteForce
# wordlists, although bareable. # wordlists, although bareable.
def self.lines_in_file(file_path) def self.lines_in_file(file_path)
lines = 0 lines = 0
File.open(file_path, 'r').each { |line| lines += 1 } File.open(file_path, 'r').each { || lines += 1 }
lines lines
end end
end end

View File

@@ -0,0 +1,6 @@
password1
password2
pa55w0rd
# comment
admin
root

View File

@@ -0,0 +1,72 @@
#--
# WPScan - WordPress Security Scanner
# Copyright (C) 2012
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#++
shared_examples_for "BruteForce" do
before :each do
@module = WpScanModuleSpec.new("http://example.localhost")
@target_url = @module.uri.to_s
@fixtures_dir = SPEC_FIXTURES_WPSCAN_MODULES_DIR + "/bruteforce"
@wordlist = @fixtures_dir + "/wordlist.txt"
@username = "admin"
@module.extend(BruteForce)
@module.verbose = true
Browser.instance.max_threads = 1
end
describe "#lines_in_file" do
it "should return 6" do
lines = BruteForce.lines_in_file(@wordlist)
lines.should == 6
end
end
describe "#brute_force" do
before :each do
end
it "should get the correct password" do
passwords = []
File.open(@wordlist, "r").each do |password|
# ignore comments
passwords << password.strip unless password.strip[0,1] == "#"
end
# Last status must be 302 to get full code coverage
passwords.each do ||
stub_request(:any, @module.login_url).to_return( { :status => 200, :body => "login_error" },
{ :status => 0, :body => "no reponse" },
{ :status => 50, :body => "server error" },
{ :status => 999, :body => "invalid" },
{ :status => 302, :body => "FOUND!" })
end
user = WpUser.new("admin", 1, nil)
result = @module.brute_force([user], @wordlist)
result.length.should == 1
result.should === [{ :name => "admin", :password => "root" }]
end
it "should cover the timeout branch and return an empty array" do
stub_request(:any, @module.login_url).to_timeout
user = WpUser.new("admin", 1, nil)
result = @module.brute_force([user], @wordlist)
result.should == []
end
end
end

View File

@@ -37,6 +37,7 @@ describe WpTarget do
it_should_behave_like "WpFullPathDisclosure" it_should_behave_like "WpFullPathDisclosure"
it_should_behave_like "WpLoginProtection" it_should_behave_like "WpLoginProtection"
it_should_behave_like "Malwares" it_should_behave_like "Malwares"
it_should_behave_like "BruteForce"
it_should_behave_like "WpUsernames" it_should_behave_like "WpUsernames"
it_should_behave_like "WpTimthumbs" it_should_behave_like "WpTimthumbs"
it_should_behave_like "WpPlugins" it_should_behave_like "WpPlugins"

View File

@@ -30,7 +30,7 @@ SPEC_FIXTURES_WPSCAN_WP_VERSION_DIR = SPEC_FIXTURES_WPSCAN_DIR + '/wp_version'
class WpScanModuleSpec class WpScanModuleSpec
attr_reader :uri attr_reader :uri
attr_accessor :error_404_hash, :wp_content_dir attr_accessor :error_404_hash, :wp_content_dir, :verbose
def initialize(target_url) def initialize(target_url)
@uri = URI.parse(add_http_protocol(target_url)) @uri = URI.parse(add_http_protocol(target_url))