CSC 482 Format Strings
The learning objectives of this lab are to become familiar with testing programs in the Unix environment and to learn how format string vulnerabilities can be exploited to read data from memory. While we will be exploiting a local program with a format string vulnerability, format string vulnerabilities can be exploited remotely if network services accept user input as format strings. Read man 3 printf to refresh your memory of the details of format strings in C before starting this activity. The table on the C/C++ reference site at http://en.cppreference. com/w/cpp/io/c/fprintf is a good place to look up format string specifiers. We will use the %d, %x, and %s specifiers in this activity. The readings on the class schedule web site include a detailed tutorial on format string exploitation. Read that tutorial and do the examples in it if you have difficulties understanding how to do the experiments below.
1 Experiment: Missing Format String
For our first experiment with format strings, let us examine the result of using printf() with and without arguments. Save the code below as printf-test.c and compile it program with the command gcc -o printf-test printf-test.c. The compiler may emit a warning about a format security problem with this and other programs in this lab. Pay attention to compiler warnings to avoid security problems like the ones we explore in this activity. #include
2 Experiment: Viewing Stack Contents
For our second experiment, let us see what can be done using a user-supplied format string. Save the code below as printf-test2.c and compile it program with the command gcc -o printf-test2 printf-test2.c. Run the program with different format strings as ar- guments, such as ./printf-test2 "%d", ./printf-test2 "%d.%x", and ./printf-test2 "%d.%x.%x.%s". What do you see with different format strings? #include
3 Experiment: Viewing Heap Contents
Before beginning this section, turn off address randomization with the following command. Address randomization is an important security defense that we will discuss later in the course. $ sudo sysctl -w kernel.randomize_va_space=0 Download vul prog.c and compile it. This program stores two secrets on the heap, which are accessed via a pointer on the stack. While we can easily read the secrets from the source
Page 2 code, we could not read them from a SETUID binary that is executable but not readable (mode 711, for example.) Yet because the program accepts user input and uses it as a format string, we will be able to read the secrets from memory. This vulnerability can be seen in the code snippet below. printf("Please enter a decimal integer\n"); scanf("%d", &int_input); /* getting an input from user */ printf("Please enter a string\n"); scanf("%s", user_input); /* getting a string from user */
/* Vulnerable place */ printf(user_input); Our goal in this section is to view the contents of secret[1]. Since the secret is stored on the heap, we cannot view it directly. Instead, we will need to place the address of the secret into memory, then use a format string vulnerability to print the contents of that address. The first step towards this goal is to use the integer input to place a known value into memory, then use a number of %x values to view the stack contents and view the string. The placement of the string in the output will indicate which %x placeholder holds the contents of the integer input. The next step is to enter a decimal number that is the address of the location of the string in memory. We can use the printf bash command to convert between decimal and hexadecimal formats as follows to help with this task. $ printf "%d\n" 0xFF 255 $ printf "%x\n" 255 ff The other conversion that will be needed is to convert ASCII characters to numbers. Entering man ascii will provide a table for such conversions.
4 Experiment: Modifying Heap Contents
The %n format specifier will write the number of bytes printed prior to it to the memory location pointed to by the current stack value. Use %n in place of %s to modify the secret instead of viewing it. Our goal in this section is to set secret[1] to the value 0x50. Use the precision options of format strings to control the value.
Page 3 5 Deliverables
Turn in a sheet of paper with your class number, instructor name, and your own name at the top. The paper should be divided into sections with the same numbers and names as the experiment sections in this document. In each section, show the inputs used to achieve the goal of the experiment.
Page 4