Class: WPScan::Finders::Users::AuthorIdBruteForcing

Inherits:
CMSScanner::Finders::Finder
  • Object
show all
Includes:
CMSScanner::Finders::Finder::Enumerator
Defined in:
app/finders/users/author_id_brute_forcing.rb

Overview

Author Id Brute Forcing

Instance Method Summary collapse

Instance Method Details

#aggressive(opts = {}) ⇒ Array<User>

Parameters:

  • opts (Hash) (defaults to: {})

Options Hash (opts):

  • :range (Range)

    Mandatory

Returns:



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# File 'app/finders/users/author_id_brute_forcing.rb', line 12

def aggressive(opts = {})
  found = []
  found_by_msg = 'Author Id Brute Forcing - %s (Aggressive Detection)'

  enumerate(target_urls(opts), opts) do |res, id|
    username, found_by, confidence = potential_username(res)

    next unless username

    found << WPScan::User.new(
      username,
      id: id,
      found_by: format(found_by_msg, found_by),
      confidence: confidence
    )
  end

  found
end

#create_progress_bar(opts = {}) ⇒ Object



46
47
48
# File 'app/finders/users/author_id_brute_forcing.rb', line 46

def create_progress_bar(opts = {})
  super(opts.merge(title: ' Brute Forcing Author Ids -'))
end

#display_name_from_body(body) ⇒ String?

Parameters:

  • body (String)

Returns:

  • (String, nil)


91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'app/finders/users/author_id_brute_forcing.rb', line 91

def display_name_from_body(body)
  page = Nokogiri::HTML.parse(body)
  # WP >= 3.0
  page.css('h1.page-title span').each do |node|
    return node.text.to_s
  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

#potential_username(res) ⇒ Array<String, String, Integer>?

Returns username, found_by, confidence.

Parameters:

  • res (Typhoeus::Response)

Returns:

  • (Array<String, String, Integer>, nil)

    username, found_by, confidence



57
58
59
60
61
62
63
64
65
# File 'app/finders/users/author_id_brute_forcing.rb', line 57

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)

  return username, 'Display Name', 50 if username
end

#request_paramsObject



50
51
52
# File 'app/finders/users/author_id_brute_forcing.rb', line 50

def request_params
  { followlocation: true }
end

#target_urls(opts = {}) ⇒ Hash

Parameters:

  • opts (Hash) (defaults to: {})

Options Hash (opts):

  • :range (Range)

Returns:

  • (Hash)


36
37
38
39
40
41
42
43
44
# File 'app/finders/users/author_id_brute_forcing.rb', line 36

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(url) ⇒ String?

Parameters:

  • url (String)

Returns:

  • (String, nil)


70
71
72
# File 'app/finders/users/author_id_brute_forcing.rb', line 70

def username_from_author_url(url)
  url[%r{/author/([^/\b]+)/?}i, 1]
end

#username_from_response(res) ⇒ String?

Returns The username found.

Parameters:

  • res (Typhoeus::Response)

Returns:

  • (String, nil)

    The username found



77
78
79
80
81
82
83
84
85
86
# File 'app/finders/users/author_id_brute_forcing.rb', line 77

def username_from_response(res)
  # Permalink enabled
  target.in_scope_urls(res, '//link|//a') do |url|
    username = username_from_author_url(url)
    return username if username
  end

  # No permalink
  res.body[/<body class="archive author author-([^\s]+)[ "]/i, 1]
end