Network Security Fall 2021

The goals of this lab are to:

  1. Gain experience with key agreement protocols for symmetric key exchange over untrusted networks
  2. Implement a “stolen ticket” attack against Needham-Schroeder

Needham-Schroeder (NS) is known to be vulnerable to replay attacks. In particular, if an attacker steals a session key and corresponding ticket, they can replay the last three steps of the NS protocol and authenticate as the victim. In this lab, you are given two pairs of “stolen” tickets and session keys. Your goal is to authenticate to a service using each of these. One ticket does not expire. The other, however, is only valid for a short time window, and redeeming it will be awarded additional points.

The server for this lab runs on This NS implementation uses protobuf v3. Messages are defined as follows:

syntax = "proto3";

// Network messages.
// Each message sent over the network can be an encrypted message or a plaintext error message.
message WireMessage {
    oneof m {
        Encrypted encrypted = 1;
        string error = 2;

// Encrypted messages.
// The ciphertext decrypts to one of the messages below.
message Encrypted {
    bytes ciphertext = 1;
    bytes nonce = 2;

message Ticket {
    bytes session_key = 1;
    string client_principal = 2;
    uint64 timestamp = 3;

message Challenge {
    bytes nonce = 1;

message ChallengeResponse {
    bytes nonce_sub_1 = 1;

message Authenticated {}

message Request {
    string challenge = 1;

message Response {
    bytes response = 1;

All messages sent over the network are WireMessages, which are in turn either a plaintext error message or an encrypted message. Message encryption is performed using libsodium; a compatible python implementation is provided by pysodium.

Encrypted messages are a combination of a nonce and ciphertext produced using libsodium’s secretbox API.

As the attacker \(M\), you should use your stolen ticket and session key to engage in the following protocol which consists of the last three steps of NS followed by an authenticated request-response pair. Each message should be prepended by its two-byte, big-endian length as usual. Also, the tickets you are given are serialized WireMessages. Finally, the Needham-Schroeder challenge nonce (which is different from the libsodium encryption nonce) should be treated as a little-endian integer.

\[ \begin{align*} M \rightarrow S &: \mathsf{u16}(|\mathsf{Ticket}|) \cdot \mathsf{Ticket} \\ S \rightarrow M &: \mathsf{u16}(|\mathsf{Challenge}|) \cdot \mathsf{Challenge} \\ M \rightarrow S &: \mathsf{u16}(|\mathsf{ChallengeResponse}|) \cdot \mathsf{ChallengeResponse} \\ S \rightarrow M &: \mathsf{u16}(|\mathsf{Authenticated}|) \cdot \mathsf{Authenticated} \\ M \rightarrow S &: \mathsf{u16}(|\mathsf{Request}|) \cdot \mathsf{Request} \\ S \rightarrow M &: \mathsf{u16}(|\mathsf{Response}|) \cdot \mathsf{Response} \\ \end{align*} \]

Your attack should use your email address as the client principal. Having obtained a Response message, it should output a base64-encoded response in the following JSON object:

    "id": "{{client_principal}}",
    "response": "{{response}}"

Lab Objectives

The server container image as well as tickets and session keys are available in Canvas.

  1. Obtain an authenticated response for the non-expiring session key and ticket
  2. Obtain an authenticated response for the expiring session key and ticket

Submission Instructions

Submit the JSON objects your code outputs to Canvas.