-4

Assume I have the following program:

#include  <stdio.h>
#include  <string.h>
#include  <stdlib.h>

int main (int argc, char **argv)
{
    char buf [100];
    snprintf ( buf, sizeof buf, argv [1] ) ;
    buf [ sizeof buf -1 ] = 0;
    printf ( "%s \n" , buf ) ;
    return 0 ;
}

If I compile and run it:

gcc test.c -o test
./test %p%p%p
(nil)0x4006d00x7f67e05b7ab0

I can see the stack values, meaning that it is affected by the format string vulnerability.

Now, let's slightly modify the above code:

#include  <stdio.h>
#include  <string.h>
#include  <stdlib.h>

int main (int argc, char **argv)
{
    char buf [100];
    printf ( "%s \n" , argv[1] ) ;
    return 0 ;
}

If I re-compile it and re-run it, the vulnerability is gone:

gcc test.c -o test
./test %p%p%p
%p%p%p

Why is this happening, what changed from the first example?

Also, in the first example, shouldn't the %s in the printf consider buf as a string? Why is such code still affected by the format string vulnerability?

badnack
  • 737
  • 1
  • 11
  • 20

3 Answers3

1

If you want the output of the first snippet to match the second one, then simply use the same formatting specifier you used for printf, i.e.:

snprintf ( buf, sizeof buf, "%s", argv [1] );
                            ^^^^

In this case the argv[1] string is not treated as a formatting template for some other arguments, and you simply get %p%p%p written to buf.

Did you perhaps intend to copy the string instead? I am asking because snprintf automatically terminates the buffer, you don't need to set the null terminator manually (and this is usually done when using strncpy):

strncpy ( buf, argv [1], sizeof buf );
buf [ sizeof buf - 1 ] = 0;
vgru
  • 49,838
  • 16
  • 120
  • 201
1

You're asking about format string vulnerability. Format string vulnerability occurs whenever an user-supplied string is used as the format to any *scanf or *printf function.

In the first fragment the vulnerability is with snprintf. In the second fragment your printf has the format string "%s". It was not supplied by the user, therefore no vulnerability. Try

printf(buf);
0
snprintf ( buf, sizeof buf, argv [1] ) ;

you have just abused snprintf as you have not passed the parameters to match your format string %p%p%p.

So you just have an UB.

You should for example (with the same format string)

snprintf ( buf, sizeof buf, argv [1], argv[0], buff, "Hello, Show where string literals are stored" ) ;
0___________
  • 60,014
  • 4
  • 34
  • 74