4 ms·
There absolutely are some silver bullets. ALL of these buffer overflows in C happen because the C stack grows backward, and old space is after new space. If a
by jblow 11y ago
There absolutely are some silver bullets.
ALL of these buffer overflows in C happen because the C stack grows backward, and old space is after new space.
If anyone have enough of a crap just to standardize a calling convention that went the other way, stack buffer overwrites would ALWAYS go into unused memory. Then security-minded people would switch to this calling convention for secure programs, and many problems would be solved.
(Of course heap problems would still exist but they are much harder to exploit and it is easy to make an allocator that tries to confound heap attacks.)
- gpderetta 11y agoC stack doesn't grow on any specific directions. On some ABIs it grows down, on others it grows up. Both are vulnerable to stack overflow attacks. edit: typo
- JabavuAdams 11y agoHey jblow. I have a tremendous amount of respect for your work, and advocacy. Thanks. Something that I've been wondering -- isn't inventing a new language for game developers fighting yesterday's battle? I've been blown away looking at what Google is doing with C++ indexing, LLVM integration, etc. I'm experimenting with model-based programming. I.e. toying with the idea that I'm not allowed to write any C++ code, only declarative models that generate C++ code. This is part of a larger project to essentially automate myself away / transcend, which may or may not be quackery.
- jblow 11y agoIf it were "yesterday's battle", I would have a good programming language to use in my domain, without having to make one. But I don't. Experimenting with model-based programming or whatever other future programming paradigm is healthy. I think we should do a lot of that, because the way we program hundreds of years from now hopefully doesn't look that much like today. BUT, you have to also be aware that there's a reason why these are future paradigms and not current paradigms, and that people building real programs today need to do something that works today. There is no way we could have built The Witness in any model-based system known today.
- tptacek 11y agoNot really, no. The very first modern stack overflow exploit (Lopatic's NCSA HTTPD) targeted HPPA, where the stack grows up.
- colanderman 11y agoUm, what? char too_small_buffer[256]; function_that_expects_a_big_buffer(too_small_buffer); There's even a paragraph on Wikipedia debunking this idea: https://en.wikipedia.org/wiki/Stack_buffer_overflow#Stacks_that_grow_up https://en.wikipedia.org/wiki/Stack_buffer_overflow#Stacks_t...
- jblow 11y agoWikipedia is wrong. It is not naive. Yes, this does not solve every possible stack overwrite. But look at the number that have actually happened in the field and whether this would have dramatically reduced vulnerability in those actual real-world cases. Most times it would. Most notably, for overwrites happening within the local stack frame, you completely remove the possibility of overwriting the return address. This is a fundamental difference in the level of vulnerability of that kind of code. It's called "reducing the attack surface". Well-known idea. Maybe my post was a bit hyperbolic, but I chalk that up to being so annoyed at this.
- tptacek 11y agoIsn't the test case he just gave you a slightly obscured version of the canonical stack overflow? void dumb_func(char *user_input) { char buf[64]; sprintf(buf, "reformatted: %s", user_input); } Overflows in functions whose activation records precede the buffer are --- obviously, because they necessarily involve hand-rolled copy loops --- rarer than those that don't. Additional fun fact: a few early generations of mid-90s stack overflow exploits didn't even target the activation records at all! I think it's interesting and worthwhile to consider whether stacks growing upwards would have made exploit development meaningfully harder, but I also think the answer to that question is straightforward: no, not really.
- pcwalton 11y ago> ALL of these buffer overflows in C happen because the C stack grows backward, and old space is after new space. This isn't true, as pointed out elsewhere in the thread. In fact, it even looks likely that this specific bug is still exploitable under your proposal. Here is the bug: https://github.com/lattera/glibc/blob/a2f34833b1042d5d8eeb263b4cf4caaea138c4ad/resolv/res_send.c#L1236 https://github.com/lattera/glibc/blob/a2f34833b1042d5d8eeb26... The buffer overflow occurs here: https://github.com/lattera/glibc/blob/a2f34833b1042d5d8eeb263b4cf4caaea138c4ad/resolv/res_send.c#L991 https://github.com/lattera/glibc/blob/a2f34833b1042d5d8eeb26... Notice that the buffer overflow occurs not in __libc_res_nquery itself but in one of the functions it calls, send_dg. From a quick glance it looks like the call chain is __libc_res_nquery -> __libc_res_nsend -> send_dg. Because the buffer is alloca'd in __libc_res_nquery but overwritten in a later call frame, an attacker should be able to overwrite either the return address of send_dg or __libc_res_nsend even if stacks grow the other way. So your proposed fix doesn't address this issue.