Since buffer overflows always let an evil hacker write outside the buffer and overwrite the return pointer to a shellcode the evil hacker can place, does it mean that successful exploitation of a stack buffer overflow always means the ability to invoke a shell if done the right way? At least in theory, if you assume that DEP and ASLR is not in place.
-
9Don't forget that the attacker might not want *arbitrary* code to run; they might merely want to *choose which existing code runs*, or even *not run*. The ability to choosing to, say, not execute a security check when one is warranted is an attack vector. – Eric Lippert Nov 27 '19 at 20:28
3 Answers
No, a buffer overflow might:
- Be against a buffer on the heap not the stack. This might still lead to code execution but will be much more complicated to exploit.
- Be limited in size, so not able to overwrite return pointers. (e.g. be able to only write 1 byte beyond the buffer)
- Be restricted in which bytes can be written, preventing suitable pointers to be written.
- Overwrite stack cookies, which are detected before the return address is used. Unless the cookie is leaked, the exploit would crash the process the vast majority of the time, rather than leading to code execution.
- Be on a stack growing upwards, so not be able to overwrite return addresses. An exploit might still be able to overwrite other local variables, or the buffer might be passed to another function, but wouldn't lead to code execution as reliably as downwards stacks.
Some of these might still lead to code execution, but other instances might be impossible to exploit.
However once you've found where a buffer overflow is happening it's usually much easier to fix it, than to prove it can't be exploited.
![](../../users/profiles/215.webp)
- 1,939
- 14
- 9
-
19It's worth noting that all these properties *might* result in a buffer overflow that's not exploitable. There have been many remote code executions based on heap overflows, there are techniques that bypass stack canaries, bad bytes and size limitations, an overflow on an upwards-growing stack might be able to overwrite local variables in a manner that somehow enables RCE, etc. So a buffer overflow should be viewed as a potential vulnerability even if it seems not exploitable at the first glance. – Peteris Nov 27 '19 at 00:50
-
1Just a side note - Buffer Overflows may/will often differ in behavior on different platforms (x86_64 vs x86, x86 vs arm, etc), on different compilers (gcc/clang/intel/proprietary), or even with different compiler flags / optimization levels. I recently had some pointer arithmetic incorrect which caused a random 8 bytes in the stack to zero out. I only found it because I was testing with different flags and it happened to exactly align with a return address pointer and null it out. – Tyzoid Nov 27 '19 at 00:59
-
1I don't get the first point. Heap-based buffer overflows are a common vector for remote code execution. – voices Nov 27 '19 at 03:29
-
30chicken is a common vector for food poisoning, but not every chicken causes food poisoning. – coteyr Nov 27 '19 at 03:31
-
Thanks for the answer and comments. Insightful. I had never thought about the 2nd point - limited in size. – Sreeraj Nov 27 '19 at 04:38
-
2"Be limited in size, so not able to overwrite return pointers". Ah you'd think you couldn't do anything with that, but alas that's not true. I remember a fascinating linux code execution exploit where only a *single byte* on the stack could be overwritten at a time. – Voo Nov 27 '19 at 13:59
-
4
-
and sometimes you write to an unallocated area and get an unhandled segfault terminating the whole application so the best you can do is a DoS – user1067003 Nov 27 '19 at 19:52
-
3Writing even a single NUL byte off the end of a buffer can still be quite exploitable and is a very common off-by-one error when dealing with strings; see https://googleprojectzero.blogspot.com/2014/08/the-poisoned-nul-byte-2014-edition.html for example. While, yes, not all buffer overflows are exploitable, attackers can be remarkably clever. – nneonneo Nov 27 '19 at 20:51
-
I just wanted to add, that most, but not all languages use the same stack for data and return addresses (see Forth or Factor, or the Inferno VM iirc). That hinders severely some kind of attacks. – fede s. Nov 28 '19 at 02:07
-
@Tyzoid pointer math is another can of problems :-) i remember being called to a senior devel to help him find the mysterious problem. Most part of time was spent persuading him to stop telling me what to do, because despite all his experience it was he asking me for help, this he should want me to apply my (even if absurd) methods, rather than just doing verbatim what he already did. After i did it and was given carte blanche - it turned out that converting pre-Unicode code Unicode-aware sources were incomplete, and pointer math in one fn zeroed a byte in local var 6 fn calls above. – Arioch Dec 02 '19 at 15:09
-
Just an almost random "precision" strike with a single zero byte (and frankly, totally redundant "i don't trust API so i will do it myseld" type of defense, made wrong) into process memory. Before due to changed compilation flags it happenned to screw a local var upon which code yet-to-be-executed depended critically - this bomb was never detected :-D Delicious case in a sense. But still, pointer math and buffer overrun is different problems, albeit sometimes related. – Arioch Dec 02 '19 at 15:12
Douglas gives a correct answer. Not all buffer overflows give code execution. However, I felt it was missing a very important caution.
Even if a buffer overflow does not allow arbitrary code execution, that does not mean that it is safe.
A write buffer overflow lets you write to data that you are not supposed to. That data being a function address is just a special case. For example, suppose I have a user struct that has fields for name and privilege. It is easy to imagine how setting my name to "JosiahhasaverylongnameAdmin" could exploit a serious vulnerability, without any arbitrary code execution.
For another real world example, if you remember Heartbleed, that is a buffer overflow. It is just a read overflow rather than a write overflow. No chance of a code execution there, but a devastating breach of confidentiality even so.
![](../../users/profiles/179255.webp)
- 1,818
- 9
- 14
The simple answer is no, not all buffer overflows are guaranteed to lead to code execution. The overflow could be too small to overwrite pointers/values needed, unable to control the overflowing part to overwrite things, or maybe too big which could kill stack cookies/canaries, etc.
![](../../users/profiles/6253.webp)
- 123,438
- 55
- 284
- 319
![](../../users/profiles/221915.webp)
- 21
- 2