|
| 1 | +require 'metasploit/framework/login_scanner/base' |
| 2 | +require 'metasploit/framework/login_scanner/rex_socket' |
| 3 | +require 'metasploit/framework/tcp/client' |
| 4 | + |
| 5 | +module Metasploit |
| 6 | + module Framework |
| 7 | + module LoginScanner |
| 8 | + |
| 9 | + # This is the LoginScanner class for dealing with vmware-auth. |
| 10 | + # It is responsible for taking a single target, and a list of credentials |
| 11 | + # and attempting them. It then saves the results. |
| 12 | + class VMAUTHD |
| 13 | + include Metasploit::Framework::LoginScanner::Base |
| 14 | + include Metasploit::Framework::LoginScanner::RexSocket |
| 15 | + include Metasploit::Framework::Tcp::Client |
| 16 | + |
| 17 | + DEFAULT_PORT = 902 |
| 18 | + LIKELY_PORTS = [ DEFAULT_PORT, 903, 912 ] |
| 19 | + LIKELY_SERVICE_NAMES = [ 'vmauthd', 'vmware-auth' ] |
| 20 | + PRIVATE_TYPES = [ :password ] |
| 21 | + REALM_KEY = nil |
| 22 | + |
| 23 | + # This method attempts a single login with a single credential against the target |
| 24 | + # @param credential [Credential] The credential object to attempt to login with |
| 25 | + # @return [Metasploit::Framework::LoginScanner::Result] The LoginScanner Result object |
| 26 | + def attempt_login(credential) |
| 27 | + result_options = { |
| 28 | + credential: credential, |
| 29 | + status: Metasploit::Model::Login::Status::INCORRECT, |
| 30 | + proof: nil, |
| 31 | + host: host, |
| 32 | + port: port, |
| 33 | + service_name: 'vmauthd', |
| 34 | + protocol: 'tcp' |
| 35 | + } |
| 36 | + |
| 37 | + disconnect if self.sock |
| 38 | + |
| 39 | + begin |
| 40 | + connect |
| 41 | + select([sock], nil, nil, 0.4) |
| 42 | + |
| 43 | + # Check to see if we received an OK? |
| 44 | + result_options[:proof] = sock.get_once |
| 45 | + if result_options[:proof] && result_options[:proof][/^220 VMware Authentication Daemon Version.*/] |
| 46 | + # Switch to SSL if required |
| 47 | + swap_sock_plain_to_ssl(sock) if result_options[:proof] && result_options[:proof][/SSL/] |
| 48 | + |
| 49 | + # If we received an OK we should send the USER |
| 50 | + sock.put("USER #{credential.public}\r\n") |
| 51 | + result_options[:proof] = sock.get_once |
| 52 | + |
| 53 | + if result_options[:proof] && result_options[:proof][/^331.*/] |
| 54 | + # If we got an OK after the username we can send the PASS |
| 55 | + sock.put("PASS #{credential.private}\r\n") |
| 56 | + result_options[:proof] = sock.get_once |
| 57 | + |
| 58 | + if result_options[:proof] && result_options[:proof][/^230.*/] |
| 59 | + # if the pass gives an OK, we're good to go |
| 60 | + result_options[:status] = Metasploit::Model::Login::Status::SUCCESSFUL |
| 61 | + end |
| 62 | + end |
| 63 | + end |
| 64 | + |
| 65 | + rescue Rex::ConnectionError, EOFError, Timeout::Error, Errno::EPIPE => e |
| 66 | + result_options.merge!( |
| 67 | + proof: e.message, |
| 68 | + status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT |
| 69 | + ) |
| 70 | + end |
| 71 | + |
| 72 | + disconnect if self.sock |
| 73 | + |
| 74 | + Result.new(result_options) |
| 75 | + end |
| 76 | + |
| 77 | + private |
| 78 | + |
| 79 | + # (see Base#set_sane_defaults) |
| 80 | + def set_sane_defaults |
| 81 | + self.connection_timeout ||= 30 |
| 82 | + self.port ||= DEFAULT_PORT |
| 83 | + self.max_send_size ||= 0 |
| 84 | + self.send_delay ||= 0 |
| 85 | + end |
| 86 | + |
| 87 | + def swap_sock_plain_to_ssl(nsock=self.sock) |
| 88 | + ctx = generate_ssl_context |
| 89 | + ssl = OpenSSL::SSL::SSLSocket.new(nsock, ctx) |
| 90 | + |
| 91 | + ssl.connect |
| 92 | + |
| 93 | + nsock.extend(Rex::Socket::SslTcp) |
| 94 | + nsock.sslsock = ssl |
| 95 | + nsock.sslctx = ctx |
| 96 | + end |
| 97 | + |
| 98 | + def generate_ssl_context |
| 99 | + ctx = OpenSSL::SSL::SSLContext.new(:SSLv3) |
| 100 | + @@cached_rsa_key ||= OpenSSL::PKey::RSA.new(1024){} |
| 101 | + |
| 102 | + ctx.key = @@cached_rsa_key |
| 103 | + |
| 104 | + ctx.session_id_context = Rex::Text.rand_text(16) |
| 105 | + |
| 106 | + ctx |
| 107 | + end |
| 108 | + end |
| 109 | + |
| 110 | + end |
| 111 | + end |
| 112 | +end |
0 commit comments