# Testing for Format String Injection

|ID          |
|------------|
|WSTG-INPV-13|

## Summary

A format string is a null-terminated character sequence that also contains conversion specifiers interpreted or converted at runtime. If server-side code [concatenates a user's input with a format string](https://www.netsparker.com/blog/web-security/string-concatenation-format-string-vulnerabilities/), an attacker can append additional conversion specifiers to cause a runtime error, information disclosure, or buffer overflow.

The worst case for format strings vulnerabilities occur in languages that don't check arguments and also include a `%n` specifier that writes to memory. These functions, if exploited by an attacker modifying a format string, could cause [information disclosure and code execution](https://www.veracode.com/security/format-string):

- C and C++ [printf](https://en.cppreference.com/w/c/io/fprintf) and similar methods fprintf, sprintf, snprintf
- Perl [printf](https://perldoc.perl.org/functions/printf.html) and sprintf

These format string functions cannot write to memory, but attackers can still cause information disclosure by changing format strings to output values the developers did not intend to send:

- Python 2.6 and 2.7 [str.format](https://docs.python.org/2/library/string.html) and Python 3 unicode [str.format](https://docs.python.org/3/library/stdtypes.html#str.format) can be modified by injecting strings that can point to [other variables](https://lucumr.pocoo.org/2016/12/29/careful-with-str-format/) in memory

The following format string functions can cause runtime errors if the attacker adds conversion specifiers:

- Java [String.format](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/String.html#format%28java.util.Locale%2Cjava.lang.String%2Cjava.lang.Object...%29) and [PrintStream.format](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/io/PrintStream.html#format%2528java.util.Locale%252Cjava.lang.String%252Cjava.lang.Object...%2529)
- PHP [printf](https://www.php.net/manual/es/function.printf.php)

The code pattern that causes a format string vulnerability is a call to a string format function that contains unsanitized user input. The following example shows how a debug `printf` could make a program vulnerable:

The example in C:

```c
char *userName = /* input from user controlled field */;

printf("DEBUG Current user: ");
// Vulnerable debugging code
printf(userName);
```

The example in Java:

```java
final String userName = /* input from user controlled field */;

System.out.printf("DEBUG Current user: ");
// Vulnerable code:
System.out.printf(userName);
```

In this particular example, if the attacker set their `userName` to have one or more conversion specifiers, there would be unwanted behavior. The C example would [print out memory contents](https://www.defcon.org/images/defcon-18/dc-18-presentations/Haas/DEFCON-18-Haas-Adv-Format-String-Attacks.pdf) if `userName` contained `%p%p%p%p%p`, and it can corrupt memory contents if there is a `%n` in the string. In the Java example, a `username` containing any specifier that needs an input (including `%x` or `%s`) would cause the program to crash with `IllegalFormatException`. Although the examples are still subject to other problems, the vulnerability can be fixed by printf arguments of `printf("DEBUG Current user: %s", userName)`.

## Test Objectives

- Assess whether injecting format string conversion specifiers into user-controlled fields causes undesired behavior from the application.

## How to Test

Tests include analysis of the code and injecting conversion specifiers as user input to the application under test.

### Static Analysis

Static analysis tools can find format string vulnerabilities in either the code or in binaries. Examples of tools include:

- C and C++: [Flawfinder](https://dwheeler.com/flawfinder/)
- Java: FindSecurityBugs rule [FORMAT_STRING_MANIPULATION](https://find-sec-bugs.github.io/bugs.htm#FORMAT_STRING_MANIPULATION)
- PHP: String formatter Analyzer in [phpsa](https://github.com/ovr/phpsa/blob/master/docs/05_Analyzers.md#function_string_formater)

### Manual Code Inspection

Static analysis may miss more subtle cases including format strings generated by complex code. To look for vulnerabilities manually in a codebase, a tester can look for all calls in the codebase that accept a format string and trace back to make sure untrusted input cannot change the format string.

### Conversion Specifier Injection

Testers can check at the unit test or full system test level by sending conversion specifiers in any string input. [Fuzz](https://owasp.org/www-community/Fuzzing) the program using all of the conversion specifiers for all languages the system under test uses. See the [OWASP Format string attack](https://owasp.org/www-community/attacks/Format_string_attack) page for possible inputs to use. If the test fails, the program will crash or display an unexpected output. If the test passes, the attempt to send a conversion specifier should be blocked, or the string should go through the system with no issues as with any other valid input.

The examples in the following subsections have a URL of this form:

`https://vulnerable_host/userinfo?username=x`

- The user-controlled value is `x` (for the `username` parameter).

#### Manual Injection

Testers can perform a manual test using a web browser or other web API debugging tools. Browse to the web application or site such that the query has conversion specifiers. Note that most conversion specifiers need [encoding](https://tools.ietf.org/html/rfc3986#section-2.1) if sent inside a URL because they contain special characters including `%` and `{`. The test can introduce a string of specifiers `%s%s%s%n` by browsing with the following URL:

`https://vulnerable_host/userinfo?username=%25s%25s%25s%25n`

If the web site is vulnerable, the browser or tool should receive an error, which may include a timeout or an HTTP return code 500.

The Java code returns the error

`java.util.MissingFormatArgumentException: Format specifier '%s'`

Depending on the C implementation, the process may crash completely with `Segmentation Fault`.

#### Tool Assisted Fuzzing

Fuzzing tools including [wfuzz](https://github.com/xmendez/wfuzz) can automate injection tests. For wfuzz, start with a text file (fuzz.txt in this example) with one input per line:

fuzz.txt:

```text
alice
%s%s%s%n
%p%p%p%p%p
{event.__init__.__globals__[CONFIG][SECRET_KEY]}
```

The `fuzz.txt` file contains the following:

- A valid input `alice` to verify the application can process a normal input
- Two strings with C-like conversion specifiers
- One Python conversion specifier to attempt to read global variables

To send the fuzzing input file to the web application under test, use the following command:

`wfuzz -c -z file,fuzz.txt,urlencode https://vulnerable_host/userinfo?username=FUZZ`

In the above call, the `urlencode` argument enables the appropriate escaping for the strings and `FUZZ` (with the capital letters) tells the tool where to introduce the inputs.

An example output is as follows

```text
ID           Response   Lines    Word     Chars       Payload
===================================================================

000000002:   500        0 L      5 W      142 Ch      "%25s%25s%25s%25n"
000000003:   500        0 L      5 W      137 Ch      "%25p%25p%25p%25p%25p"
000000004:   200        0 L      1 W      48 Ch       "%7Bevent.__init__.__globals__%5BCONFIG%5D%5BSECRET_KEY%5D%7D"
000000001:   200        0 L      1 W      5 Ch        "alice"
```

The above result validates the application's weakness to the injection of C-like conversion specifiers `%s` and `%p`.
