rspec tests for bruteforcer
This commit is contained in:
@@ -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
|
||||||
|
|||||||
6
spec/fixtures/wpscan/modules/bruteforce/wordlist.txt
vendored
Normal file
6
spec/fixtures/wpscan/modules/bruteforce/wordlist.txt
vendored
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
password1
|
||||||
|
password2
|
||||||
|
pa55w0rd
|
||||||
|
# comment
|
||||||
|
admin
|
||||||
|
root
|
||||||
72
spec/lib/wpscan/modules/brute_force_spec.rb
Normal file
72
spec/lib/wpscan/modules/brute_force_spec.rb
Normal 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
|
||||||
@@ -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"
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
Reference in New Issue
Block a user