Introduction

This is a group assignment. Groups of up to 2 are recommended. You can work alone, but this assignment involves exploration, which is best done in a group.

In this assignment, you will write programs that launch a denial-of-service attack and a buffer overflow attack against a web server.

The web server we will attack is Tiny, the example server in Chapter 12 of the textbook.

The Tiny Web Server

The Tiny web server is a very small web server intended to demonstrate how to write a web server (i.e. one your browser can connect to).

It is also, perhaps inadvertently, a great example of many security bugs. Notably, it contains basic errors such as:

  1. Not validating user input.
  2. Assuming library functions will always succeed, and therefore not checking for errors.
  3. Using stack-allocated fixed-size buffers.
  4. Using unsafe C string functions.

In this assignment, you must identify these bugs, and develop exploits for them. You will develop two exploits:

  1. A denial-of-service attack: You will send a request to the web server that causes it to enter an infinite loop, preventing it from responding to other requests.

  2. A buffer overflow attack: You will send a request that overflows one of the fixed-size stack-allocated buffers. On most modern systems, protections are enabled that will cause the web server to shut down (see below) leading to what appears to be a denial-of-service attack. However, on older systems (or with the protections disabled), the server will actually execute instructions at an address controlled by the attacker (i.e. you).

Download and compile the Tiny web server. If you do this on the cycle machines (or on a machine with a recent GCC), note the warnings the compiler shows you. They all highlight potential vulnerabilities.

Run Tiny as follows, specifying a random port number:

./tiny 5678

You should use a random number from 1000 to 65535. If you get an error that another program is already listening on a shared computer, use a different port address. Use the same port in the examples below.

Denial-of-service attack

You will write a program dos.c, that accepts a single parameter, the port of the web server.

./dos 5678

In this case, your program is called with port 5678 (use a random number). Connect to the web server at this port, and send it the payload that will cause it to enter an infinite loop.

You are permitted to emit evil laughter if you succeed.

Update: Your payload should be less than 10,000 bytes.

Buffer-overflow attack

Write a program buf.c, that accepts two parameters, one a port and another a 64-bit integer representing a memory address. Your program must construct a payload that causes Tiny to begin execution at that memory address -- i.e. you have taken control of execution.

./buf 5678 0xaabbccddeeff1122

The buf program should connect to port 5678 and deliver a payload that causes a buffer overflow in the tiny web server, causing it to execute code at address 0xaabbccddeeff1122.

Most modern systems use a stack canary, so the buffer overflow will be detected and the tiny web server will be terminated with a message like this:

*** stack smashing detected ***: <unknown> terminated

or:

*** buffer overflow detected ***: ./tiny terminated

If you see these, edit the Makefile and add -fno-stack-protector to CFLAGS. Delete tiny, and recompile. Now, when you repeat the attack, you should get a more familiar:

Segmentation fault (core dumped)

UPDATE (12/3): To really make sure you get a segmentation fault, you should change the CFLAGS line in the tiny Makefile to be:

CFLAGS = -g -Wall -I.

Although this looks like a web server crash (and hence a denial-of-service attack), it is far more insidious, as this gdb session shows:

$ gdb ./tiny
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
 [omitted]

(gdb) run 5678

 [omitted, tiny will wait for payload to be sent from client separately]

Program received signal SIGSEGV, Segmentation fault.

 [omitted]

(gdb) p $rip
$1 = (void (*)()) 0x555555556bf9 
(gdb) bt
#0  [omitted]
#1  0xaabbccddeeff1122 in ?? ()

 [omitted]

As you can see, the return address has been changed to 0xaabbccddeeff1122. At this point, with some more time, you could get the tiny web server to potentially execute anything you wanted. However, the assignment requires you to only reach this point.

You are permitted to say HULK SMASH at this point.

Update: Your payload should be less than 10,000 bytes.

How to solve this assignment

Read the source code, especially tiny.c, you can achieve this assignment's goals just by targeting functions in that file. Indeed, if you're using the cycle machines, the compiler will actually warn you about lines in the source code that can trigger buffer overflow bugs.

Triggering the DOS is relatively simple -- the challenge there is to construct a program to talk to the server. Use the example client program in the lectures as an example.

Generating the buffer overflow is trickier. First, create a request that causes a buffer overflow. Then, use gdb to detect where the buffer overflow occurred (you will need to add the -g flag to CFLAGS). Once you have identified the function(s?) with the buffer overflow, think on how you would construct a request to exploit it.

Finally, construct a request that causes the return address to be overwritten with a user-supplied value. Note this second stage will only work if the stack canaries are disabled as noted above.

You may want to read up on what (obsolete) HTTP/1.0 requests look like. See especially Section 4, and everything before that you need to understand that section.

Feel free to ask questions on Piazza.