In the late 1990s, security researchers began noticing a peculiar class of bug in C programs. The culprit was a single misuse of one of the most common functions in the language: printf.
The safe way to print a user-supplied string is:
printf("%s", user_input);
The dangerous way — seen in real production code — is:
printf(user_input); /* user controls the format */
Those two lines look almost identical, but their consequences could not be more different. In the safe version, printf treats user_input as pure data. In the dangerous version, printf treats it as a format string — a program that drives how printf reads arguments off the call stack.
If an attacker controls that string, they control what printf does: they can read arbitrary values from the stack by inserting %x or %p specifiers, and — using the special %n specifier — they can write an arbitrary value to an arbitrary address. A single log call becomes a full arbitrary read/write primitive.
The fix is trivially simple. The vulnerability has been known since 1999 (Tymm Twillman and the BIND exploit) and is classified as CWE-134. Yet it kept appearing in shipping software for decades, because a mistake that looks this innocent is easy to make and easy to miss in code review.
Comments
Loading comments...