Ref #69, #7 Proxy Auth Support Added

This commit is contained in:
Erwan
2012-11-22 15:23:59 +01:00
parent 1c2487c272
commit d802799bd2
6 changed files with 186 additions and 67 deletions

View File

@@ -11,7 +11,8 @@
SOCKS proxies (4, 4A, 5) are supported, ie : "proxy": "socks5://127.0.0.1:9000" SOCKS proxies (4, 4A, 5) are supported, ie : "proxy": "socks5://127.0.0.1:9000"
If you do not specify the protocol, http will be used If you do not specify the protocol, http will be used
*/ */
//"proxy": "127.0.0.1:3038", //"proxy": "127.0.0.1:3128",
//"proxy_auth": "username:password"
"cache_timeout": 600, // 10 minutes, at this time the cache is cleaned before each scan. If this value is set to 0, the cache will be disabled "cache_timeout": 600, // 10 minutes, at this time the cache is cleaned before each scan. If this value is set to 0, the cache will be disabled

View File

@@ -25,6 +25,7 @@ class Browser
:user_agent_mode, :user_agent_mode,
:available_user_agents, :available_user_agents,
:proxy, :proxy,
:proxy_auth,
:max_threads, :max_threads,
:cache_timeout, :cache_timeout,
:request_timeout :request_timeout
@@ -98,6 +99,29 @@ class Browser
@max_threads = max_threads @max_threads = max_threads
end end
def proxy_auth=(auth)
unless auth.nil?
if auth.is_a?(Hash)
if !auth.include?(:proxy_username) or !auth.include?(:proxy_password)
raise_invalid_proxy_format()
end
@proxy_auth = auth
elsif auth.is_a?(String)
if matches = %r{([^:]+):(.*)}.match(auth)
@proxy_auth = {:proxy_username => matches[1], :proxy_password => matches[2]}
else
raise_invalid_proxy_format()
end
else
raise_invalid_proxy_format()
end
end
end
def raise_invalid_proxy_format
raise "Invalid proxy auth format, expected username:password or {:proxy_username => username, :proxy_password => password}"
end
# TODO reload hydra (if the .load_config is called on a browser object, hydra will not have the new @max_threads and @request_timeout) # TODO reload hydra (if the .load_config is called on a browser object, hydra will not have the new @max_threads and @request_timeout)
def load_config(config_file = nil) def load_config(config_file = nil)
@config_file = config_file || @config_file @config_file = config_file || @config_file
@@ -149,6 +173,10 @@ class Browser
def merge_request_params(params = {}) def merge_request_params(params = {})
if @proxy if @proxy
params = params.merge(:proxy => @proxy) params = params.merge(:proxy => @proxy)
if @proxy_auth
params = params.merge(@proxy_auth)
end
end end
unless params.has_key?(:disable_ssl_host_verification) unless params.has_key?(:disable_ssl_host_verification)

View File

@@ -27,6 +27,7 @@ class WpscanOptions
:enumerate_usernames, :enumerate_usernames,
:enumerate_usernames_range, :enumerate_usernames_range,
:proxy, :proxy,
:proxy_auth,
:threads, :threads,
:url, :url,
:wordlist, :wordlist,
@@ -76,6 +77,14 @@ class WpscanOptions
end end
end end
def proxy_auth=(auth)
if auth.index(':') == nil
raise "Invalid proxy auth format, username:password expected"
else
@proxy_auth = auth
end
end
def enumerate_plugins=(enumerate_plugins) def enumerate_plugins=(enumerate_plugins)
if enumerate_plugins === true and @enumerate_only_vulnerable_plugins === true if enumerate_plugins === true and @enumerate_only_vulnerable_plugins === true
raise "You can't enumerate plugins and only vulnerable plugins at the same time, please choose only one" raise "You can't enumerate plugins and only vulnerable plugins at the same time, please choose only one"
@@ -201,7 +210,8 @@ class WpscanOptions
["--force", "-f", GetoptLong::NO_ARGUMENT], ["--force", "-f", GetoptLong::NO_ARGUMENT],
["--help", "-h", GetoptLong::NO_ARGUMENT], ["--help", "-h", GetoptLong::NO_ARGUMENT],
["--verbose", "-v", GetoptLong::NO_ARGUMENT], ["--verbose", "-v", GetoptLong::NO_ARGUMENT],
["--proxy", GetoptLong::OPTIONAL_ARGUMENT], ["--proxy", GetoptLong::REQUIRED_ARGUMENT],
["--proxy-auth", GetoptLong::REQUIRED_ARGUMENT],
["--update", GetoptLong::NO_ARGUMENT], ["--update", GetoptLong::NO_ARGUMENT],
["--follow-redirection", GetoptLong::NO_ARGUMENT], ["--follow-redirection", GetoptLong::NO_ARGUMENT],
["--wp-content-dir", GetoptLong::REQUIRED_ARGUMENT], ["--wp-content-dir", GetoptLong::REQUIRED_ARGUMENT],
@@ -226,7 +236,7 @@ class WpscanOptions
def self.option_to_instance_variable_setter(option) def self.option_to_instance_variable_setter(option)
cleaned_option = WpscanOptions.clean_option(option) cleaned_option = WpscanOptions.clean_option(option)
option_syms = ACCESSOR_OPTIONS.grep(%r{^#{cleaned_option}}) option_syms = ACCESSOR_OPTIONS.grep(%r{^#{cleaned_option}$})
option_syms.length == 1 ? :"#{option_syms.at(0)}=" : nil option_syms.length == 1 ? :"#{option_syms.at(0)}=" : nil
end end

View File

@@ -0,0 +1,8 @@
{
"user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:10.0) Gecko/20100101 Firefox/11.0",
"user_agent_mode": "static",
"proxy": "127.0.0.1:3038",
"proxy_auth": "user:pass",
"cache_timeout": 300,
"request_timeout": 2000
}

View File

@@ -21,6 +21,7 @@ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
describe Browser do describe Browser do
CONFIG_FILE_WITHOUT_PROXY = SPEC_FIXTURES_CONF_DIR + '/browser/browser.conf.json' CONFIG_FILE_WITHOUT_PROXY = SPEC_FIXTURES_CONF_DIR + '/browser/browser.conf.json'
CONFIG_FILE_WITH_PROXY = SPEC_FIXTURES_CONF_DIR + '/browser/browser.conf_proxy.json' CONFIG_FILE_WITH_PROXY = SPEC_FIXTURES_CONF_DIR + '/browser/browser.conf_proxy.json'
CONFIG_FILE_WITH_PROXY_AND_AUTH = SPEC_FIXTURES_CONF_DIR + '/browser/browser.conf_proxy_auth.json'
INSTANCE_VARS_TO_CHECK = ['user_agent', 'user_agent_mode', 'available_user_agents', 'proxy', 'max_threads', 'request_timeout', 'cache_timeout'] INSTANCE_VARS_TO_CHECK = ['user_agent', 'user_agent_mode', 'available_user_agents', 'proxy', 'max_threads', 'request_timeout', 'cache_timeout']
before :all do before :all do
@@ -71,6 +72,42 @@ describe Browser do
end end
end end
describe "#proxy_auth=" do
after :each do
if @raise_error
expect { @browser.proxy_auth = @proxy_auth }.to raise_error
else
@browser.proxy_auth = @proxy_auth
@browser.proxy_auth.should === @expected
end
end
it "should raise an error if the format is not correct" do
@proxy_auth = "invaludauthformat"
@raise_error = true
end
it "should raise an error if the hash does not contain :proxy_username and :proxy_password" do
@proxy_auth = { :proxy_password => "hello" }
@raise_error = true
end
it "should raise an error if the auth if not a string or a hash" do
@proxy_auth = 10
@raise_error = true
end
it "should set the correct credentials" do
@proxy_auth = {:proxy_username => "user", :proxy_password => "pass" }
@expected = @proxy_auth
end
it "should set the correct credentials" do
@proxy_auth = "username:passwd"
@expected = {:proxy_username => "username", :proxy_password => "passwd" }
end
end
describe "#user_agent" do describe "#user_agent" do
available_user_agents = %w{ ua-1 ua-2 ua-3 ua-4 ua-6 ua-7 ua-8 ua-9 ua-10 ua-11 ua-12 ua-13 ua-14 ua-15 ua-16 ua-17} available_user_agents = %w{ ua-1 ua-2 ua-3 ua-4 ua-6 ua-7 ua-8 ua-9 ua-10 ua-11 ua-12 ua-13 ua-14 ua-15 ua-16 ua-17}
@@ -156,6 +193,7 @@ describe Browser do
end end
end end
# TODO
describe "#load_config" do describe "#load_config" do
end end
@@ -214,6 +252,23 @@ describe Browser do
browser.merge_request_params().should == expected_params browser.merge_request_params().should == expected_params
end end
it "should return the default params (proxy_auth set)" do
Browser.reset
browser = Browser.instance(:config_file => CONFIG_FILE_WITH_PROXY_AND_AUTH)
expected_params = {
:proxy => @json_config_with_proxy['proxy'],
:proxy_username => "user",
:proxy_password => "pass",
:disable_ssl_host_verification => true,
:disable_ssl_peer_verification => true,
:headers => {'user-agent' => @json_config_with_proxy['user_agent']},
:cache_timeout => @json_config_with_proxy['cache_timeout']
}
browser.merge_request_params().should == expected_params
end
end end
# TODO # TODO
@@ -229,7 +284,8 @@ describe Browser do
with(:body => "login=master&password=it's me !"). with(:body => "login=master&password=it's me !").
to_return(:status => 200, :body => "Welcome Master") to_return(:status => 200, :body => "Welcome Master")
response = @browser.post(url, response = @browser.post(
url,
:params => {:login => "master", :password => "it's me !"} :params => {:login => "master", :password => "it's me !"}
) )

View File

@@ -89,11 +89,24 @@ describe "WpscanOptions" do
end end
end end
describe "#proxy_auth=" do
it "should raise an error if the format is not correct" do
expect { @wpscan_options.proxy_auth = "invalidauth" }.to raise_error
end
it "should not raise en error" do
proxy_auth = "user:pass"
@wpscan_options.proxy_auth = proxy_auth
@wpscan_options.proxy_auth.should === proxy_auth
end
end
describe "#enumerate_plugins=" do describe "#enumerate_plugins=" do
it "should raise an error" do it "should raise an error" do
@wpscan_options.enumerate_only_vulnerable_plugins = true @wpscan_options.enumerate_only_vulnerable_plugins = true
expect { @wpscan_options.enumerate_plugins = true }.to raise_error(RuntimeError, expect { @wpscan_options.enumerate_plugins = true }.to raise_error(
"You can't enumerate plugins and only vulnerable plugins at the same time, please choose only one") RuntimeError, "You can't enumerate plugins and only vulnerable plugins at the same time, please choose only one"
)
end end
it "should not raise an error" do it "should not raise an error" do
@@ -107,8 +120,9 @@ describe "WpscanOptions" do
describe "#enumerate_themes=" do describe "#enumerate_themes=" do
it "should raise an error" do it "should raise an error" do
@wpscan_options.enumerate_only_vulnerable_themes = true @wpscan_options.enumerate_only_vulnerable_themes = true
expect { @wpscan_options.enumerate_themes = true }.to raise_error(RuntimeError, expect { @wpscan_options.enumerate_themes = true }.to raise_error(
"You can't enumerate themes and only vulnerable themes at the same time, please choose only one") RuntimeError, "You can't enumerate themes and only vulnerable themes at the same time, please choose only one"
)
end end
it "should not raise an error" do it "should not raise an error" do
@@ -122,8 +136,9 @@ describe "WpscanOptions" do
describe "#enumerate_only_vulnerable_plugins=" do describe "#enumerate_only_vulnerable_plugins=" do
it "should raise an error" do it "should raise an error" do
@wpscan_options.enumerate_plugins = true @wpscan_options.enumerate_plugins = true
expect { @wpscan_options.enumerate_only_vulnerable_plugins = true }.to raise_error(RuntimeError, expect { @wpscan_options.enumerate_only_vulnerable_plugins = true }.to raise_error(
"You can't enumerate plugins and only vulnerable plugins at the same time, please choose only one") RuntimeError, "You can't enumerate plugins and only vulnerable plugins at the same time, please choose only one"
)
end end
it "should not raise an error" do it "should not raise an error" do
@@ -137,8 +152,9 @@ describe "WpscanOptions" do
describe "#enumerate_only_vulnerable_themes=" do describe "#enumerate_only_vulnerable_themes=" do
it "should raise an error" do it "should raise an error" do
@wpscan_options.enumerate_themes = true @wpscan_options.enumerate_themes = true
expect { @wpscan_options.enumerate_only_vulnerable_themes = true }.to raise_error(RuntimeError, expect { @wpscan_options.enumerate_only_vulnerable_themes = true }.to raise_error(
"You can't enumerate themes and only vulnerable themes at the same time, please choose only one") RuntimeError, "You can't enumerate themes and only vulnerable themes at the same time, please choose only one"
)
end end
it "should not raise an error" do it "should not raise an error" do
@@ -200,19 +216,19 @@ describe "WpscanOptions" do
WpscanOptions.option_to_instance_variable_setter(@argument).should === @expected WpscanOptions.option_to_instance_variable_setter(@argument).should === @expected
end end
it "should return @url" do it "should return :url=" do
@argument = "--url" @argument = "--url"
@expected = :url= @expected = :url=
end end
it "should return @verbose" do it "should return :verbose=" do
@argument = "-v" @argument = "--verbose"
@expected = :verbose= @expected = :verbose=
end end
it "should return nil for -U" do it "should return :proxy= for --proxy" do
@argument = "-U" @argument = "--proxy"
@expected = nil @expected = :proxy=
end end
it "should return nil for --enumerate" do it "should return nil for --enumerate" do
@@ -220,9 +236,9 @@ describe "WpscanOptions" do
@expected = nil @expected = nil
end end
it "should return nil for -e" do it "should return :proxy_auth= for --proxy_auth" do
@argument = "-e" @argument = "--proxy_auth"
@expected = nil @expected = :proxy_auth=
end end
end end