16

According to an article I just read, the functions printf and strcpy are considered security vulnerabilities due to Buffer overflows. I understand how strcpy is vulnerable, but could someone possibly explain how/if printf is really vulnerable, or I am just understanding it wrong.

Here is the article: https://www.digitalbond.com/blog/2012/09/06/100000-vulnerabilities/#more-11658

The specific snippet is :

The vendor had mechanically searched the source code and found some 50,000-odd uses of buffer-overflow-capable C library functions such as “strcpy()” and “printf().”

Thanks!

4
  • 3
    If you are interested in this topics I suggest you to read Hacking: The Art of Exploitation by Jon Erickson. Chapter three contains a working exploit using the format string vulnerability of printf.
    – Bakuriu
    Oct 9, 2013 at 20:07
  • Sure I understand the format string vulnerabilities, from what I've read at least. However, I was under the impression that the function itself was somehow exploitable (even if it was used as intended).
    – DarkMantis
    Oct 9, 2013 at 20:58
  • 5
    Seen another way, C/C++ itself is a buffer overflow vulnerability. All that direct toying with memory... Oct 10, 2013 at 2:05
  • I have faced similar situation for integer buffer where I can't access main() function in C. I am searching for an answer (stackoverflow.com/questions/61715941/…) May 10, 2020 at 17:28

4 Answers 4

24

It is possible to have issues with printf(), by using as format string a user-provided argument, i.e. printf(arg) instead of printf("%s", arg). I have seen it done way too often. Since the caller did not push extra arguments, a string with some spurious % specifiers can be used to read whatever is on the stack, and with %n some values can be written to memory (%n means: "the next argument is an int *; go write there the number of characters emitted so far).

However, I find it more plausible that the article you quote contains a simple typographical mistake, and really means sprintf(), not printf().

(I could also argue that apart from gets(), there is no inherently vulnerable C function; only functions which need to be used with care. The so-called "safe" replacements like snprintf() don't actually solve the problem; they hide it by replacing a buffer overflow with a silent truncation, which is less noisy but not necessarily better.)

2
  • 1
    I've even seen argued (with some merit) that gets is not inherently vulnerable either. For example, if a program calls gets to read back data that it wrote, it may be guaranteed that the data fits in the buffer. For a file this is not robust but may be correct; for a self-pipe it could even be robust. Oct 9, 2013 at 18:37
  • 3
    Slightly off-topic, but I do not agree at all with your comment regarding snprintf: it is difficult to use sprintf in a secure manner (and practically impossible if you use a %s format specifier), but snprintf, when used correctly, is safe: when snprintf truncates the input, because its size exceeds the buffer, it is not silent but tells you by giving a return value equal to the buffer size. Oct 10, 2013 at 11:10
6

In addition to the answer by @Tom, I would also like to guide you to the OWASP code review guidelines, where some issues on using printf() are highlighted and this answer to a similar question on cs.stackexchange website.

0
4

Here is an example that shows how this overflow can help you. Imagine you don't have access to the private members (pwd for example) so printf will help you see the content of this variable

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

struct SecureLogin{
    SecureLogin(const char * login_)
    {
        strcpy(login,login_);
        strcpy(pwd,"ijk");//the user does not see this part of the source code as it is in a DLL
    }
    char login[8];
private:
    char pwd[8];

};


int main() {
    // your code goes here
    SecureLogin log("abc");
    printf("Pwd = %s\n",(&log.login[0])+8);
    // Pass a string address which is the base address of the login
    // field, but add 8 bytes, which skips onto the pwd field (we know
    // login is 8 bytes)
    return 0;
}

Output:

Pwd = ijk

2

Some printf directives (ie; %n) have side effects to addresses found on the stack, so print directives can be dangerous, even if the explicit output is implemented correctly.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .