diff --git a/README b/README index 9f4cbb3e..2d4ff7ee 100644 --- a/README +++ b/README @@ -140,7 +140,9 @@ ryandewhurst at gmail --exclude-content-based '' Used with the enumeration option, will exclude all occurrences based on the regexp or string supplied You do not need to provide the regexp delimiters, but you must write the quotes (simple or double) ---config-file | -c Use the specified config file +--user-agent | -a Use the specified User-Agent + +--random-agent | -r Use a random User-Agent --follow-redirection If the target url has a redirection, it will be followed without asking if you wanted to do so or not diff --git a/README.md b/README.md index f7a1b876..7115707a 100644 --- a/README.md +++ b/README.md @@ -154,7 +154,9 @@ Apple Xcode, Command Line Tools and the libffi are needed (to be able to install --exclude-content-based '' Used with the enumeration option, will exclude all occurrences based on the regexp or string supplied You do not need to provide the regexp delimiters, but you must write the quotes (simple or double) - --config-file | -c Use the specified config file + --user-agent | -a Use the specified User-Agent + + --random-agent | -r Use a random User-Agent --follow-redirection If the target url has a redirection, it will be followed without asking if you wanted to do so or not diff --git a/data/user-agents.txt b/data/user-agents.txt new file mode 100644 index 00000000..861cf79e --- /dev/null +++ b/data/user-agents.txt @@ -0,0 +1,36 @@ +# Windows +Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/532.5 (KHTML, like Gecko) Chrome/4.0.249.0 Safari/532.5 +Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) AppleWebKit/534.14 (KHTML, like Gecko) Chrome/9.0.601.0 Safari/534.14 +Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/534.27 (KHTML, like Gecko) Chrome/12.0.712.0 Safari/534.27 +Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.24 Safari/535.1 +Mozilla/5.0 (Windows; U; Windows NT 5.1; tr; rv:1.9.2.8) Gecko/20100722 Firefox/3.6.8 ( .NET CLR 3.5.30729; .NET4.0E) +Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 +Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 +Mozilla/5.0 (Windows NT 6.1; WOW64; rv:7.0.1) Gecko/20100101 Firefox/7.0.1 +Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 (KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6 +Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 +Mozilla/5.0 (Windows NT 6.1; rv:12.0) Gecko/20120403211507 Firefox/12.0 +Mozilla/5.0 (Windows NT 6.1; WOW64; rv:15.0) Gecko/20120427 Firefox/15.0a1 +Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1; Trident/4.0) +Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0) +Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; Trident/6.0) +Opera/9.80 (Windows NT 6.1; U; es-ES) Presto/2.9.181 Version/12.00 +Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US) AppleWebKit/533.19.4 (KHTML, like Gecko) Version/5.0.2 Safari/533.18.5 + +# MAC +Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_5; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.15 Safari/534.13 +Mozilla/5.0 (Macintosh; U; PPC Mac OS X 10.5; en-US; rv:1.9.2.15) Gecko/20110303 Firefox/3.6.15 +Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1 +Mozilla/5.0 (Macintosh; U; PPC Mac OS X; en) AppleWebKit/418.8 (KHTML, like Gecko) Safari/419.3 +Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 (KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3 +Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_2; rv:10.0.1) Gecko/20100101 Firefox/10.0.1 +Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/534.55.3 (KHTML, like Gecko) Version/5.1.3 Safari/534.53.10 + +# Linux +Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.1 (KHTML, like Gecko) Chrome/13.0.782.20 Safari/535.1 +Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/534.24 (KHTML, like Gecko) Ubuntu/10.10 Chromium/12.0.703.0 Chrome/12.0.703.0 Safari/534.24 +Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.9) Gecko/20100915 Gentoo Firefox/3.6.9 +Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.1.16) Gecko/20120421 Gecko Firefox/11.0 +Mozilla/5.0 (X11; Linux i686; rv:12.0) Gecko/20100101 Firefox/12.0 +Opera/9.80 (X11; Linux x86_64; U; pl) Presto/2.7.62 Version/11.00 +Mozilla/5.0 (X11; U; Linux x86_64; us; rv:1.9.1.19) Gecko/20110430 shadowfox/7.0 (like Firefox/7.0 diff --git a/lib/common/browser.rb b/lib/common/browser.rb index c97d4549..74c41fff 100644 --- a/lib/common/browser.rb +++ b/lib/common/browser.rb @@ -12,7 +12,7 @@ class Browser :basic_auth, :cache_ttl, :max_threads, - :useragent, + :user_agent, :proxy, :proxy_auth, :request_timeout, @@ -66,7 +66,7 @@ class Browser @cache_ttl = 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 @request_timeout = 2000 # 2s @connect_timeout = 1000 # 1s - @useragent = "WPScan v#{WPSCAN_VERSION} (http://wpscan.org)" + @user_agent = "WPScan v#{WPSCAN_VERSION} (http://wpscan.org)" end # @param [ String ] url @@ -84,7 +84,7 @@ class Browser params = Browser.append_params_header_field( params, 'User-Agent', - @useragent + @user_agent ) if @proxy diff --git a/lib/common/browser/options.rb b/lib/common/browser/options.rb index 2ca3c227..7f761e54 100644 --- a/lib/common/browser/options.rb +++ b/lib/common/browser/options.rb @@ -5,7 +5,7 @@ class Browser attr_accessor :cache_ttl, :request_timeout, :connect_timeout attr_reader :basic_auth, :proxy, :proxy_auth - attr_writer :useragent + attr_writer :user_agent # Sets the Basic Authentification credentials # Accepted format: diff --git a/lib/common/common_helper.rb b/lib/common/common_helper.rb index 6e1e532e..cd3fa6bc 100644 --- a/lib/common/common_helper.rb +++ b/lib/common/common_helper.rb @@ -32,6 +32,7 @@ LOCAL_FILES_FILE = DATA_DIR + '/local_vulnerable_files.xml' VULNS_XSD = DATA_DIR + '/vuln.xsd' WP_VERSIONS_XSD = DATA_DIR + '/wp_versions.xsd' LOCAL_FILES_XSD = DATA_DIR + '/local_vulnerable_files.xsd' +USER_AGENTS_FILE = DATA_DIR + '/user-agents.txt' WPSCAN_VERSION = '2.3' @@ -187,3 +188,19 @@ def truncate(input, size, trailing = '...') trailing.length >= input.length or size-trailing.length-1 >= input.length return "#{input[0..size-trailing.length-1]}#{trailing}" end + +# Gets a random User-Agent +# +# @return [ String ] A random user-agent from data/user-agents.txt +def get_random_user_agent + user_agents = [] + f = File.open(USER_AGENTS_FILE, 'r') + f.each_line do |line| + # ignore comments + next if line.empty? or line =~ /^\s*(#|\/\/)/ + user_agents << line.strip + end + f.close + # return ransom user-agent + user_agents.sample +end diff --git a/lib/wpscan/wpscan_helper.rb b/lib/wpscan/wpscan_helper.rb index 68d5ed4d..44d409e4 100644 --- a/lib/wpscan/wpscan_helper.rb +++ b/lib/wpscan/wpscan_helper.rb @@ -82,7 +82,8 @@ def help puts puts '--exclude-content-based "" Used with the enumeration option, will exclude all occurrences based on the regexp or string supplied' puts ' You do not need to provide the regexp delimiters, but you must write the quotes (simple or double)' - puts '--config-file | -c Use the specified config file' + puts '--user-agent | -a Use the specified User-Agent' + puts '--random-agent | -r Use a random User-Agent' puts '--follow-redirection If the target url has a redirection, it will be followed without asking if you wanted to do so or not' puts '--wp-content-dir WPScan try to find the content directory (ie wp-content) by scanning the index page, however you can specified it. Subdirectories are allowed' puts '--wp-plugins-dir Same thing than --wp-content-dir but for the plugins directory. If not supplied, WPScan will use wp-content-dir/plugins. Subdirectories are allowed' diff --git a/lib/wpscan/wpscan_options.rb b/lib/wpscan/wpscan_options.rb index d5a29114..c88ffebb 100644 --- a/lib/wpscan/wpscan_options.rb +++ b/lib/wpscan/wpscan_options.rb @@ -31,7 +31,8 @@ class WpscanOptions :basic_auth, :debug_output, :version, - :useragent + :user_agent, + :random_agent ] attr_accessor *ACCESSOR_OPTIONS @@ -137,6 +138,10 @@ class WpscanOptions !to_h.empty? end + def random_agent=(a) + @user_agent = get_random_user_agent + end + # return Hash def to_h options = {} @@ -228,7 +233,8 @@ class WpscanOptions ['--wordlist', '-w', GetoptLong::REQUIRED_ARGUMENT], ['--threads', '-t', GetoptLong::REQUIRED_ARGUMENT], ['--force', '-f', GetoptLong::NO_ARGUMENT], - ['--useragent', '-a', GetoptLong::REQUIRED_ARGUMENT], + ['--user-agent', '-a', GetoptLong::REQUIRED_ARGUMENT], + ['--random-agent', '-r', GetoptLong::NO_ARGUMENT], ['--help', '-h', GetoptLong::NO_ARGUMENT], ['--verbose', '-v', GetoptLong::NO_ARGUMENT], ['--proxy', GetoptLong::REQUIRED_ARGUMENT], @@ -237,7 +243,6 @@ class WpscanOptions ['--follow-redirection', GetoptLong::NO_ARGUMENT], ['--wp-content-dir', GetoptLong::REQUIRED_ARGUMENT], ['--wp-plugins-dir', GetoptLong::REQUIRED_ARGUMENT], - ['--config-file', '-c', GetoptLong::REQUIRED_ARGUMENT], ['--exclude-content-based', GetoptLong::REQUIRED_ARGUMENT], ['--basic-auth', GetoptLong::REQUIRED_ARGUMENT], ['--debug-output', GetoptLong::NO_ARGUMENT], diff --git a/spec/lib/common/browser_spec.rb b/spec/lib/common/browser_spec.rb index f023c3aa..cf0aa4fd 100644 --- a/spec/lib/common/browser_spec.rb +++ b/spec/lib/common/browser_spec.rb @@ -12,7 +12,7 @@ describe Browser do } let(:options) { {} } let(:instance_vars_to_check) { - ['useragent', 'proxy', + ['user-agent', 'random-agent', 'proxy', 'max_threads', 'cache_ttl', 'request_timeout', 'connect_timeout'] } @@ -76,7 +76,7 @@ describe Browser do } after :each do - browser.useragent = 'SomeUA' + browser.user_agent = 'SomeUA' browser.cache_ttl = 250 browser.merge_request_params(params).should == @expected