mardi 15 novembre 2016

Understanding kerberos

Kerberos allow different nodes of a network to authenticate to each other even if this network is not secure. Not secure means that eavesdroppers are listening on the network and may catch your data to fake your identity.

I didn't find easy to understand this protocol and why it was designed in such way, so I decided to build my own tutorial.

My main source of inspiration was this two links : microsoft technet  and the RFC 

Let's start with two nodes that want to authenticate to each-over.

A naive solution would be sharing a secret password
A emit an authent request to B accompagnied with password that A and B share. 
B check the password and authenticate A. 

The problem is eavesdroppers. They're listening on the network, if they catch the password they can build the authent request for them and fake the identity.

 
Is there a solution to this problem ? The answer is yes : Symetric Encryption ! Symetric encryption is the process of encoding messages with a key (a sequence of bytes) in such a way that you can only decode it if you also have this key.

 A and B share the same secret key that they never send in clear over the network. Let's call this key Kab.  

We could build the message to authenticate this way : Authent Request + A + Encypt(Kab, Timestamp)



When B receive an authent request from A he uses the key Kab to decode the timestamp, if  he finds a valid timestamp he authenticates A. The timestamp is used to prevent an eavedropper to just resend the whole packet to B, because B will accept the authent request only if the timestamp is recent enough. We could even imagine that B will never accept twice the same timestamp from A.

With this process an eavedropper is unable to build a valid authent request.

Mutual authentication is even feasible with B resending the timestamp sent previously by A.

But it could be a problem because the eavedropper have now the timestamp and its encrypted version so it can start to search a key by brute forcing. Thus some random data are added before encryption.

B was able to split timestamp and random data, it's a proof for A that B has also the key Kab.

How this solution scale ? 

But this solution does not scale well. Each node have to share a key for each relation. For instance in a network with A, B, C, and D the node A will need to maintain 4 keys Kab, Kac and Kad to manage all the authentications with the other nodes and the node B will have to maintain Kab, Kbc and Kbd, and so on for C and D. 


An other problem occur when you need to add or remove a node in the network. The new node has to notify all the other nodes in order to share with them a key, it may involve a lot of exchange between node that potentially will never need to communicate anyway. 

And what happen if one of them is inactive or unvailable, when the new node is arriving in the network, they'll have to synchronize lately ? 

The  kerberos protocol

To solve this problem the kerberos protocol propose a solution. Each node share its key with a special node called the KDC (Key Distribution center). All the node sharing a key with the KDC make a group called realm.


So what happen when A want to authenticate with D for instance ?



(1) A ask the KDC he wants to athenticate with D
(2) KDC return a message containing a Kad key (called session key) encrypted with the Ka key (called the long term key) so that only A can decrypt it. Along the message there's also the Kad, with the requester and a validity timstamp encrypted with Kd. A cannot decrypt this message as he doesn't know the Kd key. Thus he'll only be able to resend it. This part is called the kerberos ticket.
(3) A send its authent request, with the kerberos ticket and a timestamp encrypted wit Kad if A want mutual autehntication.
(4) D use its Kd key to find Kad, the requester (A) and the validity of the request. If the requester and the validity match then the authentication is accepted. Now A and D share the same Kad key. D may use it to decrypt the timestamp  and resent it to A for mutual authentication.

A big difference wih other protocols like NTLM for instance deserve to be noted here : D don't need to connect to the KDC. The authentication of A could be validated with the information provided by the client.

The ticket granting ticket (TGT)

Actually the nodes in the system are separated between two populations : 
  1. The services. The services is what's behind a server software like print server, web server, shared file system and so on. 
  2. The users. The users is usually human being constantly connecting and disconnecting the network.
For the services the easiest way to share the keys is to copy the key between the KDC and the service. As the services are numerically much fewer than users and  stay on the network all the time it's fine. Beside we control what's installed on the servers which is not the case with the users. 

For the users the key is derived from their password. Both the client and the KDC derived the key from the password.


  • When the logon succeed the kerberos client calculate a cryptographic key from the password. This key is the long term key and is put in a secure volatile cache storage. 
  • The KDC also calculate a cryptographic key from the password, the algorithm calculation is the same thus the key is the same on both side. 
  • Notice that no password is exchanged between the workstation and the KDC on the network.

But we have two security problems ... 
  • The key Ka is a long term key. Every time A request an authentication the key Ka must be used. Then it's "easy" for a virus, a malware, any user who use the A session to get this long term key and then get a long term ability to connect to any service on the network that A was able to connect
  • When A request a kerberos ticket for D to the KDC, we must implement a pre-authentication mechanism. Otherwhise anybody could submit a request in the name of A. It should be ok as the response is encrypted with A's key thus only usable by A. But things are not so simple because the response also contains plaintext field that can be used to optimise a brute force attack on the key. Especially when the key is derived from a user password.
The solution is to create a special kerberos ticket called TGT (Ticket Granting Ticket) after the client successfully authenticate to the KDC.

The TGT is the ticket the client use for the KDC. It last about 8 hours (a logon session) and contains a session key for the communication between the client and the KDC, thus not using anymore the long term key. The long term key is used only during the authentication and is dropped from the memory.

This lead us to split the KDC into 2 different component :

  1. The authentication System (AS) that give a TGT to the client (TGT is a special kind of kerberos ticket for the KDC itself). 
  2. The Ticket Granting Service that give a kerberos ticket to the client for authenticating to the sevice
The AS hold the keys of the users (derived from the password) while the TGS hold the keys of the services : 



Now we can make the big picture :


If you want now to practise I advice to follow this tutorial on manula blog where you create a user, a KDC and a service. It's the opportunity to make the relation between the component/action and the big picture.