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 bySystem.out.printf
, possibly causing a security breach.
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 .
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.
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.
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:
WrongFormatConversion
would be thrown at runtime:@Test public void wrongMask() { String s="january"; System.out.printf("%)/$#", s); }
MissingFormatArgumentException
would be thrown at runtime:@Test public void highArgumentIndex() { String s="january"; System.out.printf("%1000$s%n", s); }
@Test public void highFieldWidth() { String s="january"; System.out.printf("%1000000s%n", s); }
@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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With