What is Format String ?
if you wrote a C code before I guarantee that you’ve seen printf() function which writes a formatted string to the stdout. The first argument of printf() is the string that contains the text to be written to stdout. It can optionally contain embedded format tags that are replaced by the values specified in subsequent additional arguments and formatted as requested.
int printf(const char *format, …)
Format String | Output | Usage |
%d | Decimal (int) | Output decimal number |
%s | String | Reads a null-terminated string from memory |
%x | Hexadecimal | Output a hexadecimal number |
%n | Number of bytes written so far | Writes the number of bytes till the format string to memory |
%p | Pointer | Prints out a pointer in hexadecimal format |
For detailed description of printf function and format specifiers check this:
http://www.cplusplus.com/reference/cstdio/printf/
Format strings vulnerability exists in most of the printf family functions like:
- printf
- fprintf
- vsprintf
- vsnprintf
- sprintf
- snprintf
- vfprintf
- vprintf
Example:
#include <stdio.h> int main () { int chr; for( chr = 97 ; chr <= 122; chr++ ) { printf("ASCII value = %d, Character value = %c, Hex value = %x\n", chr , chr, chr); } return(0); }
gcc -m32 printf_example.c -o printf_example
./printf_example
The format string parser searches the first argument of the printf function for any format specifier which starts with the ‘%’ symbol and replace them with the subsequent arguments of the function respectively.
When format strings are vulnerable?
if the printf function doesn’t have a format string and the variable controlled by the user is passed to the function directly, it leads to a format string vulnerability.
Example:
#include <stdio.h> #include <string.h> int main (int args, char ** argv) { char buffer[100]; strncpy(buffer, argv[1], 100); printf(buffer); return(0); }
gcc -m32 printf_vulnerable.c -o printf_vulnerable
./printf_vulnerable
If we execute the program with normal string as argument it will work fine
But what if we pass a format specifier to the program as argument instead of a normal string?
oops! we could leak the values on the stack through passing the format specifier ‘%p‘ ( which prints out a pointer in hexadecimal format ) multiple times as the argument to the printf function and the function didn’t find a corresponding variable or value on the stack so it will start popping values off the stack.
Notice that: 0x41414141 and 0x42424242 are the hex representations of the string “AAAABBBB” that we passed before the format specifiers.
How to exploit a format string vulnerability?
Although format string vulnerabilities are not prevalent anymore, you still have chances to find them in legacy programs.
And the exploitation of this vulnerability not the same for every situation but there are some general steps you can apply:
1- Start fuzzing any input you can find to the program with different format specifiers
2- Check if you got unusual output and then explore further
Most of the time hackers combine format string vulnerability with other vulnerabilities to bypass mitigations like ASLR. Say we have stack buffer overflow bug in a program but it has ASLR enabled and we found a format string bug also, then we can leak addresses from the stack and get the actual addresses we need at runtime.
Finally let’s review what we can gain from exploiting a format string vulnerability (as i said before it is scenario dependent).
- Denial of service
- View data on the stack
- View memory at arbitrary locations
- Code execution (If you are lucky)
- Write data into arbitrary locations
This was a brief introduction to format string vulnerabilities for in-depth explanation i highly recommend part 0x350 from Hacking The Art Of Exploitation 2nd Edition Book By Jon Erickson.
References:
- Hacking The Art Of Exploitation 2nd Edition By Jon Erickson [Book]
- https://en.wikipedia.org/wiki/Printf_format_string
- https://en.wikipedia.org/wiki/Uncontrolled_format_string
- https://www.owasp.org/index.php/Format_string_attack
Leave a Reply