CS177: Project 5 - Authentication and Impersonation (15% of project score)
The goals of this project are:
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.
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).
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:
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.