Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What does it mean to use a string that was input from the user as a format-control and why is it a security breach?

Tags:

I read this Error Prevention Tip (3.1) in Deitel and Deitel's book, Java: How to Program. I do not understand what it means. I only know that it was talking about the line of code below:

// display the name stored in object myAccount
System.out.printf("Name in object myAccount is:%n%s%n", myAccount.getName());

The paragraph is as follows:

Never use as a format-control a string that was input from the user. When method System.out.printf evaluates the format-control string in its first argument, the method performs tasks based on the conversion specifier(s) in that string. If the format-control string were obtained from the user, a malicious user could supply conversion specifiers that would be executed by System.out.printf, possibly causing a security breach.

like image 732
Maxoud Avatar asked Apr 03 '17 03:04

Maxoud


People also ask

What is format string vulnerabilities in cybersecurity?

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. The format argument has many different specifies which could allow an attacker to leak data if they control the format argument to printf .

How an attacker does control the format string?

If the application uses Format Functions in the source-code, which is able to interpret formatting characters, the attacker could explore the vulnerability by inserting formatting characters in a form of the website.

What do you mean by format string?

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.


1 Answers

Strictly speaking, using a string input by the user for format-control would be like this:

String format=getFromUser(...);
System.out.printf(format, arg1, arg2, arg3...);

This could be really harmful because, apart of the coding injection suggested by @JohnKugelman, I can think of four easy ways in which a malicious user could break security through a format string:

  • The simplest is by entering a wrong mask, so that a WrongFormatConversion would be thrown at runtime:
    @Test
    public void wrongMask()
    {
        String s="january";
        System.out.printf("%)/$#", s);
    }
  • By entering a high argument index, so that a MissingFormatArgumentException would be thrown at runtime:
    @Test
    public void highArgumentIndex()
    {
        String s="january";
        System.out.printf("%1000$s%n", s);
    }
  • By entering a high field width, so that such a huge line would be outputed, that it would be impractical to read:
    @Test
    public void highFieldWidth()
    {
        String s="january";
        System.out.printf("%1000000s%n", s);
    }
  • Idem, but specifying a zero-padding high width for a number argument, so that the padding operation would consume a long time and possibly high memory too (surely because the padding algorithm was not intended to handle big strings, and so, it was not designed to be optimal).
    @Test
    public void highArgumentWidth()
    {
        int n=12;
        System.out.printf("%01000000d%n", n);
    }

This test delayed almost one minute to be executed on my computer. Try with a high enough width and you'll probably get an OutOfMemoryError after several minutes of delay.

(Code injection is easily avoidable through a simple pre-processing of the input string to escap all double-quotes, but these flaws are of semantic nature, so they are harder to find and avoid).

But none of these can be applied to your line, because your format string is hard-coded, not input from user.

Update

To understand how dangerous is to accept a control format string from the final user, you'd better repeat the upper set of tests, but in an interactive mode:

    public static void main(String[] args)
    {
        String format=args[0];
        int n=12;
        System.out.printf(format, n);
    }

Then, imagine yourself as a hacker trying to break this program. Execute it with these proposed values:

  • %)/$#
  • %1000$d
  • %1000000d
  • %01000000d

Conclussion: The format string must be composed by the programmer, not by the final interactive user.

like image 124
Little Santi Avatar answered Sep 23 '22 10:09

Little Santi