Class: WPScan::Finders::Users::AuthorIdBruteForcing
Overview
Constant Summary
Constants inherited
from Finder
Finder::DIRECT_ACCESS
Instance Attribute Summary
Attributes inherited from Finder
#progress_bar, #target
Instance Method Summary
collapse
#enumerate, #head_or_get_request_params, #maybe_get_full_response
Methods inherited from Finder
#browser, #found_by, #hydra, #initialize, #passive, #titleize
Instance Method Details
#aggressive(opts = {}) ⇒ Array<User>
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
# File 'app/finders/users/author_id_brute_forcing.rb', line 21
def aggressive(opts = {})
shared = opts[:found]
local = shared ? nil : []
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
user = Model::User.new(
username,
id: id,
found_by: format(found_by_msg, found_by),
confidence: confidence
)
(shared || local) << user
end
local || []
end
|
#create_progress_bar(opts = {}) ⇒ Object
57
58
59
|
# File 'app/finders/users/author_id_brute_forcing.rb', line 57
def create_progress_bar(opts = {})
super(opts.merge(title: ' Brute Forcing Author IDs -'))
end
|
#display_name_from_body(body) ⇒ String?
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
# File 'app/finders/users/author_id_brute_forcing.rb', line 104
def display_name_from_body(body)
page = Nokogiri::HTML.parse(body)
page.css('h1.page-title span').each do |node|
text = node.text.to_s.strip
return text unless text.empty?
end
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
61
62
63
|
# File 'app/finders/users/author_id_brute_forcing.rb', line 61
def full_request_params
{ followlocation: true, maxredirs: 10 }
end
|
#potential_username(res) ⇒ Array<String, String, Integer>?
Returns username, found_by, confidence.
68
69
70
71
72
73
74
75
76
|
# File 'app/finders/users/author_id_brute_forcing.rb', line 68
def potential_username(res)
username = username_from_author_url(res.effective_url) || username_from_response(res)
return username, 'Author Pattern', 100 if username
username = display_name_from_body(res.body)
[username, 'Display Name', 50] if username
end
|
#target_urls(opts = {}) ⇒ Hash
47
48
49
50
51
52
53
54
55
|
# File 'app/finders/users/author_id_brute_forcing.rb', line 47
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?
81
82
83
84
85
|
# File 'app/finders/users/author_id_brute_forcing.rb', line 81
def username_from_author_url(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.
90
91
92
93
94
95
96
97
98
99
|
# File 'app/finders/users/author_id_brute_forcing.rb', line 90
def username_from_response(res)
target.in_scope_uris(res, '//@href[contains(., "author/")]') do |uri|
username = username_from_author_url(uri)
return username if username
end
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
|