<<

CSC 482 Format Strings

The learning objectives of this lab are to become familiar with testing programs in the 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 to refresh your memory of the details of format strings in C before starting this activity. The table on the C/C++ reference site 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-.c and compile it program with the 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 int main(int argc, char *argv[]) { char fmt[]="%d %x\n"; printf(fmt, 4096, 0xDEADBEEF); printf(fmt); } Answer the following questions: 1. How does the output of the two printf calls differ? 2. If you run the program multiple times, the output changes. Why might this happen?

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 - 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 int main(int argc, char *argv[]) { if(argc >= 2) { printf(argv[1]); printf("\n"); } else fprintf(stderr, "No command line arguments supplied.\n"); } Typing longer and longer format strings to of the contents of the program’s memory becomes tedious. To automate this process, we can use one line perl scripts and take advantage of perl’s string multiplication operator. Simple perl scripts like these can be extremely useful to generate the unusual input strings that we need to test the security of programs. $ perl -e ’print ("%08x." x 8); print "\n"’ %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x $ perl -e ’while($i<4) { print ("%08x." x 8); print "\n"; ++$i }’ %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x %08x.%08x.%08x.%08x.%08x.%08x.%08x.%08x Our next problem is to use these strings as command line arguments. This can be accom- plished by capturing the output of a command with the following syntax. $ myarg=$(perl -e ’print ("%08x." x 8); print "\n"’) $ $myarg $ ./printf-test2 "$(perl -e ’print ("%08x." x 8); print "\n"’)" Use perl’s to generate command line arguments to test-printf2 to dump 1024 bytes of memory or as close to that amount as you can dump. Once you accomplish that, keep dumping memory until you cause a segmentation fault. Using string format instead of hex format can be useful for this purpose.

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. $ sysctl - kernel.randomize_va_space=0 Download vul prog.c and compile it. This program stores two secrets on the heap, 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 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 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 . 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