The following sections display the decoded messages and describes the steps and difficulties in decrypting them. Since Kerberos armouring requires a Ticket Granting Ticket (TGT) for the device (Windows client), we start there. The data structures shown are defined in RFC 4120 (Kerberos V5) and RFC 6113 (Kerberos Preauth Framework).
AS-REQ for the device, no pre-authentication
There is no encrypted information in this message.
ERROR for the device, pre-authentication required
AS-REQ for the device, with pre-authentication
Decrypting the PA-ENC-TIMESTAMP EncryptedData gives, using the password of the device (or the appropriate key derived from the password (the aes256-cts-hmac-sha1-96 key, in this case)):
{
[0] { 03/03/2020 17:09:58 } -- patimestamp
[1] { 313892 } -- pausec
}
AS-REP for the device
Decrypting the final EncPart EncryptedData shown above using the password/key of the device gives:
[APPLICATION 25] { -- EncKDCRepPart
{
[0] { -- key
{ [0] { 18 }
[1] { 'mMcDNF8bhHlXF+ntZ7CosH1qNaUujc6WoCyGustqEG0=' } -- base64
}
}
[1] { -- last-req
{ { [0] { 0 }
[1] { 03/03/2020 17:09:58 }
} }
}
[2] { 716117998 } -- nonce
[3] { 14/09/2037 04:48:05 } -- key-expiration
[4] { 40-E1-00-00 } -- flags
[5] { 03/03/2020 17:09:58 } -- authtime
[6] { 03/03/2020 17:09:58 } -- starttime
[7] { 04/03/2020 03:09:58 } -- endtime
[8] { 10/03/2020 17:09:58 } -- renew-till
[9] { 'LEIMGRUBE.CH' } -- srealm
[10] { -- sname
{ [0] { 2 }
[1] { { 'krbtgt' 'LEIMGRUBE.CH' } }
}
}
[11] { -- caddr
{ { [0] { 20 }
[1] { 'EC2AMAZ-EHM3HUN ' }
} }
}
[12] { -- padata, RFC 6806
{ { [1] { 167 } -- PA-PAC-OPTIONS
[2] { byte[11] => { [0] { 80-00-00-00 } } } }
{ [1] { 165 } -- PA-SUPPORTED-ENCTYPES
[2] { 1F-00-05-00 }
} }
}
}
}
Decrypting the ticket EncPart EncryptedData shown above using the password/key of the krbtgt account gives:
[APPLICATION 3] { -- EncTicketPart
{
[0] { 40-E1-00-00 } -- flags
[1] { -- key
{ [0] { 18 }
[1] { 'mMcDNF8bhHlXF+ntZ7CosH1qNaUujc6WoCyGustqEG0=' } -- base64
}
}
[2] { 'LEIMGRUBE.CH' } -- crealm
[3] { -- cname
{ [0] { 1 }
[1] { { 'EC2AMAZ-EHM3HUN$' } }
}
}
[4] { -- transited
{ [0] { 0 }
[1] { }
}
}
[5] { 03/03/2020 17:09:58 } -- authtime
[6] { 03/03/2020 17:09:58 } -- starttime
[7] { 04/03/2020 03:09:58 } -- endtime
[8] { 10/03/2020 17:09:58 } -- renew-till
[10] { -- authorization-data
{ { [0] { 1 } -- AD-IF-RELEVANT
[1] { byte[862] => { { [0] { 128 } -- AD-WIN2K-PAC
[1] { byte[840] } } } } }
}
}
}
}
The same “key” value is present in both encrypted parts. This enables the “session” key to be shared between the krbtgt account and the device. This key will be needed to decrypt later Kerberos armouring.
The AD-WIN2K-PAC data is just serialized data (and not encoded ASN.1). Here is a formatted dump of its contents:
PAC Type LoginInformation:
LogonTime: 2020-03-03T16:06:52.9729666Z
LogoffTime: 0001-01-01T00:00:00.0000000
KickOffTime: 0001-01-01T00:00:00.0000000
PasswordLastSet: 2020-02-17T06:58:17.9280757Z
PasswordCanChange: 2020-02-18T06:58:17.9280757Z
PasswordMustChange: 0001-01-01T00:00:00.0000000
EffectiveName: EC2AMAZ-EHM3HUN$
FullName:
LogonScript:
ProfilePath:
HomeDirectory:
HomeDirectoryDrive:
LogonCount: 429
BadPasswordCount: 0
UserId: 1008
PrimaryGroupId: 516
GroupIds: 7 516
UserFlags: 0x20
UserSessionKey: 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
LogonServer: EC2AMAZ-EHM3HUN
LogonDomainName: LEIMGRUBE
LogonDomainId: S-1-5-21-1700842961-3107118889-547158845
UserAccountControl: 0x2100
SubAuthStatus: 0x0
LastSuccessfulILogon: 1601-01-01T00:00:00.0000000Z
LastFailedILogon: 1601-01-01T00:00:00.0000000Z
FailedILogonCount: 0x0
ExtraSids: 0x7 S-1-5-9
ExtraSids: 0x7 S-1-5-21-0-0-0-497
ExtraSids: 0x7 S-1-18-1
PAC Type ClientInformation: 00-8F-57-2F-76-F1-D5-01 EC2AMAZ-EHM3HUN$
PAC Type UpnDns: EC2AMAZ-EHM3HUN$@Leimgrube.ch LEIMGRUBE.CH
PAC Type ClientClaimsInformation: ()
PAC Type ServerChecksum: 10-00-00-00-B0-E5-EC-FF-0A-9A-B5-8F-CD-F9-FC-E1
PAC Type KdcChecksum: 10-00-00-00-52-C2-12-E0-7E-47-C3-61-22-2D-FD-0B
AS-REQ for the user, no pre-authentication
There are 3 EncryptedData elements in the AS-REQ, but we have decrypted and shown one already, namely the EncPart of the Ticket used for the armouring (the device TGT).
Decrypting the Authenticator of the armour value AP-REQ with the session key from the device TGT gives:
[APPLICATION 2] { -- Authenticator
{
[0] { 5 } -- authenticator-vno
[1] { 'LEIMGRUBE.CH' } -- crealm
[2] { -- cname
{ [0] { 1 }
[1] { { 'EC2AMAZ-EHM3HUN$' } }
}
}
[4] { 24660 } -- cusec
[5] { 03/03/2020 17:09:58 } -- ctime
[6] { -- subkey
{ [0] { 18 }
[1] { '2ft/oGqS50PtgmO0OK+3UH4KBwp4LtIUOuPS7JJ6ia8=' } -- base64
}
}
[7] { 0 } -- seq-number
}
}
Combining the subkey from above with the ticket session key, using the function KRB-FX-CF2 allows us to derive the armour key.
KRB-FX-CF2 is defined in RFC 6113 and it utilises the pseudo-random method of the encryption algorithm profile. Appendix A of RFC 6113 says “In performing interoperability testing, there was significant ambiguity surrounding [RFC3961] pseudo-random operations” and that was certainly my experience too.
aes256-cts-hmac-sha1-96 uses a simplified algorithm profile (defined in RFC 3962) and the pseudo-random method is defaulted from section 5.3 of RFC 3961. The default pseudo-random method uses the encryption function (E) of the simplified profile. Perhaps the first uncertainty is whether “encryption function” and “E” are synonymous; initially, I thought that they were, as when RFC 3961 section 5.2 refers to “encryption/decryption functions, E and D”. However section 5.3 seems to define “encryption function” in terms of “E” and other functions:
encryption function conf = Random string of length c
pad = Shortest string to bring confounder
and plaintext to a length that's a
multiple of m.
(C1, newIV) = E(Ke, conf | plaintext | pad,
oldstate.ivec)
H1 = HMAC(Ki, conf | plaintext | pad)
ciphertext = C1 | H1[1..h]
newstate.ivec = newIV
The biggest confusion for me was the “mode” of “E” (e.g. ECB/CBC/CTS). Even when I deduced/noticed that “No integrity checking or confounder should be included here”, I persisted with the idea that E was aes-cts and “m” (the message block size) was 1. The definition of “m” includes the statement “If a block cipher is used in a mode that can handle messages that are not multiples of the cipher block size, such as CBC mode with cipher text stealing (CTS, see [RC5]), this value would be one octet”.
Only the remark in Appendix A that “These test vectors assume that the AES pseudo-random operation is aes-ecb(trunc128(sha-1(input)))” finally made the requirements of an interoperable implementation of “pseudo-random” for aes256-cts-hmac-sha1-96 clear.
Decrypting the EncFastReq element with the armour key gives:
{ -- KrbFastReq
[0] { 00-00-00-00 } -- fast-options
[1] { -- padata
{ { [1] { 128 } -- PA-PAC-REQUEST
[2] { byte[7] => { [0] { True } } } }
{ [1] { 167 } -- PA-PAC-OPTIONS
[2] { byte[11] => { [0] { 80-00-00-00 } } } } }
}
[2] { -- req-body
{ [0] { 40-81-00-10 } -- kdc-options
[1] { -- cname
{ [0] { 1 }
[1] { { 'Administrator' } } }
}
[2] { 'LEIMGRUBE.CH' } -- realm
[3] { -- sname
{ [0] { 2 }
[1] { { 'krbtgt' 'LEIMGRUBE.CH' } } }
}
[5] { 13/09/2037 04:48:05 } -- till
[6] { 13/09/2037 04:48:05 } -- rtime
[7] { 716117995 } -- nonce
[8] { -- etype
{ 18 23 -133 -128 24 -135 }
}
[9] { -- addresses
{ { [0] { 20 }
[1] { 'EC2AMAZ-EHM3HUN ' } } } }
}
}
}
ERROR for the user, pre-authentication required
Decrypting the EncFastRep element with the armour key gives:
{ -- KrbFastResponse
[0] { -- padata
{ { [1] { 137 } -- PA-FX-ERROR
[2] { byte[96] => [APPLICATION 30] { -- KRB-ERROR
{ [0] { 5 } -- pvno
[1] { 30 } -- msg-type
[4] { 03/03/2020 17:09:58 } -- stime
[5] { 313892 } -- susec
[6] { 25 } -- error-code
[9] { 'LEIMGRUBE.CH' } -- realm
[10] { { [0] { 2 } [1] { { 'krbtgt' 'LEIMGRUBE.CH' } } } } -- sname
} } } }
{ [1] { 133 } -- PA-FX-COOKIE
[2] { 4D-69-63-72-6F-73-6F-66-74 } }
{ [1] { 19 } -- PA-ETYPE-INFO2
[2] { byte[60] => { { [0] { 18 } [1] { 'LEIMGRUBE.CHAdministrator' } }
{ [0] { 23 } }
{ [0] { -133 } }
{ [0] { -128 } } } } }
{ [1] { 138 } -- PA-ENCRYPTED-CHALLENGE
[2] { } }
{ [1] { 16 } -- PA-PK-AS-REP
[2] { } }
{ [1] { 15 } -- PA-PK-AS-REP_OLD
[2] { } }
}
}
[3] { 716117995 } -- nonce
}
AS-REQ for the user, with pre-authentication
[APPLICATION 2] { -- Authenticator
{
[0] { 5 } -- authenticator-vno
[1] { 'LEIMGRUBE.CH' } -- crealm
[2] { -- cname
{ [0] { 1 }
[1] { { 'EC2AMAZ-EHM3HUN$' } }
}
}
[4] { 24661 } -- cusec
[5] { 03/03/2020 17:09:58 } -- ctime
[6] { -- subkey
{ [0] { 18 }
[1] { 'FI0VJO9MmOPrTFeo3Qn8g19rzjNgiVTnFegDvcrP55E=' } -- base64
}
}
[7] { 0 } -- seq-number
}
}
Decrypting the EncFastReq element with the new armour key derived from the subkey above gives:
{ -- KrbFastReq
[0] { 00-00-00-00 } -- fast-options
[1] { -- padata
{ { [1] { 138 } -- PA-ENCRYPTED-CHALLENGE
[2] { byte[67] => { [0] { 18 } [2] { byte[56] } } } }
{ [1] { 128 } -- PA-PAC-REQUEST
[2] { byte[7] => { [0] { True } } } }
{ [1] { 167 } -- PA-PAC-OPTIONS
[2] { byte[11] => { [0] { 80-00-00-00 } } } } } }
[2] { -- req-body
{ [0] { 40-81-00-10 } -- kdc-options
[1] { -- cname
{ [0] { 1 }
[1] { { 'Administrator' } } }
}
[2] { 'LEIMGRUBE.CH' } -- realm
[3] { -- sname
{ [0] { 2 }
[1] { { 'krbtgt' 'LEIMGRUBE.CH' } } }
}
[5] { 13/09/2037 04:48:05 } -- till
[6] { 13/09/2037 04:48:05 } -- rtime
[7] { 716117988 } -- nonce
[8] { -- etype
{ 18 23 -133 -128 24 -135 }
}
[9] { -- addresses
{ { [0] { 20 }
[1] { 'EC2AMAZ-EHM3HUN ' } } } }
}
}
}
Decrypting the embedded PA-ENCRYPTED-CHALLENGE, using the client challenge armour key (derived from the client key and the armour key, using KRB-FX-CF2) gives:
{ [0] { 03/03/2020 17:09:58 } [1] { 313892 } }
AS-REP for the user
Decrypting the KrbFastArmoredRep EncryptedData using the armour key gives:
{ -- KrbFastResponse
[0] { -- padata
{ { [1] { 19 } -- PA-ETYPE-INFO2
[2] { byte[38] => { { [0] { 18 }
[1] { 'LEIMGRUBE.CHAdministrator' } } } } }
{ [1] { 138 } -- PA-ENCRYPTED-CHALLENGE
[2] { byte[67] => { [0] { 18 } [2] { byte[56] } } } } }
}
[1] { -- strengthen-key
{ [0] { 18 }
[1] { '4aNHiHJpxx293D5zLMVKqaFkkwsQt0gHXESecGd86YM=' } } -- base64
}
[2] { -- finished
{ -- KrbFastFinished
[0] { 03/03/2020 17:09:58 } -- timestamp
[1] { 313892 } -- usec
[2] { 'LEIMGRUBE.CH' } -- crealm
[3] { { [0] { 1 } [1] { { 'Administrator' } } } } -- cname
[4] { -- ticket-checksum
{ [0] { 16 } [1] { 98-66-FC-21-FD-21-21-80-81-76-07-C4 } }
}
}
}
[3] { 716117988 } -- nonce
}
Decrypting the embedded PA-ENCRYPTED-CHALLENGE, using the KDC challenge armour key (derived from the client key and the armour key, using KRB-FX-CF2) gives:
{ [0] { 03/03/2020 17:09:58 } [1] { 313892 } }
Decrypting the final EncPart EncryptedData shown above using the password/key of the user, strengthened with the strengthen-key in the KrbFastResponse gives:
[APPLICATION 25] { -- EncKDCRepPart
{
[0] { -- key
{ [0] { 18 }
[1] { 'lsJxd2LXykXBPBZ/jXRjCeJlfIsWanhSWIcs+eoGovk=' } -- base64
}
}
[1] { -- last-req
{ { [0] { 0 }
[1] { 03/03/2020 17:09:58 }
} }
}
[2] { 716117988 } -- nonce
[3] { 06/04/2020 23:04:57 } -- key-expiration
[4] { 40-E1-00-00 } -- flags
[5] { 03/03/2020 17:09:58 } -- authtime
[6] { 03/03/2020 17:09:58 } -- starttime
[7] { 04/03/2020 03:09:58 } -- endtime
[8] { 10/03/2020 17:09:58 } -- renew-till
[9] { 'LEIMGRUBE.CH' } -- srealm
[10] { -- sname
{ [0] { 2 } [1] { { 'krbtgt' 'LEIMGRUBE.CH' } } }
}
[11] { -- caddr
{ { [0] { 20 } [1] { 'EC2AMAZ-EHM3HUN ' } } } }
[12] { -- padata
{ { [1] { 167 } -- PA-PAC-OPTIONS
[2] { byte[11] => { [0] { 80-00-00-00 } } } }
{ [1] { 165 } -- PA-SUPPORTED-ENCTYPES
[2] { 1F-00-05-00 }
} }
}
}
}
Decrypting the Ticket EncPart EncryptedData shown above using the password/key of the host/admin account gives:
[APPLICATION 3] { -- EncTicketPart
{
[0] { 40-E1-00-00 } -- flags
[1] { -- key
{ [0] { 18 }
[1] { 'lsJxd2LXykXBPBZ/jXRjCeJlfIsWanhSWIcs+eoGovk=' } -- base64
}
}
[2] { 'LEIMGRUBE.CH' } -- crealm
[3] { { [0] { 1 } [1] { { 'Administrator' } } } } -- cname
[4] { { [0] { 0 } [1] { } } } -- transited
[5] { 03/03/2020 17:09:58 } -- authtime
[6] { 03/03/2020 17:09:58 } -- starttime
[7] { 04/03/2020 03:09:58 } -- endtime
[8] { 10/03/2020 17:09:58 } -- renew-till
[10] { -- authorization-data
{ { [0] { 1 } -- AD-IF-RELEVANT
[1] { byte[846] => { { [0] { 128 } -- AD-WIN2K-PAC
[1] { byte[824] } } } } }
} }
}
}
TGS-REQ
[APPLICATION 2] { -- Authenticator
{
[0] { 5 } -- authenticator-vno
[1] { 'LEIMGRUBE.CH' } -- crealm
[2] { { [0] { 1 } [1] { { 'Administrator' } } } } -- cname
[3] { -- cksum
{ [0] { 7 }
[1] { BB-FE-FC-99-91-8D-23-CD-F8-01-F6-56-18-E5-AF-2B }
}
}
[4] { 24662 } -- cusec
[5] { 03/03/2020 17:09:58 } -- ctime
[6] { -- subkey
{ [0] { 18 }
[1] { '7YGfZdDpOIgvAS6gx8CkUpwLdRlvp8M+gqz/4c0VKrY=' } -- base64
}
}
[7] { 716117985 } -- seq-number
}
}
Decrypting the EncFastReq element with the new armour key derived from the subkey above and the key from the PA-TGS-REQ ticket gives:
{ -- KrbFastReq
[0] { 00-00-00-00 } -- fast-options
[1] { -- padata
{ { [1] { 167 } -- PA-PAC-OPTIONS
[2] { byte[11] => { [0] { C0-00-00-00 } } } } } }
[2] { -- req-body
{ [0] { 40-81-00-00 } -- kdc-options
[2] { 'LEIMGRUBE.CH' } -- realm
[3] { { [0] { 2 } [1] { { 'host' 'admin' } } } } -- sname
[5] { 13/09/2037 04:48:05 } -- till
[7] { 716117985 } -- nonce
[8] { { 18 17 } } -- etype
[10] { { [0] { 18 } [2] { byte[136] } } } -- enc-authorization-data
}
}
}
The two EncAuthorizationData elements (in the outer ReqBody and the KrbFastReq req-body) are identical. Decrypting with the subkey gives:
{
{ [0] { 1 } -- AD-IF-RELEVANT
[1] { byte[95] =>
{ { [0] { 141 } -- KERB_AUTH_DATA_TOKEN_RESTRICTIONS
[1] { byte[53] => { { [0] { 0 } [1] { byte[40] } } } } }
{ [0] { 142 } -- KERB-LOCAL
[1] { D0-23-FE-DF-21-02-00-00-30-93-AD-23-00-00-00-00 } } } } }
}
TGS-REP
Decrypting the KrbFastArmoredRep EncryptedData using the armour key gives:
{ -- KrbFastResponse
[0] { -- padata
{ }
}
[1] { -- strengthen-key
{ [0] { 18 }
[1] { 'cNisWraV1QLW4/WuGrbZTArNS/Yx0VY9FhDI5ohbcRU=' } } -- base64
}
[2] { -- finished
{ -- KrbFastFinished
[0] { 03/03/2020 17:09:58 } -- timestamp
[1] { 313892 } -- usec
[2] { 'LEIMGRUBE.CH' } -- crealm
[3] { { [0] { 1 } [1] { { 'Administrator' } } } } -- cname
[4] { -- ticket-checksum
{ [0] { 16 } [1] { 21-1F-C3-BC-95-02-B7-6D-D5-3E-8D-01 } }
}
}
}
[3] { 716117985 } -- nonce
}
Decrypting the Ticket EncPart EncryptedData shown above using the password/key of the host/admin account gives:
[APPLICATION 3] { -- EncTicketPart
{
[0] { 40-A1-00-00 } -- flags
[1] { -- key
{ [0] { 18 }
[1] { 'mvIE6JfoLACcnJcq+ZDazBstli4/ywWyeJfsKGiuQV0=' } -- base64
}
}
[2] { 'LEIMGRUBE.CH' } -- crealm
[3] { { [0] { 1 } [1] { { 'Administrator' } } } } -- cname
[4] { { [0] { 0 } [1] { } } } -- transited
[5] { 03/03/2020 17:09:58 } -- authtime
[6] { 03/03/2020 17:09:58 } -- starttime
[7] { 04/03/2020 03:09:58 } -- endtime
[8] { 10/03/2020 17:09:58 } -- renew-till
[10] { -- authorization-data
{
{ [0] { 1 } -- AD-IF-RELEVANT
[1] { byte[846] =>
{ { [0] { 128 } -- AD-WIN2K-PAC
[1] { byte[824] } } } } }
}
{ [0] { 1 } -- AD-IF-RELEVANT
[1] { byte[95] =>
{ { [0] { 141 } -- KERB_AUTH_DATA_TOKEN_RESTRICTIONS
[1] { byte[53] => { { [0] { 0 } [1] { byte[40] } } } } }
{ [0] { 142 } -- KERB-LOCAL
[1] { D0-23-FE-DF-21-02-00-00-30-93-AD-23-00-00-00-00 } } } } }
}
}
}
}
Decrypting the final EncPart EncryptedData shown above using the subkey from the Authenticator in the TGS-REQ, strengthened with the strengthen-key in the KrbFastResponse gives:
[APPLICATION 26] { -- EncTGSRepPart
{
[0] { -- key
{ [0] { 18 }
[1] { 'mvIE6JfoLACcnJcq+ZDazBstli4/ywWyeJfsKGiuQV0=' } -- base64
}
}
[1] { { { [0] { 0 } [1] { 03/03/2020 17:09:58 } } } } -- last-req
[2] { 716117985 } -- nonce
[4] { 40-A1-00-00 } -- flags
[5] { 03/03/2020 17:09:58 } -- authtime
[6] { 03/03/2020 17:09:58 } -- starttime
[7] { 04/03/2020 03:09:58 } -- endtime
[8] { 10/03/2020 17:09:58 } -- renew-till
[9] { 'LEIMGRUBE.CH' } -- srealm
[10] { { [0] { 2 } [1] { { 'host' 'admin' } } } } -- sname
[12] { -- padata
{ { [1] { 165 } -- PA-SUPPORTED-ENCTYPES
[2] { 1F-00-00-00 } }
{ [1] { 167 } -- PA-PAC-OPTIONS
[2] { byte[11] => { [0] { C0-00-00-00 } } }
} }
}
}
}
Summary
I have nothing “profound” to say by way of summary, but I thought a distinct “end-marker” was needed after the last decrypted Kerberos message.
The most interesting part of the encrypted data is possibly the authorization data; if one can obtain a handle to a Windows token created as a result of Kerberos authentication then much of the information can be obtained via the GetTokenInformation and LsaGetLogonSessionData routines.
No comments:
Post a Comment