Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/metasploit/framework/login_scanner/kerberos.rb
19612 views
1
require 'metasploit/framework/login_scanner/base'
2
3
module Metasploit
4
module Framework
5
module LoginScanner
6
7
# Kerberos User scanner
8
class Kerberos
9
include Metasploit::Framework::LoginScanner::Base
10
include Msf::Exploit::Remote::Kerberos::Client
11
12
DEFAULT_PORT = 88
13
REALM_KEY = Metasploit::Model::Realm::Key::ACTIVE_DIRECTORY_DOMAIN
14
DEFAULT_REALM = nil
15
LIKELY_PORTS = [ DEFAULT_PORT ].freeze
16
LIKELY_SERVICE_NAMES = [ 'kerberos', 'kerberos5', 'krb5', 'kerberos-sec' ].freeze
17
PRIVATE_TYPES = %i[ password ].freeze
18
CAN_GET_SESSION = true
19
20
def attempt_login(credential)
21
result_options = {
22
credential: credential,
23
host: host,
24
port: port,
25
protocol: 'tcp',
26
service_name: 'kerberos'
27
}
28
29
begin
30
res = send_request_tgt(
31
server_name: server_name,
32
client_name: credential.public,
33
password: credential.private,
34
realm: credential.realm
35
)
36
unless res.preauth_required
37
# Pre-auth not required - let's get an RC4-HMAC ticket, since it's more easily crackable
38
begin
39
res = send_request_tgt(
40
server_name: server_name,
41
client_name: credential.public,
42
password: credential.private,
43
realm: credential.realm,
44
offered_etypes: [Rex::Proto::Kerberos::Crypto::Encryption::RC4_HMAC]
45
)
46
rescue Rex::Proto::Kerberos::Model::Error::KerberosEncryptionNotSupported => e
47
# RC4 likely disabled - let's just use the initial response
48
end
49
end
50
51
result_options = result_options.merge(
52
{
53
status: Metasploit::Model::Login::Status::SUCCESSFUL,
54
proof: res
55
}
56
)
57
return Metasploit::Framework::LoginScanner::Result.new(result_options)
58
rescue ::EOFError => e
59
result_options = result_options.merge({ status: Metasploit::Model::Login::Status::UNABLE_TO_CONNECT, proof: e })
60
return Metasploit::Framework::LoginScanner::Result.new(result_options)
61
rescue Rex::Proto::Kerberos::Model::Error::KerberosError => e
62
status = self.class.login_status_for_kerberos_error(e)
63
result_options = result_options.merge({ status: status, proof: e })
64
return Metasploit::Framework::LoginScanner::Result.new(result_options)
65
end
66
end
67
68
attr_accessor :server_name
69
70
# Override the kerberos client's methods with the login scanner implementations
71
alias rhost host
72
alias rport port
73
alias timeout connection_timeout
74
75
# @param [Rex::Proto::Kerberos::Model::Error::KerberosError] krb_err The kerberos error
76
def self.login_status_for_kerberos_error(krb_err)
77
error_code = krb_err.error_code
78
case error_code
79
when Rex::Proto::Kerberos::Model::Error::ErrorCodes::KDC_ERR_KEY_EXPIRED, Rex::Proto::Kerberos::Model::Error::ErrorCodes::KRB_AP_ERR_SKEW
80
# Correct password, but either password needs resetting or clock is skewed
81
Metasploit::Model::Login::Status::SUCCESSFUL
82
when Rex::Proto::Kerberos::Model::Error::ErrorCodes::KDC_ERR_C_PRINCIPAL_UNKNOWN
83
# The username doesn't exist
84
Metasploit::Model::Login::Status::INVALID_PUBLIC_PART
85
when Rex::Proto::Kerberos::Model::Error::ErrorCodes::KDC_ERR_CLIENT_REVOKED
86
# Locked out, disabled or expired
87
# It doesn't appear to be documented anywhere, but Microsoft gives us a bit
88
# of extra information in the e-data section
89
begin
90
pa_data_entry = krb_err.res.e_data_as_pa_data.find do |pa_data|
91
pa_data.type == Rex::Proto::Kerberos::Model::PreAuthType::PA_PW_SALT
92
end
93
94
if pa_data_entry
95
pw_salt = pa_data_entry.decoded_value
96
if pw_salt.nt_status
97
case pw_salt.nt_status.value
98
when ::WindowsError::NTStatus::STATUS_ACCOUNT_LOCKED_OUT
99
Metasploit::Model::Login::Status::LOCKED_OUT
100
when ::WindowsError::NTStatus::STATUS_ACCOUNT_DISABLED
101
Metasploit::Model::Login::Status::DISABLED
102
when ::WindowsError::NTStatus::STATUS_ACCOUNT_EXPIRED
103
# Actually expired, which is effectively Disabled
104
Metasploit::Model::Login::Status::DISABLED
105
else
106
# Unknown - maintain existing behaviour
107
Metasploit::Model::Login::Status::DISABLED
108
end
109
else
110
Metasploit::Model::Login::Status::DISABLED
111
end
112
else
113
Metasploit::Model::Login::Status::DISABLED
114
end
115
rescue Rex::Proto::Kerberos::Model::Error::KerberosDecodingError
116
# Could be a non-MS implementation?
117
Metasploit::Model::Login::Status::DISABLED
118
end
119
else
120
Metasploit::Model::Login::Status::INCORRECT
121
end
122
end
123
124
private
125
126
def set_sane_defaults
127
self.connection_timeout = 10 if self.connection_timeout.nil?
128
self.port = DEFAULT_PORT unless self.port
129
end
130
131
def print_status(*args)
132
framework_module.print_status(*args) if framework_module
133
end
134
135
def print_good(*args)
136
framework_module.print_good(*args) if framework_module
137
end
138
139
def vprint_status(*args)
140
framework_module.vprint_status(*args) if framework_module
141
end
142
end
143
end
144
end
145
end
146
147