6

I am learning about heap overflow attacks and my textbook provides the following vulnerable C code:

/* record type to allocate on heap */
typedef struct chunk {
    char inp[64];            /* vulnerable input buffer */
    void (*process)(char *); /* pointer to function to process inp */
} chunk_t;

void showlen(char *buf)
{
    int len;
    len = strlen(buf);
    printf("buffer5 read %d chars\n", len);
}

int main(int argc, char *argv[])
{
    chunk_t *next;

    setbuf(stdin, NULL);
    next = malloc(sizeof(chunk_t));
    next->process = showlen;
    printf("Enter value: ");
    gets(next->inp);
    next->process(next->inp);
    printf("buffer5 done\n");
}

However, the textbook doesn't explain how one would fix this vulnerability. If anyone could please explain the vulnerability and a way(s) to fix it that would be great. (Part of the problem is that I am coming from Java, not C)

tam5
  • 3,197
  • 5
  • 24
  • 45
  • 4
    your `inp` is 64 bytes. so input 65 bytes and you've overflow... – Marc B May 20 '15 at 18:51
  • 4
    And to fix it, [use fgets()](http://stackoverflow.com/questions/1694036/why-is-the-gets-function-so-dangerous-that-it-should-not-be-used) – Andreas Fester May 20 '15 at 18:53
  • @orangesoda which book is this? –  May 20 '15 at 18:54
  • For example, by entering a carefully crafted byte sequence, most likely non-ascii, which is 68 byte long, you could overwrite the function pointer with a known address of a different function which then gets executed (in a larger program, say, an office package). But that is not directly heap related, it would equally apply to a struct on the stack. In order to do something heap specific you would target data which you know is close on the heap, or perhaps manipulate the book keeping information stored between the memory chunks (but I am not sure how that would do anything but crash the prog). – Peter - Reinstate Monica May 20 '15 at 18:55
  • Take a look at [THIS](http://stackoverflow.com/questions/3302255/c-scanf-vs-gets-vs-fgets) – LPs May 20 '15 at 18:56
  • the textbook is Computer Security Principles and Practice (2nd ed) by Stallings – tam5 May 20 '15 at 19:25

4 Answers4

5

The code uses gets, which is infamous for its potential security problem: there's no way to specify the length of the buffer you pass to it, it'll just keep reading from stdin until it encounters \n or EOF. It may therefore overflow your buffer and write to memory outside of it, and then bad things will happen - it could crash, it could keep running, it could start playing porn.

To fix this, you should use fgets instead.

user4520
  • 3,401
  • 1
  • 27
  • 50
5

The problem is that gets() will keep reading into the buffer until it reads a newline or reaches EOF. It doesn't know the size of the buffer, so it doesn't know that it should stop when it hits its limit. If the line is 64 bytes or longer, this will go outside the buffer, and overwrite process. If the user entering the input knows about this, he can type just the right characters at position 64 to replace the function pointer with a pointer to some other function that he wants to make the program call instead.

The fix is to use a function other than gets(), so you can specify a limit on the amount of input that will be read. Instead of

gets(next->inp);

you can use:

fgets(next->inp, sizeof(next->inp), stdin);

The second argument to fgets() tells it to write at most 64 bytes into next->inp. So it will read at most 63 bytes from stdin (it needs to allow a byte for the null string terminator).

Barmar
  • 741,623
  • 53
  • 500
  • 612
1

You can fill up next with more than 64 bytes you will by setting the address for process. Thereby enable one to insert whatever address one wishes. The address could be a pointer to any function.

To fix simple ensure that only 63 bytes (one for null) is read into the array inp - use fgets

Ed Heal
  • 59,252
  • 17
  • 87
  • 127
0

The function gets does not limit the amount of text that comes from stdin. If more than 63 chars come from stdin, there will be an overflow. The gets discards the LF char, that would be an [Enter] key, but it adds a null char at the end, thus the 63 chars limit.

If the value at inp is filled with 64 non-null chars, as it can be directly accessed, the showlen function will trigger an access violation, as strlen will search for the null-char beyond inp to determine its size.

Using fgets would be a good fix to the first problem but it will also add a LF char and the null, so the new limit of readable text would be 62.

For the second, just take care of what is written on inp.

fbiazi
  • 387
  • 2
  • 10