Path: blob/master/lib/metasploit/framework/login_scanner/kerberos.rb
28052 views
require 'metasploit/framework/login_scanner/base'12module Metasploit3module Framework4module LoginScanner56# Kerberos User scanner7class Kerberos8include Metasploit::Framework::LoginScanner::Base9include Msf::Exploit::Remote::Kerberos::Client1011DEFAULT_PORT = 8812REALM_KEY = Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN13DEFAULT_REALM = nil14LIKELY_PORTS = [ DEFAULT_PORT ].freeze15LIKELY_SERVICE_NAMES = [ 'kerberos', 'kerberos5', 'krb5', 'kerberos-sec' ].freeze16PRIVATE_TYPES = %i[ password ].freeze17CAN_GET_SESSION = true1819def attempt_login(credential)20result_options = {21credential: credential,22host: host,23port: port,24protocol: 'tcp',25service_name: 'kerberos'26}2728begin29res = send_request_tgt(30server_name: server_name,31client_name: credential.public,32password: credential.private,33realm: credential.realm34)35unless res.preauth_required36# Pre-auth not required - let's get an RC4-HMAC ticket, since it's more easily crackable37begin38res = send_request_tgt(39server_name: server_name,40client_name: credential.public,41password: credential.private,42realm: credential.realm,43offered_etypes: [Rex::Proto::Kerberos::Crypto::Encryption::RC4_HMAC]44)45rescue Rex::Proto::Kerberos::Model::Error::KerberosEncryptionNotSupported => e46# RC4 likely disabled - let's just use the initial response47end48end4950result_options = result_options.merge(51{52status: Metasploit::Model::Login::Status::SUCCESSFUL,53proof: res54}55)56return Metasploit::Framework::LoginScanner::Result.new(result_options)57rescue ::EOFError => e58result_options = result_options.merge({ status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e })59return Metasploit::Framework::LoginScanner::Result.new(result_options)60rescue Rex::Proto::Kerberos::Model::Error::KerberosError => e61status = self.class.login_status_for_kerberos_error(e)62result_options = result_options.merge({ status: status, proof: e })63return Metasploit::Framework::LoginScanner::Result.new(result_options)64end65end6667attr_accessor :server_name6869# Override the kerberos client's methods with the login scanner implementations70alias rhost host71alias rport port72alias timeout connection_timeout7374# @param [Rex::Proto::Kerberos::Model::Error::KerberosError] krb_err The kerberos error75def self.login_status_for_kerberos_error(krb_err)76error_code = krb_err.error_code77case error_code78when Rex::Proto::Kerberos::Model::Error::ErrorCodes::KDC_ERR_KEY_EXPIRED, Rex::Proto::Kerberos::Model::Error::ErrorCodes::KRB_AP_ERR_SKEW79# Correct password, but either password needs resetting or clock is skewed80begin81pa_data_entry = krb_err.res.e_data_as_pa_data.find do |pa_data|82pa_data.type == Rex::Proto::Kerberos::Model::PreAuthType::PA_PW_SALT83end8485if pa_data_entry86pw_salt = pa_data_entry.decoded_value87if pw_salt.nt_status88case pw_salt.nt_status.value89when ::WindowsError::NTStatus::STATUS_PASSWORD_EXPIRED90# Windows Server 2019 Build 17763 (possibly others) replies with STATUS_PASSWORD_EXPIRED even when the password is incorrect91Metasploit::Model::Login::Status::INCORRECT92else93Metasploit::Model::Login::Status::SUCCESSFUL94end95else96Metasploit::Model::Login::Status::SUCCESSFUL97end98else99Metasploit::Model::Login::Status::SUCCESSFUL100end101rescue Rex::Proto::Kerberos::Model::Error::KerberosDecodingError102Metasploit::Model::Login::Status::SUCCESSFUL103end104when Rex::Proto::Kerberos::Model::Error::ErrorCodes::KDC_ERR_C_PRINCIPAL_UNKNOWN105# The username doesn't exist106Metasploit::Model::Login::Status::INVALID_PUBLIC_PART107when Rex::Proto::Kerberos::Model::Error::ErrorCodes::KDC_ERR_CLIENT_REVOKED108# Locked out, disabled or expired109# It doesn't appear to be documented anywhere, but Microsoft gives us a bit110# of extra information in the e-data section111begin112pa_data_entry = krb_err.res.e_data_as_pa_data.find do |pa_data|113pa_data.type == Rex::Proto::Kerberos::Model::PreAuthType::PA_PW_SALT114end115116if pa_data_entry117pw_salt = pa_data_entry.decoded_value118if pw_salt.nt_status119case pw_salt.nt_status.value120when ::WindowsError::NTStatus::STATUS_ACCOUNT_LOCKED_OUT121Metasploit::Model::Login::Status::LOCKED_OUT122when ::WindowsError::NTStatus::STATUS_ACCOUNT_DISABLED123Metasploit::Model::Login::Status::DISABLED124when ::WindowsError::NTStatus::STATUS_ACCOUNT_EXPIRED125# Actually expired, which is effectively Disabled126Metasploit::Model::Login::Status::DISABLED127else128# Unknown - maintain existing behaviour129Metasploit::Model::Login::Status::DISABLED130end131else132Metasploit::Model::Login::Status::DISABLED133end134else135Metasploit::Model::Login::Status::DISABLED136end137rescue Rex::Proto::Kerberos::Model::Error::KerberosDecodingError138# Could be a non-MS implementation?139Metasploit::Model::Login::Status::DISABLED140end141else142Metasploit::Model::Login::Status::INCORRECT143end144end145146private147148def set_sane_defaults149self.connection_timeout = 10 if self.connection_timeout.nil?150self.port = DEFAULT_PORT unless self.port151end152153def print_status(*args)154framework_module.print_status(*args) if framework_module155end156157def print_good(*args)158framework_module.print_good(*args) if framework_module159end160161def vprint_status(*args)162framework_module.vprint_status(*args) if framework_module163end164end165end166end167end168169170