CS177: Project 5 - Authentication and Impersonation (15% of project score)

Project Goals

The goals of this project are:

  • to implement a part of the Needham-Schroeder key exchange protocol
  • to leverage a stolen key and ticket to impersonate a victim when connecting to a network service

Administrative Information

The project is an individual project. It is due on Thursday, May 28, 2020, 23:59:59 PST (no deadline extensions; late flags will not be accepted).


According to the MITRE ATT&CK framework, pass-the-ticket (PtT) is a method of authenticating to a system using Kerberos tickets without having access to an account's password. This is often a first step to lateral movement, where an intruder is moving to other (higher value) hosts after gaining an initial foothold into a victim network. In this technique, valid Kerberos tickets for valid accounts are captured by credential dumping on the compromised host (using tools such as Mimikatz). When the adversary is able to obtain a service ticket, they would be able to use this ticket to access a remote service of interest.

Detailed Description

In this project, you will implement a simplified pass-the-ticket attack. We will not target an actual Kerberos system. Instead, we will implement this attack against a simplified version that uses the Needham-Schroeder (NS) symmetric key protocol. The NS protocol can be used to establish a session key between two parties over an untrusted network (for example, a user and a network service). Let's assume that a user in the network (let's call her Alice) wants to authenticate and communicate with a service (let's call this service Bob). Both Alice and Bob trust a central server, called the Authentication Server (AS). Alice and Bob use the NS protocol and the trusted AS to establish a session key between the two of them.

Like for previous challenges, you will first go to our CTFd site and launch your service instances. The site will give you the address and destination port where your service (Bob) is running and listening for your connections.

Both Alice and Bob have their own established keys K_AS and K_BS that they share with the Authentication Server (AS). In the case of Alice, this could be a password that Alice has registered with the central AS. The protocol proceeds in the following five steps (you can find a more detailed description for the protocol here).

  1. Alice notifies the AS that she wants to talk to Bob.
  2. The server generates a session key K_AB and sends back to Alice two pieces of information: First, the AS will send a copy of the session key K_AB, encrypted using K_AS (which is the key the AS shares with Alice). This will make sure that Alice gets a copy of the session key for herself. Second, the AS will send a ticket to Alice (which is also encrypted with K_AS). This ticket contains a copy of the session key K_AB, encrypted with Bob’s shared key with the AS (which is K_BS).
  3. Alice cannot open the ticket herself, but she forwards this ticket to Bob.
  4. Bob can decrypt the ticket (using his own key K_BS), and by doing so, he also obtains the session key K_AB. He then generates a challenge, encrypts it with K_AB, and sends this back to Alice.
  5. Alice decrypts the message and obtains the challenge. She then sends back a response to this challenge, again using the session key K_AB.

At this point, both parties are convinced that the session key K_AB is known to both sides, and they can use this key to start their communication.

Unfortunately, the Needham-Schroeder protocol is shown to be vulnerable to a replay attack where an attacker, Eve, could learn (or compromise) a session key K_AB and its corresponding ticket. This could happen, for example, when the attacker extracts from the memory of a compromised machine a key and a service ticket that were used in a prior, legitimate connection. Using this information, Eve can carry out Steps 3-5 of the Needham Schroeder protocol with Bob, who will accept K_AB as the session key, and who thinks he is talking to Alice. That is, Eve can impersonate Alice and talk to Bob (as if she was Alice).

In this project, you are given the key that is used by Alice to communicate with the Authentication Server (K_AS). You are also given the message that Alice received from the AS in Step 2 of the Needham-Schroeder protocol (recall that this includes the session key K_AS and the ticket for Bob). Your goal is to use this information to impersonate Alice when talking to Bob (our server). When you complete the NS protocol and successfully impersonate Alice, our server will send you a flag (which is encrypted with the session key). In other words, you have to perform Steps 3-5 of the NS protocol. As usual, once you have obtained the flag, submit them

In our project, all participants use SecretBox as the (secret-key) cryptographic algorithm that is used to encrypt and decrypt all messages. SecretBox uses a combination of the Salsa20 stream cipher and Poly1305 MAC. Of course, this means that you need to use SecretBox to encrypt and decrypt messages, regardless of the program language you use for this project. For Python, you can find a library that implements SecretBox here. We strongly recommend that you use this library to encrypt and decrypt the messages.

SecretBox uses a (master) secret key and a nonce value. The nonce value contains 24 bytes, which are randomly generated whenever some data is encrypted (more specifically, the nonce value is used together with the master key to create the encryption key used for the operation). Of course, the nonce must be sent together with the ciphertext. This is because the same nonce has to be used for the corresponding decryption operation. That is, the party who receives the ciphertext (and who also knows the master key) can use the nonce together with the master key to decrypt the message. Note that this SecretBox nonce is different from the nonce N_A that is used in Step 2 of the Needham-Schroeder protocol.

For our project, each exchange (message) between your client and the server has two parts. The first part is a fixed-length unsigned short integer (which we call m_len) that indicates the length of the following message, in bytes. The server expects the length value in big-endian (also called network byte order). For the second part, which is the actual message, we will be using protobuf. You will recognize that this format is very similar to what we used in the first project. This time, we also provide the protobuf definitions to make things easier and to avoid confusion. You can get the protobuf file here.

Each message (which is called WireMessage in the protobuf file) either contains an encrypted message (of type Encrypted) or a string with an error message. Each encrypted message (of type Encrypted) contains a ciphertext field and a nonce field. The nonce is included so the other party can decrypt the ciphertext using the SecretBox library.


For this project you need to implement the following steps:

  1. You need to obtain the ticket. Remember that you are given K_AS (the key that is used by Alice to communicate with the Authentication Server). Note that the password can be simply read in as raw bytes from a file, which you can obtain here. You are also given the message that Alice received from the AS in Step 2 of the Needham-Schroeder protocol. This message is of type AuthenticationServerResponse (as identified in the protobuf file), and can be obtained here. You need to parse the message to obtain the session key K_AB and the ticket.
  2. Once you have the ticket, you need to send it to the server. This is Step 3 of the Needham-Schroeder protocol. Please note that you do not need to make any modification to the ticket. If the ticket is valid, the server responds back to you with a challenge value, which will be encrypted with the session key K_AB. This is Step 4 of the NS protocol.
  3. Now, you need to solve the challenge and send the correct response to the server. For that, you may look at Step 5 of the Needham-Schroeder protocol. The server expects that the response to the challenge is packaged in exactly the same way as the challenge message. That is, you need to put the response into a protobuf of type Challenge before encryption.
  4. At the end, if the response is accepted by the server, the server sends the flag, which is encrypted with the session key K_AB. You need to decrypt it and submit the flag.

Every time you need to encrypt a message, you need to use the SecretBox algorithm and pass in both the ciphertext and nonce (the two fields in the Encrypted type in the protobuf file). Every time you want to decrypt a message, you need to parse the encrypted message to obtain both the ciphertext and the nonce, which you will then pass as arguments to the SecretBox decryption algorithm.