Thursday, October 19, 2006 10:01 PM
IIS and Kerberos. Part 1 - What is Kerberos and how does it work?
Edit: I've created a list of all the parts in this series here, which will be updated as I add more parts.
Configuring Kerberos and Delegation is one of the more common problems I see in the communities and even within Avanade. Since Kerberos isn't a simple topic, I'm going to write a quick series explaining how Kerberos works, common scenarios and problems and some troubleshooting tips.
Kerberos is an open authentication protocol developed at MIT, and implemented in Windows 2000/2003 Active Directory domains (amongst other places). Authentication is the process of proving your identity to a remote system. Your identity is who you are, and authentication is the process of proving that. In many systems your identity is your username, and you use a secret shared between you and the remote system (a password) to prove that your identity.
The problem with simplistic shared secret systems is two-fold:
a) there is a scalability problem. If every user needs to maintain a shared secret with every individual server (or every service on every server!) then that results in poor passwords. Users can not be expected to remember dozens, hundreds or thousands of unique passwords and so end up repeating them regardless of whether the server is a low security or high security resource
b) there is an issue in securely transmitting the shared secret from the user to the server. Various technologies (like TLS/SSL) exist for securing the transport of data between machines, however it is incumbent upon each service to utilise services lower down in the network stack.
Kerberos is designed to overcome these limitations. In this part we look at how a simple Kerberos implementation works. In this scenario we have a user using a client machine that wishes to connect to a remote service (the user here is a person or application, the client is the OS or machine). Remember that we want a system that allows us to store shared secrets centrally, and to securely transmit user credentials between client and service. Lastly we should look to prevent replay attacks (where someone who is sniffing the wire can replay captured packets to impersonate a legitimate user, even if they do not know how to create the authentication packets themselves).
To begin with we introduce the Kerberos KDC - Key Distribution Centre. In the Windows Active Directory world, the KDC lives on Domain Controllers (DCs). The client connects to the Authorisation Service (AS) that runs on the KDC and asks the AS to authenticate the user to the remote service. Technically, the client doesn't need to authenticate itself to the Domain Controller. However in the Active Directory world, something called pre-authentication is used to ensure that the user (or client application) is actually who they say they are.
The AS on the KDC generates a session key that will be used by the client and the remote service. It encrypts the session key with the user's password (this is why the user doesn't need to authenticate - if the user isn't who they say they are, they won't be able to decrypt the session key because they don't know the user's password). The KDC also prepares a second piece of data - it again encrypts the session key as well as the user's username (known as a Kerberos principal), but using the service's password this time to encrypt the data. Only the remote service will be able to decrypt this second piece of data. This second piece of data is known as the Service Ticket (or just Ticket).
The KDC now sends both pieces of data back to the client. The user, knowing their own password, is able to decrypt the first piece of data, and extract the session key. The user however does not know the service's password, so is unable to decrypt the second piece of data. The client uses the session key to encrypt the current time (amongst other things, but they aren't so important right now). This piece of data is known as the Authenticator. The client sends the Authenticator it just generated, along with the Service Ticket received from the KDC to the remote service.
The remote service is able to decrypt the Service Ticket using its own password. It is thus able to get access to the session key, and the Principal (user) attempting to connect. It now uses the session key to decrypt the Authenticator, and extract the time. It compares the time to the current system time on the server to ensure a match. Since only the service, the KDC and the user, know the session key then the service can assume that user must be who they say they are.
If an imposter sent a Service Ticket to the service (e.g. by replaying captured packets) they wouldn't know the correct session key necessary to encrypt the timestamp correctly. Alternatively, if the imposter attempts to use captured Authenticator packets (which contain a timestamp), thus bypassing the need to know the session key, then the times will not match when the Authenticator is decrypted by the service and the service will refuse to authenticate the remote user.
If this was the extent of the Kerberos, then each and every time the client received an encrypted session key from the KDC, the user would need to enter their password to allow the client machine access to it. That could rapidly become a productivity sinkhole (imagine having to enter your password for each and every HTTP request you made!). To get around this, the client machine could cache the user's password, but that isn't a particulary secure system. What Kerberos does is introduce the concept of a Ticket Granting Ticket (TGT).
Ticket Granting Tickets are issued by the AS running on the KDC in the same way that a normal service ticket is issued. However the TGT is valid for the Ticket Granting Service, rather than a remote HTTP server (or any other type of server). Whenever the user wishes to connect to a remote service, it can use the TGT that it has already received to connect to the TGS. The TGS, after authenticating the user via the TGT, issues a Service Ticket to the remote service. However instead of encrypting anything using the user's password, it encrypts using the session key originally generated by the AS. Since the client machine aleady knows this from when the TGT was received in the first place, there is no need to bother the user for their password. The TGT typically has a short lifespan - around 8 hours or so.