5

I am trying to learn about format string bugs and I found the gcc option -Wformat-security to raise a warning when a potential format string bug is found. I would like to know if there is a way to evade this check and still have a format bug problem. For example:

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

int main (int argc, char * argv[])
{
  char outbuf[32];
  char buffer[32];

  if (argc < 2)
  {
     fprintf (stderr, "Error missing argument!\n");
     exit (EXIT_FAILURE);
  }

  snprintf (buffer, 28, "ERR Wrong command: %8s", argv[1]);
  sprintf (outbuf, buffer);

  perror(outbuf);

  return EXIT_SUCCESS;
}

When compiled in 32bits, it will crash on %21d input (not on %20d, but on any number higher than 20). But, the -Wformat-security will detect it and raise a warning as follow:

$> gcc -m32 -Wall -Wextra -Wformat-security -std=c99 -o fstring fstring.c 
fstring.c: In function ‘main’:
fstring.c:19:3: warning: format not a string literal and no format arguments [-Wformat-security]
   sprintf (outbuf, buffer);
   ^

So, is there a way to hide the bug from the warning and still have a possible exploitation ?

Edit: My point is not to correct the bug, but to understand what kind of format string bugs are not captured by this warning. It helps to understand where to look if no warning is raised but potential format string bugs are present.

3
  • -Wxxx flags only affects the warnings that are shown, it does not change the code. What is your problem?
    – Lekensteyn
    Nov 11, 2013 at 22:44
  • @Lekensteyn : He want to hide the bug from the warning! Nov 11, 2013 at 23:20
  • @Lekensteyn: Yes, this is as Sajjad Pourali said.
    – perror
    Nov 12, 2013 at 0:08

2 Answers 2

6

You must keep secure format of the function and with using to junk arguments bypass format-security.
for example printf(var); is 100% unsafe format ! and compiler able to detect it, but printf(var1,var2) (it can be safe and also dangerous) ! the compiler is not smart enough to detect .
You can use a code like it printf(argv[1],"junk");

For Example

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

int main (int argc, char * argv[])
{
  printf (argv[1],argc);
  //              ^^^^---------> Junk :)
  return EXIT_SUCCESS;
}
/*
sajjad@xxx:~$ gcc -m32 -Wall -Wextra -Wformat-security -std=c99 a.c 
sajjad@xxx:~$ ./a.out %n%n%n
Bus error: 10
sajjad@xxx:~$ ./a.out %s%s%s
Bus error: 10
sajjad@xxx:~$ ./a.out %x%x%x
bffcfb242bffcfb88sajjad@xxx:~$ ./a.out %d%d%d
-10747629722-1074762872sajjad@xxx:~$ ./a.out %s
???|???sajjad@xxx:~$
/*

/*

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

int main (int argc, char * argv[])
{
  char outbuf[32];
  char buffer[32];

  if (argc < 2)
  {
     fprintf (stderr, "Error missing argument!\n");
     exit (EXIT_FAILURE);
  }

  snprintf (buffer, 28, "ERR Wrong command: %8s", argv[1]);
  sprintf (outbuf,buffer, "junk");
  //                      ^^^^^^---------> Junk :)
  perror(outbuf);

  return EXIT_SUCCESS;
}

*/
1
  • If I understand it well, even only one argument to the format string function will allow to disable the check even if the vulnerability is still here. Thanks for this example code !
    – perror
    Nov 12, 2013 at 0:12
1

Invoking through a function pointer is another way to evade -Werror=format-security

The first example below triggers the format-security error while the second does not, but I am not sure why this works.

1st example (format-security error triggered):

char * format = "Hello World\n";
printf(format);

2nd example (format-security error bypassed):

char * format = "Hello World\n";
int (*alias)(const char *, ...) = printf;
alias(format);
0

You must log in to answer this question.

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