Format string attack
A format string vulnerability is a bug where user input is passed as the format argument to printf, scanf, or another function in that family.
The format argument has many different specifies which could allow an attacker to leak data if they control the format argument to printf. Since printf and similar are variadic functions, they will continue popping data off of the stack according to the format.
For example, if we can make the format argument "%x.%x.%x.%x", printf will pop off four stack values and print them in hexadecimal, potentially leaking sensitive information.
printf can also index to an arbitrary "argument" with the following syntax: "%n$x" (where n is the decimal index of the argument you want).
While these bugs are powerful, they're very rare nowadays, as all modern compilers warn when printf is called with a non-constant string.
Example
#include <stdio.h>
void main(int argc, char **argv)
{// This line is safeprintf("%s\n", argv[1]);
// This line is vulnerableprintf(argv[1]);
}
Safe Code
The line printf("%s", argv[1]); in the example is safe, if you compile the program and run it:
./example "Hello World %s%s%s%s%s%s"
The printf in the first line will not interpret the “%s%s%s%s%s%s” in the input string, and the output will be: “Hello World %s%s%s%s%s%s”
Vulnerable Code
The line printf(argv[1]); in the example is vulnerable, if you compile the program and run it:
./example "Hello World %s%s%s%s%s%s"
The printf in the second line will interpret the %s%s%s%s%s%s in the input string as a reference to string pointers, so it will try to interpret every %s as a pointer to a string, starting from the location of the buffer (probably on the Stack). At some point, it will get to an invalid address, and attempting to access it will cause the program to crash.
Different Payloads
An attacker can also use this to get information, not just crash the software. For example, running:
./example "Hello World %p %p %p %p %p %p"
Will print the lines:
Hello World %p %p %p %p %p %p
Hello World 000E133E 000E133E 0057F000 CCCCCCCC CCCCCCCC CCCCCCCC
The first line is printed from the non-vulnerable version of printf, and the second line from the vulnerable line. The values printed after the “Hello World” text, are the values on the stack of my computer at the moment of running this example.
Also reading and writing to any memory location is possible in some conditions, and even code execution.
For more information, please see the Exploiting Format String Vulnerabilities article from 2001.
Similar Functions to printf
The whole printf function family is vulnerable. Here is an example of snprintf:
#include <stdio.h>
void main(int argc, char **argv)
{char buf[100];snprintf(buf, sizeof buf, argv[1]);
}
Running this program as the following will cause a crash.
./example "Hello World %s%s%s%s%s%s"
A safe use of snprintf will be:
snprintf(buf, sizeof buf, "%s", argv[1]);