Network Security Fall 2021

The goals of this assignment are to:

  1. Implement a network service that provides password authentication
  2. Defend the service against denial-of-service attacks
  3. Defend the service against online password guessing attacks

Service Specification

For this assignment, your service will implement a simple protocol using protobuf v3 messages. In this protocol, each message is preceded by a two-byte, big-endian integer giving the length of the following protobuf message. Each TCP connection only supports one message exchange. The protocol is as shown below.

\[ \begin{align*} C \rightarrow S &: \mathsf{u16}(|\mathsf{Request}|) \cdot \mathsf{Request} \\ S \rightarrow C &: \mathsf{u16}(|\mathsf{Response}|) \cdot \mathsf{Response} \\ \end{align*} \]

The messages themselves are defined as follows.

syntax = "proto3";

message Request {
    oneof request {
        StopRequest stop = 1;
        ResetBlockListsRequest reset = 2;
        ExpressionRequest expr = 3;

message StopRequest {}
message ResetBlockListsRequest {}

message ExpressionRequest {
    string username = 1;
    string password = 2;
    string expression = 3;

message Response {
    oneof response {
        StopResponse stop = 1;
        ResetBlockListsResponse reset = 2;
        ExpressionResponse expr = 3;

message StopResponse {}
message ResetBlockListsResponse {}

message ExpressionResponse {
    bool authenticated = 1;
    string result = 2;

The protocol runs on port 13000/tcp. StopRequest is a meta-request; upon reception, the server must immediately terminate. ResetBlockListsRequest is also a meta-request; upon reception, the server must immediately expunge all block list entries.

The application protocol that will be evaluated consists of ExpressionRequest and ExpressionResponse exchanges; think of the service as a trivial example of outsourced computation. Servers must implement user authentication by checking usernames and passwords against a provided database. The database will consist of a TOML document that contains an array of user objects with username and password_hash keys. Password hashes follow PHC string format. Use appropriate libraries of your choice to support the following hash algorithms.

  • SHA-256
  • SHA-512
  • bcrypt
  • Argon2

An example user database is as follows:

username = "mario"
# password = "m4mmAM!4$$$"
password_hash = "$argon2id$v=19$m=102400,t=2,p=8$Zwzh3HsPQcj5fw/hfK+1Fg$xjJOvlBbDDxe3InW2Tm17Q"

username = "luigi"
# password = "super plumber luigi time"
password_hash = "$5$rounds=535000$TqX3t1a9E3VMMzdV$Yv3cImIQytnyRxziLj2hgb.G4Vd2LRsOxNjldrzy/g5"

On successful authentication, the authenticated field must be set to true in the response. The server must also provide the result of evaluating the Python expression contained in the request’s expression field in the response’s result field. If authentication failed, authenticated must be set to false in the response and result is undefined.

Expression evaluation must be implemented by executing a Python interpreter on the expression. The result is the captured output of the evaluation (stdout only).

The service must be packaged as a container image that can be executed with the following invocation:

$ docker run -it --rm \
    -p 13000:13000 \
    -v ${host_path}/users.toml:/tmp/users.toml \
    ${image_name} /tmp/users.toml

Defending Against Attacks

The service must implement defenses against denial-of-service and password guessing attacks.

  1. The server must provide concurrent service for at least 4 clients. Feel free to use multiprocessing, multithreading, or asynchronous code to achieve this.

  2. The server must identify clients that send more than 30 invalid requests within the span of 60 seconds to the service, and permanently block those source IP addresses. Invalid requests are those that fail to parse, that do not contain a required field such as a username or password, that contain an invalid password, that contain an invalid expression, or have any other feature that prevents a successful response.

  3. (Graduate Only) The server must time out slow clients to avoid “Slowloris”-style attacks. Slow clients are defined as those that take more than 30 seconds to send a request. Source IP addresses for offending clients must be permanently blocked (until cleared by a ResetBlockListsRequest).

  4. (Graduate Only) The server must identify and terminate expression evaluations that take longer than 5 seconds to compute. Users that submit such expressions must be permanently blocked (until cleared by a ResetBlockListsRequest).

The server will be evaluated on its ability to block malicious clients (true positives) while preserving service to benign clients (avoiding false positives).

Public Tests

A partial test suite is available as a statically-linked x86_64 binary in Canvas as password_tests, and can be invoked against your server as follows.

$ password_tests ${server_address}:${server_port}

Submission Instructions

Package your solution as a gzipped TAR archive. Your solution should have the following structure.

$ tree -F a03_passwords
├── Dockerfile
└── src/

The root directory must be named a03_passwords, and the source code to your solution should be contained in src/. Your Dockerfile should produce an image that follows the invocation instructions above.

Submit the solution archive to Canvas.