Class: WPScan::Controller::BruteForce

Inherits:
CMSScanner::Controller::Base
  • Object
show all
Defined in:
app/controllers/brute_force.rb

Overview

Brute Force Controller

Instance Method Summary collapse

Instance Method Details

#brute_force(users, passwords) {|User| ... } ⇒ Object

the iteration should be on the passwords to be more efficient however, it’s not that simple expecially when a combination is found:

- the estimated number of requests (for the progressbar) has to be updated.
- the user found has to be deleted from the loop

Parameters:

  • users (Array<User>)
  • passwords (Array<String>)

Yields:

  • (User)

    when a valid combination is found



51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'app/controllers/brute_force.rb', line 51

def brute_force(users, passwords)
  hydra = Browser.instance.hydra

  users.each do |user|
    bar = progress_bar(passwords.size, user.username) if user_interaction?

    passwords.each do |password|
      request = target.(user.username, password)

      request.on_complete do |res|
        bar.progress += 1 if user_interaction?

        if res.code == 302
          user.password = password
          hydra.abort

          yield user
          next
        elsif user_interaction? && res.code != 200
          # Errors not displayed when using formats other than cli/cli-no-colour
          output_error(res)
        end
      end

      hydra.queue(request)
    end
    hydra.run
  end
end

#cli_optionsObject



5
6
7
8
9
10
11
12
13
14
15
# File 'app/controllers/brute_force.rb', line 5

def cli_options
  [
    OptFilePath.new(
      ['--passwords FILE-PATH', '-P',
       'List of passwords to use during the brute forcing.',
       'If no --username/s option supplied, user enumeration will be run'],
      exists: true
    ),
    OptSmartList.new(['--usernames LIST', '-U', 'List of usernames to use during the brute forcing'])
  ]
end

#output_error(response) ⇒ Object

Parameters:

  • response (Typhoeus::Response)


99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# File 'app/controllers/brute_force.rb', line 99

def output_error(response)
  return if response.body =~ /login_error/i

  error = if response.timed_out?
            'Request timed out.'
          elsif response.code.zero?
            "No response from remote server. WAF/IPS? (#{response.return_message})"
          elsif response.code.to_s =~ /^50/
            'Server error, try reducing the number of threads.'
          else
            "Unknown response received Code: #{response.code}\n Body: #{response.body}"
          end

  output('error', msg: error)
end

#passwords(wordlist_path) ⇒ Array<String>

Parameters:

  • wordlist_path (String)

Returns:

  • (Array<String>)


92
93
94
95
96
# File 'app/controllers/brute_force.rb', line 92

def passwords(wordlist_path)
  @passwords ||= File.open(wordlist_path).reduce([]) do |acc, elem|
    acc << elem.chomp
  end
end

#progress_bar(size, username) ⇒ Object



81
82
83
84
85
86
87
# File 'app/controllers/brute_force.rb', line 81

def progress_bar(size, username)
  ProgressBar.create(
    format: '%t %a <%B> (%c / %C) %P%% %e',
    title: "Brute Forcing #{username} -",
    total: size
  )
end

#runObject



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'app/controllers/brute_force.rb', line 17

def run
  return unless parsed_options[:passwords]

  begin
    found = []

    brute_force(users, passwords(parsed_options[:passwords])) do |user|
      found << user

      output('found', user: user) if user_interaction?
    end
  ensure
    output('users', users: found)
  end
end

#usersArray<Users>

Returns The users to brute force.

Returns:

  • (Array<Users>)

    The users to brute force



34
35
36
37
38
39
40
# File 'app/controllers/brute_force.rb', line 34

def users
  return target.users unless parsed_options[:usernames]

  parsed_options[:usernames].reduce([]) do |acc, elem|
    acc << User.new(elem.chomp)
  end
end