Module: WpUser::BruteForcable
- Included in:
- WpUser
- Defined in:
- lib/common/models/wp_user/brute_forcable.rb
Class Method Summary (collapse)
-
+ (Array<String>) passwords_from_wordlist(wordlist)
Load the passwords from the wordlist, which can be a file path or an array or passwords.
Instance Method Summary (collapse)
-
- (void) brute_force(wordlist, options = {})
Brute force the user with the wordlist supplied.
- - (Typhoeus::Request) login_request(password)
-
- (ProgressBar) progress_bar(passwords_size, options)
:nocov:.
- - (Boolean) valid_password?(response, password, options = {})
Class Method Details
+ (Array<String>) passwords_from_wordlist(wordlist)
Load the passwords from the wordlist, which can be a file path or an array or passwords
File comments are ignored, but will miss passwords if they start with a hash...
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/common/models/wp_user/brute_forcable.rb', line 125 def self.passwords_from_wordlist(wordlist) if wordlist.is_a?(String) passwords = [] charset = File.charset(wordlist).upcase opt = "r:#{charset}" # To remove warning when charset = UTF-8 # Ignoring internal encoding UTF-8: it is identical to external encoding utf-8 opt += ':UTF-8' if charset != 'UTF-8' File.open(wordlist, opt).each do |line| next if line[0,1] == '#' passwords << line.strip end elsif wordlist.is_a?(Array) passwords = wordlist else raise 'Invalid wordlist, expected String or Array' end passwords end |
Instance Method Details
- (void) brute_force(wordlist, options = {})
This method returns an undefined value.
Brute force the user with the wordlist supplied
It can take a long time to queue 2 million requests, for that reason, we queue browser.max_threads, send browser.max_threads, queue browser.max_threads and so on.
hydra.run only returns when it has recieved all of its, responses. This means that while we are waiting for browser.max_threads, responses, we are waiting...
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
# File 'lib/common/models/wp_user/brute_forcable.rb', line 22 def brute_force(wordlist, = {}) browser = Browser.instance hydra = browser.hydra passwords = BruteForcable.passwords_from_wordlist(wordlist) queue_count = 0 found = false = self.(passwords.size, ) passwords.each do |password| request = login_request(password) request.on_complete do |response| .progress += 1 if [:show_progression] && !found puts "\n Trying Username : #{login} Password : #{password}" if [:verbose] if valid_password?(response, password, ) found = true self.password = password return end end hydra.queue(request) queue_count += 1 if queue_count >= browser.max_threads hydra.run queue_count = 0 puts "Sent #{browser.max_threads} requests ..." if [:verbose] end end # run all of the remaining requests hydra.run end |
- (Typhoeus::Request) login_request(password)
79 80 81 82 83 84 85 |
# File 'lib/common/models/wp_user/brute_forcable.rb', line 79 def login_request(password) Browser.instance.forge_request(login_url, method: :post, body: { log: login, pwd: password }, cache_ttl: 0 ) end |
- (ProgressBar) progress_bar(passwords_size, options)
:nocov:
64 65 66 67 68 69 70 71 72 73 |
# File 'lib/common/models/wp_user/brute_forcable.rb', line 64 def (passwords_size, ) if [:show_progression] ProgressBar.create( format: '%t %a <%B> (%c / %C) %P%% %e', title: " Brute Forcing '#{login}'", length: 120, total: passwords_size ) end end |
- (Boolean) valid_password?(response, password, options = {})
94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/common/models/wp_user/brute_forcable.rb', line 94 def valid_password?(response, password, = {}) if response.code == 302 progression = "#{green('[SUCCESS]')} Login : #{login} Password : #{password}\n\n" valid = true elsif response.body =~ /login_error/i verbose = "\n Incorrect login and/or password." elsif response.timed_out? progression = "#{red('ERROR:')} Request timed out." elsif response.code == 0 progression = "#{red('ERROR:')} No response from remote server. WAF/IPS?" elsif response.code.to_s =~ /^50/ progression = "#{red('ERROR:')} Server error, try reducing the number of threads." else progression = "#{red('ERROR:')} We received an unknown response for #{password}..." verbose = red(" Code: #{response.code}\n Body: #{response.body}\n") end puts "\n " + progression if progression && [:show_progression] puts verbose if verbose && [:verbose] valid || false end |