# A1 **Deadline:** Wednesday, September 19, 2018, 11:55 pm *This assignment may be completed individually or in pairs* ## Structure of the Server and ```telnet``` Tutorial This assignment will have you launch a series of attacks against a small server, which can serve–among other things–HTML and image files. The starter files for this assignment are available <a href="a1.zip">here</a>. The server is implemented in the file server.c. <b>Note:</b> If you are having trouble configuring your system, you might want to use <a href="181S-2018fa.vdi.zip">this VM</a> to complete this assignment. You can run this disk image with <a href="https://www.virtualbox.org">VirtualBox</a> (also available on the lab machines). <br/>Settings: 64-bit Ubuntu, 4GB+ memory. Username: 181S Student Password: 181S-Security. This server is woefully incomplete: it only implements a very tiny part of the HTTP–the exchange-format used between web-browsers and servers. And yet this server still implements enough of HTTP to be able to display static content. Note that the word “server” is used all over the place in tech. For this assignment, a “server” means an application that can exchange data with a user on the other end of a communication channel (frequently called a “port”). Begin by building the server: ``` make fs ``` This command builds the version of the server with all of the fancy modern protection mechanisms enabled, so it won’t be susceptible to (as many of) the attacks we’ll launch in this assignment. To run the server, type the following: ``` ./fs ``` The server should now be running on port 5000. This means that it’s listening for connections. To talk to the server, you can use the telnet program: ``` telnet localhost 5000 ``` The first command-line argument is the server to connect to. This could be a remote host, like www.cs.pomona.edu, but in this case it’s going to be a special host named localhost, which is an alias for the IP address 127.0.0.1. This is like talking to a remote machine, across the internet, except you’re talking to a server running your local machine. Once we’re connected, we can start sending the server commands: ``` hello Hello! ``` When we type in “hello”, the server replies back with “Hello!.” The complete list of commands is documented below. This server also supports a form of HTTP, which is a standard format (protocol) used to exchange data between your web browser and the server itself. Think of the web browser as doing this same stuff that you’re typing into telnet in a specific way, except that it’s doing it using a program. To see this, open a web browser (inside of the VM, using the user interface) and point the address address bar at localhost:5000. Like navigating to www.cs.pomona.edu, the server sends the necessary commands to our server application to retrieve the page. You should be able to see the server application generating some logs as it does this, so you can see which files get requested. Here’s the complete list of commands: * ```hello``` replies back with Hello! * ```goodbye``` terminates the connection * ```echo <text>``` replies back with “Server is echoing: “ followed by * ```setmsg <msg>``` sets a global variable in the server named special_message * ```getmsg```, gets the special message set with setmsg * ```authenticate <tried_password>``` authenticates the connection to with a password when ```<tried_password>``` matches the password hard-coded into the server. Once the connection has been authenticated, it will reveal the “secret message”, which is also hard-coded. * ```getsecret``` gets the secret, assuming the connection has been authenticated * ```get <URI> <http-version>``` GETs a resource using the HTTP protocol. Here’s an example ``` authenticate secret You are now authenticated getsecret hello my message is here echo Hi, my name is Charles! Server is echoing: Hi, my name is Charles! getmsg Here is a special message ``` I expect you to be able to pick up and read through server.c on your own, and this is specifically part of the project. A large part of security (and software-engineering at large) is figuring out other people’s code. So work through it, and when you get stuck, play around with telnet. When you get confused, insert logmsg or printf statements, or (better yet) walk through it in the debugger. ## Problem 1: Crashing the Server **Note:** From now on, make sure you use the ./fs_nsp_nnx executable. This is the one that is vulnerable. ./fs has full protection mechanisms turned on. Consider the handle_connection function inside of of the server executable. The local variables for handle_connection will be laid out on the stack in order. This function is insecure because fails to perform a bounds-check before copying data: the variable string in handle_connection is a buffer of size 100, but inputs of up to 1024 can be read into the larger (global) buffer variable. Your first job is to figure out an input that could be sent to the server that would cause the return instruction pointer to be overwritten, so that–upon returning from handle_connection, the program would go to a nonsense location and the program would crash. (FYI: the reason why it would crash is that control flow would wander into an unmapped or unauthorized page, generating a segmentation fault.) During a successful attack, the server should look something like this: ``` Got a connection on port 5000, handling now. ffffdc70 Received some data! echo <more stuff here> Segmentation fault (core dumped) ``` Once you figure it out, the next step is to script your attack. I’ve included a simple script, client.py. Script your attack in the function crash_server. #####Hints: 1. If you need a review of C, assembly, or gdb, try doing the optional <a href="exercises.html">review exercises</a> before starting the assignments. 2. The following GDB commands might be helpful: ``` info frame info locals print <address-in-hex> print $rsp / etc.. (for registers) x/20xb <address> / x/20xb $rsp / etc.. ``` 3. Remember the stack grows down! 4. The following Python socket functions might be useful: ``` send recv ``` For example, you could write s.send("echo hello") to send “echo hello” to the server. Note that the Python API takes care of some of the ceremony of doing things like writing the length. 5. send expects a byte string as argument. To turn a Python string into an array of bytes, use the following: "echo ".encode(). 6. If you want to represent a single byte, use b’\x23’, which represents the single byte containing the hex value 0x23. If you wanted to write the string containing the bytes 0x23, 0x24, 0x57, and 0x42, in that order, you could write b’\x2e\x24\x57\x42’ 6. You will probably want to want combine the string “echo “ with a sequence of bytes. To do this, you can simply add them together (since Python’s add is overloaded): “echo “.encode() + b’\x41’ * 23 generates the ASCII for “echo “ (note the space), followed by the letter ‘A’ (ASCII-encoded) 23 times. ## Problem 2: Owning Control Flow Craft an exploit that will force the program to print out “Hello, world!\n”. To do this, follow the same technique you did in Problem 1, but instead of making %rip become some nonsense value, make it the address of the function hello_world. That way, when the program returns from handle_connection, it will then go to hello_world instead. Write your exploit inside of the Python function hello_world. It is totally okay if the server crashes after printing “Hello, world!” When you get done, the server should do something like this: ``` Hello, world! Illegal instruction (core dumped) ``` #####Hints: 1. Use GDB to manually figure out how to redirect control flow at first. This helps you get a feel for where things should be in memory, and you can draw them out on a whiteboard or on paper as you use GDB. It also helps you debug your exploit as you develop it. 2. The gdb commands info frame, print, x, and set might be helpful. 3. Remember, you’re on a little-endian machine. So if I give you the number 0xDEADBEEFDEADBEEF, it will be represented as 0xEFBEADDEFEBEADDE. ## Problem 3: Executing Shellcode Now you can control control-flow. Great. But say you want to run your own code. To do this, you need to inject some assembly code into your program, and then have %rip jump to the shellcode. Your task in this part is to inject the shellcode into the program (via the buffer overflow) and then jump to it. I have included a sample shellcode in the file shellcode.c (its assembly is given, too). Write your shellcode injection in the Python function inject_execute_shellcode #####Hints: 1. You’re going to want to place your shellcode somewhere inside the buffer, and then smash the stack so that control flows back to wherever you placed that shellcode. Therefore, you need to figure out the position of the string variable. ## Problem 4: Leaking the Secret The server implements some code to check that the user types in a proper authenticate command before allowing the secret message to be retrieved. E.g., if I simply telnet into the server and then type in getsecret I get the message: “You are not authenticated right now, first use the authenticate command.” Your job in this part is to figure out how to get the server to give me the secret message without typing in the password. Write your solution in the function leak_secret. #####Hints: 1. This part requires injecting some of your own shellcode that writes a nonzero value to the address of is_authenticated. ## Feedback This is the first time this course has been offered. In the interest of improving future iterations of this course, please answer the following questions and upload them in a file called ```feedback.txt```: 1. How long did you spend on this assignment? 2. Any comments or feedback? Things you found interesting? Things you found challenging? Things you found boring? ### Collaboration Policy You may work individually or in pairs. If you choose to work in pairs, you should submit only one solution. You may discuss ideas with other students at a high-level, but under no circumstances should you be looking at code written by anyone other than you or your partner. Any ideas that originated with another person should be cited. ### What to Submit Submit your attack script client.py containing the four attack functions. Be sure to include the constants requested in the comment at the top! You should also submit a feedback file feedback.txt containing the answers to the feedback questions. Submissions that fail to follow the submission guidelines may be subject to a 10% deduction.