Stack Corruption Detection using canary value

Viewed 1635

I'm reading a textbook which describes defense that is be able to detect when a stack has been corrupted. The book says:

Recent versions of gcc incorporate a mechanism known as a stack protector into the generated code to detect buffer overruns. The idea is to store a special canary value in the stack frame between any local buffer and the rest of the stack state, as illustrated in the picture below: enter image description here

This canary value, also referred to as aguard value, is generated randomly each time the program runs, and so there is no easy way for an attacker to determine what it is. Before restoring the register state and returning from the function, the program checks if the canary has been altered by some operation of this function or one that it has called. If so, the program aborts with an error.

I get the idea but I still think there is a flaw in this design. Yes the attacker might not be able to determine what the value of canary is, but the attacker know the size of canary(8 bytes), so the attacker can manipulate the pointer to bypass this 8 byte area in stack where canary locates then overwrite the return address, so canary actually protects nothing, is my understanding correct?

2 Answers

If the attacker has arbitrary write, then yes, the canary is useless. In fact, there are many ways arbitrary write can invalidate a canary, including overwriting the GOT entry of __stack_chk_fail (the function called when the canary is overwritten), or just not overwriting the canary to begin with. However, arbitrary write isn't always obtainable. It usually only happens when there's a format string vulnerability. When there's just a buffer overflow, to write to an address after the canary, you have to write to the addresses before that address, which includes the canary. This means that the only reasonable way to overwrite the return address with a buffer overflow is to either guess the canary or leak it through another vulnerability.

First off, it's important to note that the diagram, although correct, is the opposite direction as most conventional diagrams of a stack. Thus, the user input will start at buf and progress upwards.

Since the random stack canary is placed between the buffer and return address, and the goal of an attack is usually to overwrite the return address to redirect program flow, there is no way to avoid overwriting the canary value. This effectively defeats any kind of exploit relying on a buffer overflow. In addition, the stack canary always ends in a null byte, which also makes it a bit harder to write even if its value is known, because many string functions will terminate at the null byte.

The reason buffer overflow exploits are so common is that it is very easy for a programmer to accidentally take more input than can fit in a buffer. In practice, being able to manipulate the stack pointer or skip over the stack canary like you suggest is significantly more difficult (if not impossible) than a buffer overflow, and in many cases requires control of the return address anyway.

However, preventing one type of exploit does not mean other techniques are not viable. As Aplet mentioned, there are other techniques that can bypass or nullify the protection that stack canaries offer. It is impossible to prevent all exploitation techniques, and in general, the more protection is applied, the more of a performance penalty there is. Stack canaries are an excellent balance of small performance penalty and detection of a large number of attacks.

Related