Issues with Active Directory <-> MIT x-realm key replacement
srinivas.cheruku at gmail.com
Wed Dec 8 23:25:46 EST 2010
What about a case when MIT client trying to access the AD services after the cross-realm keys are changed? For e.g. the MIT client would have service ticket krbtgt/AD at MIT encrypted with the older key and this ticket when presented to AD will not be able to decrypt this ticket as I believe AD doesn't store old cross-realm passwords. Do you have any way to mitigate this, other than MIT users destroying the cache or waiting for the cross-realm ticket to expire?
From: krbdev-bounces at MIT.EDU [mailto:krbdev-bounces at MIT.EDU] On Behalf Of Jeffrey Altman
Sent: Thursday, December 09, 2010 3:47 AM
To: 'krbdev at mit.edu'
Subject: Issues with Active Directory <-> MIT x-realm key replacement
I am sure that I am not the first to discover that implementing a key replacement strategy for Active Directory <-> MIT cross-realm keys is impossible to do with current code without causing an outage for clients with cached cross-realm service tickets. This is due to the fact that Active Directory issues krbtgt/MIT at AD service tickets with the kvno set to zero. As a result, the MIT KDC when presented with a service ticket issued before the key replacement will attempt to decrypt it with kvno "maxkvno" instead of "maxkvno - 1".
The code path of consequence is that krb5_rd_req_decrypt_tkt_part() calls krb5_kt_get_entry() with kvno == 0 which returns the entry for maxkvno which is then passed to krb5_decrypt_tkt_part() which will return KRB5KRB_AP_ERR_BAD_INTEGRITY since the key entry will not match the key used to encrypt req->ticket.
As a side effect clients that have cached krbtgt/MIT at AD service tickets will either need to have the cache destroyed or wait until the tickets expire. The default AD GPO policy is for a 10 hour lifetime with 7 day renewal. There is no mechanism in AD to mitigate this outage by setting a shorter lifetime (say 10 minutes) for just the krbtgt/MIT at AD service principal at least max lifetime minutes before the key replacement.
I wrote code to permit the MIT KDC to retry using the "maxkvno - 1" key when krb5_decrypt_tkt_part() returns KRB5KRB_AP_ERR_BAD_INTEGRITY IFF the krb5_princ_name(service) == "krbtgt", the requested kvno is zero, and maxkvno > 1. However, this leaves a security vulnerability in that it requires the key to be replaced twice at least max lifetime minutes apart in order to ensure that a compromised or weaker key is no longer usable.
I can reduce the window of vulnerability if the
krb5_dbe_lookup_last_pwd_change() returned timestamp is compared to the decrypted req->ticket issue time and only permit the "maxkvno - 1" key to be acceptable if the ticket was issued during the max lifetime period prior to the last_pwd_change time. I believe this criteria should be sufficient to make this an acceptable default behavior for a KDC. Do other members of the MIT Kerberos development community concur?
More information about the krbdev