Search code examples
csecurityiolimitbuffer-overflow

Buffer overflow causes extra characters to be executed by terminal as shell command


I'm getting myself initiated to buffer overflow risks, especially when it comes to low-level C library input/output functions and trying to understand how it relates to memory exploitation and code injection.

I am considering the following chunk of code and the weird behavior its execution gives :

int main ()
{
     char buffer[10];

     int r = read (STDIN_FILENO, buffer, 14);
     puts(buffer);

     return EXIT_SUCCESS;
}

Now when given the following 17-size input

Hello, World !pwd

I get the following output :

Hello, Wor
> pwd
/media/...<current working directory path>

As shown by the output, the 3 extra characters (here intentionally pwd for demonstration purposes) - that were out of bounds for the specified limit of the read function - got taken over by the terminal and executed as a shell command.

What causes this behavior, from a low-level perspective ?
Can that be used to carry out a code injection ?


Solution

  • As shown by the output, the 3 extra characters (here intentionally pwd for demonstration purposes) - that were out of bounds for the specified limit of the read function - got taken over by the terminal and executed as a shell command.

    How is that possible, from a low-level perspective ?

    As @ChrisTurner observed first in comments, there is nothing surprising about the pwd being interpreted as input to the shell from which you launched the program, after the program exits. Although each program has its own handle on it, they are reading from the same file, probably connected to a terminal.

    Your program helps, though, by using a low-level I/O function, read, which will not consume any more bytes from that file than you request. Contrast stream-based functions such as fread, fgets, and scanf, which most often perform buffered reads (this is a characteristic of the stream they operate upon, not the functions themselves). In your particular case, any of these would consume all the input up to and including the first newline.

    You do have a potential buffer overflow in your program, but it is a red herring. The behavior you describe does depend on read reading the full 14 bytes requested, which it is not guaranteed to do, but which for all intents and purposes you can rely upon it to do when the standard input is connected to a terminal. It having done so, your program will indeed exhibit undefined behavior, but the manifestation of that UB is likely to be constrained to the program's output (notice how it's truncated?) or even to be invisible to you. It is not responsible for "pwd" being read as input by the parent shell.

    What about non-console program execution, like GUI apps, web apps, and so on ... How would they behave in this case ? And most importantly, what security issues does this situation raise, in terms of binary exploitation and code injection, and maybe other security aspects that I'm not aware of ?

    Only a person or program that has direct access anyway to the program's parent shell, if any, or to that shell's controlling terminal can feed input to it. You have not demonstrated otherwise. There is no particular security consideration to discuss.