COMMAND
StackGuard
SYSTEMS AFFECTED
Those using StackGuard
PROBLEM
Following is based on ImmuniX OS Security Alert. A method has
been found to violate StackGuard protection against stack smashing
attacks. ImmuniX OS is generally intended to aleviate the need
for frequent patching; this is the first StackGuard vulnerability
to be discovered since StackGuard was introduced in January 1998.
A significant security vulnerability has been discovered by
Mariusz Woloszyn that permits attackers to perpetrate successful
attacks against StackGuarded programs under particular
circumstances. Woloszyn is preparing a Phrack article describing
this vulnerability, which is summarized here. StackGuard 1.21
effectively protects against this vulnerability. Consider this
vulnerable code:
foo(char * arg) {
char * p = arg; // a vulnerable pointer
char a[25]; // the buffer that makes the pointer vulnerable
gets(a); // using gets() makes you vulnerable
gets(p); // this is the good part
}
In attacking this code, the attacker first overflows the buffer
a[] with a goal of changing the value of the char * p pointer.
Specifically, the attacker can cause the p pointer to point
anywhere in memory, but especially at a return address record in
an activation record. When the program then takes input and
stores it where p points, the input data is stored where the
attacker said to store it.
The above attack is effective against the Random and Terminator
Canary mechanisms because those methods assume that the attack is
linear, i.e. that an attacker seeking to corrupt the return
address must necessarily use a string operation that overflows an
automatic buffer on the stack, moving up memory through the
canary word, and only then reach the return address entry. The
above attack form, however, allows the attacker to synthesize a
pointer to arbitrary space, including pointing directly at the
return address, bypassing canary protection.
SOLUTION
StackGuard 1.21 introduces a new canary defense mechanism: the XOR
Random canary. Like the random canary mechanism, we choose a
vector of 128 random canary words at exec() time, but we also XOR
the canary with the return address word, so that the return
address is bound to the random canary value. The exact procedure
is as follows:
* Setting up an activation record: when calling a function
o push the return address
o look up the random canary word for the current function
o XOR the random canary word with the return address
o store the result immediately below the return address in the
activation record
* Tearing down an activation record: when returning from a function
o fetch the canary word from memory
o XOR the memory canary word with the return address on the
stack
o compare the result with the random canary word associated
with the current function
The result of this method is that we have the same protection as
with the classic Random canary, and also the property that the
attacker cannot modify the return address without invalidating
the canary word. StackGuard 1.21 has been made available:
http://immunix.org/downloads.html#sg1.21