Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sprintf function's buffer overflow?

{     
    char buf[8];
    sprintf(buf,"AAAA%3s","XXXXXXXX");
    printf("%s\n",buf);
}

What will happen?

The buffer has 8 characters worth of space and only 3 free characters left, however, "XXXXXXXX" is 8 characters long.

I did a test with Visual Studio 2008 on Windows 7. As a result, the program printed AAAXXXXXXX, and a run-time error happened.

like image 999
remainn Avatar asked Nov 26 '10 03:11

remainn


People also ask

Why is sprintf unsafe?

Warning: The sprintf function can be dangerous because it can potentially output more characters than can fit in the allocation size of the string s . Remember that the field width given in a conversion specification is only a minimum value. To avoid this problem, you can use snprintf or asprintf , described below.

Why should we use Snprintf () instead of sprintf ()?

Snprintf is safer to use because characters are not omitted and it is stored in the buffer for later usage. Both sprintf and snprintf store the string and produces the output as needed by user.

How can sprintf fail?

In UNIX, it can fail: EILSEQ A wide-character code that does not correspond to a valid character has been detected. EINVAL There are insufficient arguments. EILSEQ has already been mentioned.

Will sprintf overwrite?

You're overwriting the content of the file every time because you're using mode w to write the file, which re-writes the file from the beginning. If you simply want to append your data to the end of the file, you should use mode a like this: fptr=fopen("program.


2 Answers

It makes a lot of sense to consider what happens in your and, more importantly, similar, cases. As other posters have noted, it invokes UB. That's probably true. However, the world does not stop simply because someone did not define what exactly should happen next. And what physically happens next, may well be a major security hole.

If your string XXX... comes from uncontrolled sources, you are very close to generating a buffer overflow vulnerability.

(1) Your stack typically "grows" backwards, i.e. the smaller the addresses, the more the stack is filled.

(2) Strings expect the characters belonging to that string to be stored so that character n+1 is stored after character n.

(3) When you call a function, the return address, i.e. the address of the instruction that is to be executed after the function returns, is pushed to the stack (among other things, typically).

Now consider a stack frame of your function.

|----------------|
| buf [size 8]   |
|----------------|
| (func args)    |
|----------------|
| (other stuff)  |
|----------------|
| return address |
|----------------|

By finding out what exactly the offset between buf and the return address on the stack is, a malicious user may manipulate input to your application in a way that the XXX... string contains an address of the attacker's choosing at just the point where the uncontrolled sprintf function will overwrite the return address on the stack. (NB: Better use snprintf if it's available to you). Thereby the attacker mounted a buffer overflow attack. He might use something like the NOP sled technique to have your application start a shell for him. If you were writing an application that ran under a privileged user account, you'd just have provided an attacker with a first-grade entry to your costumer's system, an ACE hole, if you will.

Update

The run-time error you experience may well be due to an overwritten return address. Since you filled it with, basically, gargabe, the address the CPU jumped to did probably contain byte sequences that, interpreted as program text, cause an invalid memory access (or the address itself was already bad).

It should be noted that some compilers can help against these kinds of errors. GCC, for example, has the -fstack-protector. I'm not familiar with how good those features are.

like image 122
dennycrane Avatar answered Oct 01 '22 08:10

dennycrane


The function sprintf() will write past the array as it writes in the string, and therefore invokes undefined behavior. Looking at your code, it'll probably write over the first few bytes of whatever happens to be next on the stack, or cause a runtime error, but that behavior is not guaranteed.

Undefined behavior quite literally means anything can happen. That means your code may do nothing wrong, cause a runtime error, or cause your computer to explode, win the lottery, make unicorns appear in your backyard, raise Hitler from the dead or assassinate the President of the United States. Please don't do this.

Always ensure that your character buffer has enough space to hold whatever you are sprintf()-ing into it plus an extra character for the null terminator. In general, don't try to mess around with memory spaces that are not yours.

like image 32
In silico Avatar answered Oct 01 '22 08:10

In silico