Monday, March 7, 2011

Protection from Format String Vulnerability

What exactly is a "Format String Vulnerability" in a Windows System, how does it work, and how can I protect against it?

From stackoverflow
  • Okay, assuming you're serious and want to know because you use C and want to avoid making the mistake in your own code, I suggest a quick Google search:

    http://www.google.co.uk/search?q=Format+string+attack

  • In this pseudo code the user enters some characters to be printed, like "hello"

    string s=getUserInput();
    write(s)
    

    That works as intended. But since the write can format strings, for example

    int i=getUnits();
    write("%02d units",i);
    

    outputs: "03 units". What about if the user in the first place wrote "%02d"... since there is no parameters on the stack, something else will be fetched. What that is, and if that is a problem or not depends on the program.

    An easy fix is to tell the program to output a string:

    write("%s",s);
    

    or use another method that don't try to format the string:

    output(s);
    

    a link to wikipedia with more info.

  • A format string attack, at its simplest is this:

    char buffer[128];
    gets(buffer);
    printf(buffer);
    

    There's a buffer overflow vulnerability in there as well, but the point is this: you're passing untrusted data (from the user) to printf (or one of its cousins) that uses that argument as a format string.

    That is: if the user types in "%s", you've got an information-disclosure vulnerability, because printf will treat the user input as a format string, and will attempt to print the next thing on the stack as a string. Since you didn't pass any other arguments to printf, it'll display something arbitrary.

    If the user types in "%n", you've got a potential elevation of privilege attack (at least a denial of service attack), because %n causes printf to write the number of characters printed so far to the next location on the stack. Since you didn't give it a place to put this value, it'll write to somewhere arbitrary.

    This is all bad, and is one reason why you should be extremely careful when using printf and cousins.

    What you should do is this:

    printf("%s", buffer);
    

    This means that the user's input is never treated as a format string, so you're safe from that particular attack vector.

    In Visual C++ 2008, you can use the __Format_string annotation to tell it to validate the arguments to printf. %n is disallowed by default. In GCC, you can use __attribute__(__printf__) for the same thing.

0 comments:

Post a Comment