Using SSH Public Keys and Unmodified Clients to Securely Acquire Kerberos Tickets

After reading the RFCs a bit, I think this can be done securely without modifying the ssh client (which would defeat the purpose). However, changes to both the sshd and KDC are necessary. And those changes will require a lot of work – this is not a weekend hack.

Understanding SSH Public Key Authentication

SSH2 (RFC4251) authentication (RFC4252) works like this: the SSH “transport” (RFC4253) calls for a pluggable “key exchange” protocol to establish a shared secret between the client and server. Essentially all of these protocols involve the server proving its identity to the client, the client and server each generating some randomness, and the establishment of some shared secret based on the combined randomness. At some point along the way the server signs this secret or the randomness with its host key to prove its identity to the client.

As part of the process of generating the shared secret, a “session identifier” is generated based in part on the randomness mentioned above. The client signs the session identifier using the private key, and the server verifies the signature.

So, to review, there are three steps. Steps 2+3 are both considered part of the “key exchange” protocol, of which there are many. Step 4 is the “public key authentication”.

  1. Client and server both generate randomness.

  2. Client and server establish a shared secret and session identifier (which is derived from the shared secret).

  3. Server proves identity to client.

  4. Client signs session identifier to prove identity to server.

An important aspect of this protocol is that the client and server both contribute randomness. The fact that this randomness is unique for every connection is absolutely essential to preventing replay attacks.

The hard parts of using SSH Public Keys to acquire Kerberos TGTs without modifying the ssh client are:

  1. The KDC must not trust the machine running sshd to protect against replay attacks. Replay protection must happen at the KDC. This ensures that a compromised sshd host cannot continue to acquire Kerberos tickets after the client has disconnected, so the new scheme presents no additional security risks beyond the usual unavoidable ticket-theft resulting from a compromised host.

  2. The scheme must be easily adaptable to the wide variety of key-exchange mechanisms floating around out there. In other words, it should not rely on any feature of the key exchange protocol other than the fact that it takes randomness as input in order to prevent replays.

Basic Scheme

The KDC is extended to offer two new services:

  1. The KDC will, upon request, generate a random number and a timestamp and sign this combination, asserting “I, the KDC, generated this random number at this time”. Only the KDC need be able to verify this signature. This can be a public service and need not be an authenticated connection; no secrecy is required, and any modification by a man-in-the-middle will invalidate the signature.

  2. The KDC will, upon a request authenticated by principal host/XXXX@REALM, issue a TGT for a user in exchange for the following data:

    • An SSH key exchange algorithm identifier indicating which key exchange algorithm was used.

    • A signed randomness-timestamp combination mentioned above, with a timestamp not more than a few minutes old.

    • A listing of all data which was hashed in order to produce the (secret) SSH session identifier. The KDC must verify that the signed randomness from the previous point is the same randomness used here.

    • The result of signing the hashed data with the user's public key.

Note that the last two values should be handled only by the client, sshd host, and KDC; therefore the request from the sshd host to the KDC must be encrypted. Likewise, the reply from the KDC contains a TGT, so it too must be encrypted. Fortunately, the request and reply are coming from a host/XXXX@REALM principal, so a trust anchor is present.

Clearly the KDC must have access to the user's SSH public key in order to confirm the second kind of request. This access might be a result of either storing SSH public keys directly in the KDC database or a result of the KDC having read access to users' ~/.ssh/authorized_keys file. Initially the latter approach will probably be more useful.

The KDC could conceivably include an access control list indicating which host/XXXX@REALM keys are authorized to perform an SSH-key-for-TGT exchange; it might be the case that only certain hosts are allowed to do this.


Here's what a conversation looks like:

  1. The ssh client connects to the ssh server and indicates that it wants to use public-key authentication.

  2. Rather than generating randomness locally, the sshd uses service #1 mentioned above to acquire some signed randomness from the KDC and uses that instead. This signed randomness is associated with the connection in sshd's memory.

  3. Once the client signs the derived session key and sends it back to sshd, the sshd uses the host/XXXX@REALM key of the machine on which it is running to access service #2 above. The sshd machine presents the signed randomness to the KDC to prove that this is not a replay attack, and presents the hashed data plus signature to prove that some user connected to the host has demonstrated knowledge of the required SSH private key sometime between the time at which the randomness was generated and the current time. This window is constrained to be rather small (on the order of seconds or minutes).

  4. Based on the proof presented in step #3, the KDC issues a TGT to to the machine running sshd. This TGT is issued via a connection secured by the host/XXXX@REALM key, so it is secure against eavesdropping.

  5. The machine running sshd stores the received TGT in the user's local credentials cache and proceeds with login as usual (in the case of an AFS environment, libpam-afs will typically run aklog to acquire tokens).

If the machine running sshd is compromised, the attacker will only be able to steal short-lived tickets from users who connect to the machine after the compromise takes place. However, this presents no additional risk beyond that which is present when using GSSAPIDelegateCredentials – in that case the tickets of users connecting after the compromise are also at risk.