A format string is an ASCII string that contains text and format parameters.
// A statement with format string printf("my name is : %s\n", "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
This article is contributed by Akash Sharan. If you like GeeksforGeeks and would like to contribute, you can also write an article using contribute.geeksforgeeks.org or mail your article to firstname.lastname@example.org. See your article appearing on the GeeksforGeeks main page and help other Geeks.
Please write comments if you find anything incorrect, or you want to share more information about the topic discussed above.
Attention reader! Don’t stop learning now. Get hold of all the important DSA concepts with the DSA Self Paced Course at a student-friendly price and become industry ready.
- Encode an ASCII string into Base-64 Format
- Spectre Security Vulnerability
- Meltdown Security Vulnerability
- Vulnerability in input() function – Python 2.x
- Command Injection Vulnerability and Mitigation
- How to use SQLMAP to test a website for SQL Injection vulnerability
- Zombie Processes and their Prevention
- Denial of Service and Prevention
- Path Traversal Attack and Prevention
- Format specifiers in C
- Format specifiers in different Programming Languages
- Difference between %d and %i format specifier in C language
- C program to write an image in PGM format
- C program to print characters without using format specifiers
- C program to invert (making negative) an image content in PGM format
- Print all possible combinations of the string by replacing '$' with any other digit from the string
- Print substring of a given string without using any string function and loop in C
- How to find length of a string without string.h and loop in C?
- std::string::crbegin() and std::string::crend() in C++ with Examples
- C | String | Question 13