>Alas, stack smashing is much harder these days. On my stock Ubuntu 12.04 install, there are 3 countermeasures: ... GCC Stack-Smashing Protector (SSP), aka ProPolice: the compiler rearranges the stack layout to make buffer overflows less dangerous and inserts runtime stack integrity checks.
There are certain scenarios that SSP is not used, such as with arrays that are less than 8 items wide if I remember right. You can also bypass SSP if you find a separate memory disclosure vulnerability and learn the stack cookie.
>Therefore, I argue executable space protection is worse than nothing [because ROP attacks can bypass it].
ROP attacks only work if you know what the program's memory space looks like. If you're trying to attack a server and don't know what specific executables it is running are, then the attack becomes ridiculously more difficult. (There are certain scenarios that can be brute-forced through: http://www.scs.stanford.edu/brop/) If there is no executable space protection, then you can do a more straight-forward blind attack by sending your executable payload to the server many times so that the payload is in many places in the server's memory (where it would not be executable if executable space protection were in place), and then repeatedly use an exploit to jump to a random memory space until you get lucky and land in the payload. (Well, this might be less workable on 64-bit systems which have ridiculously large address spaces. You'd probably need to pair this with another vulnerability which disclosed some memory addresses so you had an idea of what ranges to guess in.)
Executable space protection also often prevents not-intentionally-exploited bugs from naturally wreaking too much havoc with the program's executable memory, so that the program crashes fast instead of silently rewriting its own code to fail in mysterious ways later.
>Aside from being high-cost and low-benefit, it segregates code from data.
Separating code from data is a very useful default. Many remote code execution vulnerabilities come from mixing them together accidentally. (See SQL injections and XSS attacks. The equivalent protections to executable space protection against these attacks are prepared statements / parameter binding, and the HTTP Content-Security-Policy header. Use these!) There are ways to opt-out of it when it is actually necessary.
>But worse still are its implications for programmers. Executable space protection interferes with self-modifying code, which is invaluable for just-in-time compiling, and for miraculously breathing new life into ancient calling conventions set in stone.
Programs can already allocate regions of memory with read-write-execute permissions, or switch the permissions of existing memory regions.
>We just saw how trivial it is to stitch together shreds of existing code to do our dirty work. We barely scratched the surface: with just a few gadgets, any computation is possible.
Not so much to disagree, but a suggestion: If you want to do anything more complicated than a syscall or two (an execve call will take down and cannibalize the entire process!), then using rop gadgets to do all of your dirty work is unnecessary pain. A good trick is to use rop gadgets to allocate a memory region with read-write-execute permissions, copy some executable code into it, and then jump into it. (Then you can have that code repair the program's stack, accomplish whatever changes you desired, maybe even patch the program's vulnerability to stop anyone from following you in, and then resume the normal operation of the process.)
> There are certain scenarios that SSP is not used, such as with arrays that are less than 8 items wide if I remember right. You can also bypass SSP if you find a separate memory disclosure vulnerability and learn the stack cookie.
-fstack-protector-strong always does it when there's an array. Many distributions lowered the minimum array size for -fstack-protector to 4 bytes too.
> A good trick is to use rop gadgets to allocate a memory region with read-write-execute permissions, copy some executable code into it, and then jump into it.
Note that this is why PaX's MPROTECT feature exists. It prevents injecting code or bypassing RELRO by default and executables need to be marked with exceptions for stuff like JIT compilation to work.
There are certain scenarios that SSP is not used, such as with arrays that are less than 8 items wide if I remember right. You can also bypass SSP if you find a separate memory disclosure vulnerability and learn the stack cookie.
>Therefore, I argue executable space protection is worse than nothing [because ROP attacks can bypass it].
ROP attacks only work if you know what the program's memory space looks like. If you're trying to attack a server and don't know what specific executables it is running are, then the attack becomes ridiculously more difficult. (There are certain scenarios that can be brute-forced through: http://www.scs.stanford.edu/brop/) If there is no executable space protection, then you can do a more straight-forward blind attack by sending your executable payload to the server many times so that the payload is in many places in the server's memory (where it would not be executable if executable space protection were in place), and then repeatedly use an exploit to jump to a random memory space until you get lucky and land in the payload. (Well, this might be less workable on 64-bit systems which have ridiculously large address spaces. You'd probably need to pair this with another vulnerability which disclosed some memory addresses so you had an idea of what ranges to guess in.)
Executable space protection also often prevents not-intentionally-exploited bugs from naturally wreaking too much havoc with the program's executable memory, so that the program crashes fast instead of silently rewriting its own code to fail in mysterious ways later.
>Aside from being high-cost and low-benefit, it segregates code from data.
Separating code from data is a very useful default. Many remote code execution vulnerabilities come from mixing them together accidentally. (See SQL injections and XSS attacks. The equivalent protections to executable space protection against these attacks are prepared statements / parameter binding, and the HTTP Content-Security-Policy header. Use these!) There are ways to opt-out of it when it is actually necessary.
>But worse still are its implications for programmers. Executable space protection interferes with self-modifying code, which is invaluable for just-in-time compiling, and for miraculously breathing new life into ancient calling conventions set in stone.
Programs can already allocate regions of memory with read-write-execute permissions, or switch the permissions of existing memory regions.
>We just saw how trivial it is to stitch together shreds of existing code to do our dirty work. We barely scratched the surface: with just a few gadgets, any computation is possible.
Not so much to disagree, but a suggestion: If you want to do anything more complicated than a syscall or two (an execve call will take down and cannibalize the entire process!), then using rop gadgets to do all of your dirty work is unnecessary pain. A good trick is to use rop gadgets to allocate a memory region with read-write-execute permissions, copy some executable code into it, and then jump into it. (Then you can have that code repair the program's stack, accomplish whatever changes you desired, maybe even patch the program's vulnerability to stop anyone from following you in, and then resume the normal operation of the process.)