A format string is an ASCII string that contains text and format parameters.
// A statement with format string printf("my name is : %s ", "Akash"); // Output // My name is : Akash
There are several format strings that specify output in C and many other programming languages but our focus is on C.
Format string vulnerabilities are a class of bug that take advantage of an easily avoidable programmer error. If the programmer passes an attacker-controlled buffer as an argument to a printf (or any of the related functions, including sprintf, fprintf, etc), the attacker can perform writes to arbitrary memory addresses. The following program contains such an error:
Since printf has a variable number of arguments, it must use the format string to determine the number of arguments. In the case above, the attacker can pass the string “%p %p %p %p %p %p %p %p %p %p %p %p %p %p %p” and fool the printf into thinking it has 15 arguments. It will naively print the next 15 addresses on the stack, thinking they are its arguments:
$ ./a.out "%p %p %p %p %p %p %p %p %p %p %p %p %p %p %p" 0xffffdddd 0x64 0xf7ec1289 0xffffdbdf 0xffffdbde (nil) 0xffffdcc4 0xffffdc64 (nil) 0x25207025 0x70252070 0x20702520 0x25207025 0x70252070 0x20702520
At about 10 arguments up the stack, we can see a repeating pattern of 0x252070 – those are our %ps on the stack! We start our string with AAAA to see this more explicitly:
$ ./a.out "AAAA%p %p %p %p %p %p %p %p %p %p" AAAA0xffffdde8 0x64 0xf7ec1289 0xffffdbef 0xffffdbee (nil) 0xffffdcd4 0xffffdc74 (nil) 0x41414141
The 0x41414141 is the hex representation of AAAA. We now have a way to pass an arbitrary value (in this case, we’re passing 0x41414141) as an argument to printf. At this point we will take advantage of another format string feature: in a format specifier, we can also select a specific argument. For example, printf(“%2$x”, 1, 2, 3) will print 2. In general, we can do printf(“%$x”) to select an arbitrary argument to printf. In our case, we see that 0x41414141 is the 10th argument to printf, so we can simplify our string1:
$ ./a.out 'AAAA%10$p' AAAA0x41414141
Preventing Format String Vulnerabilities
- Always specify a format string as part of program, not as an input. Most format string vulnerabilities are solved by specifying “%s” as format string and not using the data string as format string
- If possible, make the format string a constant. Extract all the variable parts as other arguments to the call. Difficult to do with some internationalization libraries
- If the above two practices are not possible, use defenses such as Format_Guard . Rare at design time. Perhaps a way to keep using a legacy application and keep costs down.Increase trust that a third-party application will be safe
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.