Class: WPScan::Finders::Users::AuthorIdBruteForcing
- Inherits:
-
CMSScanner::Finders::Finder
- Object
- CMSScanner::Finders::Finder
- WPScan::Finders::Users::AuthorIdBruteForcing
- Includes:
- CMSScanner::Finders::Finder::Enumerator
- Defined in:
- app/finders/users/author_id_brute_forcing.rb
Overview
Author Id Brute Forcing
Instance Method Summary collapse
- #aggressive(opts = {}) ⇒ Array<User>
- #create_progress_bar(opts = {}) ⇒ Object
- #display_name_from_body(body) ⇒ String?
- #full_request_params ⇒ Object
-
#potential_username(res) ⇒ Array<String, String, Integer>?
Username, found_by, confidence.
- #target_urls(opts = {}) ⇒ Hash
- #username_from_author_url(uri) ⇒ String?
-
#username_from_response(res) ⇒ String?
The username found.
- #valid_response_codes ⇒ Array<Integer>
Instance Method Details
#aggressive(opts = {}) ⇒ Array<User>
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# File 'app/finders/users/author_id_brute_forcing.rb', line 19 def aggressive(opts = {}) found = [] found_by_msg = 'Author Id Brute Forcing - %s (Aggressive Detection)' enumerate(target_urls(opts), opts.merge(check_full_response: true)) do |res, id| username, found_by, confidence = potential_username(res) next unless username found << Model::User.new( username, id: id, found_by: format(found_by_msg, found_by), confidence: confidence ) end found end |
#create_progress_bar(opts = {}) ⇒ Object
53 54 55 |
# File 'app/finders/users/author_id_brute_forcing.rb', line 53 def (opts = {}) super(opts.merge(title: ' Brute Forcing Author IDs -')) end |
#display_name_from_body(body) ⇒ String?
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 |
# File 'app/finders/users/author_id_brute_forcing.rb', line 100 def display_name_from_body(body) page = Nokogiri::HTML.parse(body) # WP >= 3.0 page.css('h1.page-title span').each do |node| text = node.text.to_s.strip return text unless text.empty? end # WP < 3.0 page.xpath('//link[@rel="alternate" and @type="application/rss+xml"]').each do |node| title = node['title'] next unless title =~ /Posts by (.*) Feed\z/i return Regexp.last_match[1] unless Regexp.last_match[1].empty? end nil end |
#full_request_params ⇒ Object
57 58 59 |
# File 'app/finders/users/author_id_brute_forcing.rb', line 57 def full_request_params { followlocation: true } end |
#potential_username(res) ⇒ Array<String, String, Integer>?
Returns username, found_by, confidence.
64 65 66 67 68 69 70 71 72 |
# File 'app/finders/users/author_id_brute_forcing.rb', line 64 def potential_username(res) username = (res.effective_url) || username_from_response(res) return username, 'Author Pattern', 100 if username username = display_name_from_body(res.body) return username, 'Display Name', 50 if username end |
#target_urls(opts = {}) ⇒ Hash
43 44 45 46 47 48 49 50 51 |
# File 'app/finders/users/author_id_brute_forcing.rb', line 43 def target_urls(opts = {}) urls = {} opts[:range].each do |id| urls[target.uri.join("?author=#{id}").to_s] = id end urls end |
#username_from_author_url(uri) ⇒ String?
77 78 79 80 81 |
# File 'app/finders/users/author_id_brute_forcing.rb', line 77 def (uri) uri = Addressable::URI.parse(uri) unless uri.is_a?(Addressable::URI) uri.path[%r{/author/([^/\b]+)/?}i, 1] end |
#username_from_response(res) ⇒ String?
Returns The username found.
86 87 88 89 90 91 92 93 94 95 |
# File 'app/finders/users/author_id_brute_forcing.rb', line 86 def username_from_response(res) # Permalink enabled target.in_scope_uris(res, '//@href[contains(., "author/")]') do |uri| username = (uri) return username if username end # No permalink, TODO Maybe use xpath to extract the classes ? res.body[/<body class="archive author author-([^\s]+)[ "]/i, 1] end |
#valid_response_codes ⇒ Array<Integer>
11 12 13 |
# File 'app/finders/users/author_id_brute_forcing.rb', line 11 def valid_response_codes @valid_response_codes ||= [200, 301, 302] end |