Next, we will understand what kind of mistakes cause format string vulnerabilities by exploring some examples and finally we will discuss various risks that format string vulnerabilities bring with them. 

Unusual usage of printf function

Let us begin by considering the following example to understand some unusual ways of using printf function in  C language. Let us use the following C program, where we have one additional format specifier than the number of variables to be printed. Essentially, the program has 5 variables (a, b, c, d, e) to be printed but we are specifying 6 format specifiers. test6.c When printf function is executed in the preceding program, the following events occur: int a = 100; float b = 2.3; int *c;         c = &a;  char d[] = “demo”; char *e = d; printf(“%d, %1.1f, %p, %p, %p, %p n”, a,b,c,d,e); }

The data available in variable a (on the stack), will replace the format specifier %d and an integer value (100) will be printed. The data available in variable b (on the stack), will replace the format specifier %1.1f and a float value (2.3) will be printed. The data available in variable c (on the stack), will replace the format specifier %p and the address of variable a, which is a pointer to the data stored in variable a will be printed. The data available in variable d (on the stack), will replace the format specifier %p and the address of the string demo will be printed. The data available in variable e (on the stack),  will replace the format specifier %p and the address of the string demo will be printed.

What happens when the last format specifier (%p) is seen by printf function? The next value on the stack will be fetched and printed even though there are no user initialized variables. It is possible to add as many format specifiers as we wish and subsequent entries from the stack will be fetched and printed. Let us test our theory by compiling and executing this program. The following gcc command can be used on a Linux machine to compile the program. Running the output binary test6 prints an additional value from the stack as highlighted below. As we can notice, the number of entries in the output is equal to the number of format specifiers used with printf function. $ Similarly, we can add more format specifiers to the printf function as shown in the following code snippet. test7.c As we can notice in the above excerpt, there are 6 additional format specifiers this time in the C program. int a = 100; float b = 2.3; int *c;         c = &a;  char d[] = “demo”; char *e = d; printf(“%d, %1.1f, %p, %p, %p, %p, %p, %p, %p, %p, %pn”, a,b,c,d,e); } Running this program displays some more entries from the stack as shown in the following excerpt. Since, the program is fetching memory addresses from the stack using it’s printf function, if an attacker can control the format specifier part of the target binary, it is possible to leak memory addresses and perform further attacks such as leaking secrets and bypassing exploit mitigation techniques. The next section explains various other  $

How can format string vulnerabilities be exploited?

Leaking memory addresses:

Leaking memory addresses of a process can lead to exploit mitigation bypasses. For example, ASLR randomizes base addresses of stack and other libraries such as libc. Using format string vulnerabilities, it is possible to leak addresses from stack and derive their respective base addresses. In addition to it, it is also possible to leak canaries and bypass stack smashing protections.

Leaking secrets:

If any secrets strings are stored on the stack, it is possible to leak them using format string vulnerabilities. This can be done by using %s format specifier, which is used to print data pointed by an address. So, this format specifier can be used to locate a string from memory using format string vulnerabilities.

Overwriting memory addresses:

So far, we discussed attacks that read data from memory. By using the format specifier %n, it is also possible to write to specific memory locations. Furthermore, it is possible to redirect function pointers to user-controlled shellcode. It is also possible to use Format String vulnerabilities to overwrite Global Offset Table leading to code execution.

Denial of Service:

When the exploit techniques discussed so far are not working or are deemed to be less useful, it is possible to cause Denial of Service attacks by causing a segmentation fault. This can be done by attempting to access invalid memory addresses using the control we have on the format specifiers.

Conclusion

In this article, we discussed how printf like functions behave when more format specifiers than those that are needed are passed to it. They cause memory leaks leading to various different attacks including Denial of Service. We have discussed what kind of impact format string vulnerabilities can cause when exploited. In the next article, we will discuss how Format String vulnerabilities can be exploited when user-controlled input is passed to print functions.  

Sources

https://owasp.org/www-community/Source_Code_Analysis_Tools https://owasp.org/www-community/attacks/Format_string_attack https://www.netsparker.com/blog/web-security/format-string-vulnerabilities/