Howdy! đ
What a better way to do closure on the whole âhow Stack worksâ story then with some common ways used to exploit them. As usual, first the infographic and then the more detailed text.
(click on image to enlarge)
Even though OSâ and Programming Languages have come a long way in order to prevent these kinds of attacks, you still do hear about them and they still happen. The difference is that they became more sophisticated and more complex then before, but deep-down, they rely on same techniques. The (in)famous âStack Buffer Overflowâ or âStack Buffer Overrunâ.
The thing is that Stackâs biggest advantage (i.e. how data is stored - stacked on top of eaech other) is itâs biggest weakness as well. Just think about it really - from POV of memory, itâs just linear sequence of bits. Thereâs no concept of âthese bits belong to Xâ. Itâs just range of bits, that logically get interpreted by OS and programming language. Hereâs where the problem lies - if you stack multiple objects on top of each other, and you allow user to provide some (unchecked) input - they might intentionally write MORE than they are supposed to, and those additional bits will spill over to next address, which might have been reserved for something else.
Iâll give you a practical example. Think of a whiteboard. You can only write so much on your whiteboard. Whiteboard would be the Stack size and anything you write outside and on the walls will be interpreted as malicious attempt and will get you thrown out of your class.
Now imagine that I draw vertical lines and split the Whiteboard into multiple areas. What really prevents you to overwrite multiple of those is my hope that you wonât do it; or that there will be somebody penalising you if you do so. Well, the thing is that C and C++, if left unchecked, wonât penalise you for it. And this is called overflow.
Stack really stores quite some stuff, and some of those stuff are pointers to where you came from, and other variables that might get executed by CPU. So if you were able to overwrite those bits (i.e. by spilling your data over), you might force CPU into executing some malicious stuff (e.g. creating reverse shell, or installing some malicious backdoor in your system). Or you might want to interrupt the service by sending more data than Stack can store, effectively forcing OS to kill that process. Possibilities are endless, really :)
This was way bigger problem back in the day, than it is today. And thatâs primarily because many techniques were developed to battle that.
One simple way is to, instead of providing linear address space, you actually randomize it a bit, hoping that attacker might not figure out the randomization scheme and, as such, memory layout. This is what Address Space Layour Randomization (ASLR) does.
Another one is more hardcore - simply mark segments of memory that are NOT allowed to contain executable bits. Thatâs what Data Execution Prevention (DEP) does. And thereâs even a more hardened, hardware version of it.
Finally, thereâs a simple technique used since the dawn of time - use a spy. Or a snitch. Thatâs what Stack Canaries are for. You add a predefined value on top of Stack and then you check if it was overwritten. If it was - you are dealing with malicious attempt.
And thatâd be about it for today :) If you want to explore more, I came around an interesting website called Binary Exploitation Notes where you can read more about various interesting techniques.
Next week Iâm going to put focus back on Containers, but after that Iâm jumping into Heaps, Allocations, and everything else that goes with it. Until then, if you havenât subscribed already, you might want to do so now:
If you missed some of the previous articles, here are the last three: