Open In App

Format String Vulnerability and Prevention with Example

Last Updated : 07 Mar, 2024
Improve
Improve
Like Article
Like
Save
Share
Report

A format string is an ASCII string that contains text and format parameters.

Example:

// 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:

C




// A simple C program with format
// string vulnerability
#include<stdio.h>
 
int main(int argc, char** argv)
{
    char buffer[100];
    strncpy(buffer, argv[1], 100);
 
    // We are passing command line
    // argument to printf
    printf(buffer);
 
    return 0;
}


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


Like Article
Suggest improvement
Previous
Next
Share your thoughts in the comments

Similar Reads