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 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:
In this assignment, you must identify these bugs, and develop exploits for them. You will develop two exploits:
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.
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.
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.
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.
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.