Skip to content

Instantly share code, notes, and snippets.

@wheresalice
Last active May 6, 2019 17:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wheresalice/d3ff72e8e06a76f6055092b43c262da2 to your computer and use it in GitHub Desktop.
Save wheresalice/d3ff72e8e06a76f6055092b43c262da2 to your computer and use it in GitHub Desktop.
unistd read() overflow

So here's a weird thing.

From the man page of unistd's read():

read() attempts to read up to count bytes from file descriptor fd into the buffer starting at buf

The file descriptor here can be STDIN, and this can be used as a way of reading user input. But weird things start to happen when you provide more than count bytes input on STDIN.

Build the included C file and then run it.

It expects a two-byte input, so give it aa and everything appears normal.

Give it aals -lh however, and you'll see ls -lh executed on the commandline (this doesn't always work piped in, so type/paste it in).

It's not the C code that's executing this, it's your shell.

To make things more interesting you can include non-printing characters in your input, to make it look like you are providing less bytes than count.

But surely nobody actually does this right? Surely nobody would actually use this method of reading an input? Actually, they do. And sometimes in quite sensitive pieces of code. But I'll leave discovering those as an exercise to the reader.

test:
gcc test.c -o test
#include <unistd.h>
#include <stdio.h>
int main() {
char buffer[10];
int rbytes = 0;
printf("Enter two random characters followed by a command (eg. 'aals -lh' without the quotes)\n");
printf("The command will be executed, because read() only accepts the first two characters, and the rest overflow\n");
rbytes = read(STDIN_FILENO, buffer, 2);
printf("\nReceived: ");
printf(buffer);
printf("\nLength: ");
printf("%d", rbytes);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment