Re: Stack Shield: defending from "stack smashing" attacks

From: Tobias Haustein (hausteinat_private-AACHEN.DE)
Date: Tue Aug 31 1999 - 00:24:42 PDT

  • Next message: Daniel Jacobowitz: "Re: ProFTPD"

    --tKtFalx5NIx0HZ72
    Content-Type: text/plain; charset=us-ascii
    Content-Transfer-Encoding: quoted-printable
    
    * Crispin Cowan (crispinat_private) [990830 19:47]:
    
    First, I want to make clear that I'm not involved in the development
    of Stack Shield. Anyway, I wrote a very similar tool some time ago,
    but stopped the development because of some very nasty problems. I
    will comment on these problems, that are present in Stack Shield, too.=20
    
    > [...]
    
    > Similar to StackGuard, Stack Shield hacks the prolog and epilog
    > functions to implement the defense, but instead of the StackGuard
    > mechanism of instrumenting the main stack, Stack Shield copies the
    > return addresses to the secondary stack.  Upon return, the hacked
    > epilog compares the return address on the secondary stack to that on
    > the main stack.  If they match, the return proceeds normally, and if
    > they don't match, Stack Shield patches the main stack with the
    > (presumably safe) return address from the secondary stack.
    
    This, of course, is a design flaw. The assumption, that a program
    while survive a stack smashing attack by just correcting the return
    address is somewhat optimistic. Therefore, one should use the
    StackGuard approach and abort the program (with some cool logging).
    
    > [...]
    
    > Perhaps I don't see your point. How is this more secure than StackGuard?
    
    You're right. StackGuard is at least as secure as Stack Shield. In
    some very rare cases, StackGuard is more secure, since it can detect
    buffer overflow attacks that don't change the return address, but only
    the state of the program! This type of attack goes undetected when
    using Stack Shield.
    
    > On some other not-quite-security issues:
    >=20
    >    * Compatability:
    >         o Stack Shield has a fixed size buffer for the secondary stack.
    >           Deeply recursive programs will bust this buffer.
    
    This is the first nasty problem. I was about to implement a second
    stack that grows automatically. This is not really hard to implement,
    but is operating system dependent and some work to get it right.=20
    
    > [...]
    
    >         o Stack Shield is an outboard post-processor.  This would be a
    >           HUGE compatability advantage, except that it appears to be a
    >           post-processor for assembly source files.  Thus, you still
    >           need to have source code for the program to be protected.  You
    >           also have to extensively hack make files to insert Stack
    >           Shield in the middle of compiling each file.  The path of .c
    >           -> .o -> executable becomes .c -> .s -> stack shield -> .o ->
    >           executable.  From our experience re-building all of Red Hat
    >           Linux with StackGuard, you can trust me that this will become
    >           an issue :-)
    
    This can be avoided if one hacks the compiler instead of supplying a
    new post-processor. I used this approach. Although I have not finished
    the hack to work in every possible optimization mode (though it's not
    hard to do), it works fine in most cases. The hack itself is very
    short (less than 100 lines of code) and it took me about 3 hours to
    locate the right spot in the gcc code, change, compile and test it.
    
    > [...]
    
    >    * Performance:  Stack Shield does a copy to the secondary stack and
    >      an increment in the prolog, and a compare and decrement in the
    >      epilog.  This is essentially similar to the workload imposed by
    >      StackGuard using the "Random Canary" defense, where we have an
    >      outboard table of 128 random numbers that are statically
    >      modulo-mapped to functions.  StackGuard in "Terminator Canary" mode
    >      (where the "canary" word is -1 (EOF), CR, LF, and 0; the set of
    >      common string function terminators) is likely to be faster.
    
    During my tests, I found that my method produces an overhead in
    between of 7% and 13% in total execution time on most programs. As I
    recall your paper on StackGuard [1], your figures were somewhat
    larger, even though I would expect your method to be faster.
    
    So, why would one use the approach of saving the return address on
    another stack, instead of patching the stack itself, like StackGuard?
    The only reason I can imagine, is that one does not want to change the=20
    stack layout. The benefit of not changing the stack layout, is that
    you can do the change outside of the compiler. I was about to write a
    binary translator, that reads an executeable, locates every function
    prolog and epilog, adds the nescessary code to detect buffer
    overflows, and writes a new version of the executeable. By using this
    approach, one could make existing executeables safe against (most)
    buffer overflows. The cost would be minimal, since the translator must=20
    only run once and the overhead of the proposed method is about 10% on
    average. (The reason for me to change the compiler was to check
    whether the approach works and to measure the induced overhead).
    
    Writing such a translator is possible, since there are examples of
    working tools that do similar things (Purify [2], Etch [3], ...).=20
    Anyway, doing this is a lot of work, therefore, I'm currently trying
    to find a skeleton for the translator, instead of writing one from
    scratch. If someone has a working translator on hand, I'm very
    interested in getting the source code to continue on this project.
    
    
    References
    ----------
    
    [1] Crispin Cowan, Calton Pu, Dave Maier, Hether Hinton, Jonathan
    Walpole, Peat Bakke, Steve Battie, Aaron Grier, Perry Wagle, Qian
    Zhang, "StackGuard: Automatic Adaptive Detection and Prevention of
    Buffer-Overflow Attacks", Proceedings of the 7th USENIX Security
    Conference, January 1998
    
    [2] Reed Hastings, Bob Joyce, "Purify: Fast Detection of Memory Leaks
    and Access Errors", Proceedings of the Winter 1992 USENIX Conference,
    pp. 125-136, January 1992
    
    [3] Ted Romer, Geoff Voelker, Dennis Lee, Alec Wolman, Wayne Wonk,
    Hank Levy, Brian Bershad, Brad Chen, "Instrumentation and Optimization
    of Win32/Intel Executeables Using Etch", Proceedings of the USENIX
    Windows NT Workshop.  pp. 1-7.  August 1997
    
    
    Ciao,
    
    Tobias
    
    --=20
    Dipl. Inform. Tobias Haustein
    
    Department of Computer Science IV, Aachen University of Technology
    Ahornstr. 55, D-52056 Aachen
    Phone +49 (241) 80-21417, Fax +49 (241) 8888-220
    E-Mail hausteinat_private-aachen.de
    Web http://www-i4.informatik.rwth-aachen.de/~haustein/
    --tKtFalx5NIx0HZ72
    Content-Type: application/pgp-signature
    
    -----BEGIN PGP SIGNATURE-----
    Version: PGPfreeware 5.0i for non-commercial use
    MessageID: lsS0p55U2qTbuBzS639hCpbwFBVNOaGe
    
    iQEVAwUBN8uDOBs02tO3FOYBAQEfpQgAoqzVEVvZtqERep+XHLDqnNwpFo+3XaSx
    Og7SY90Td83OcdEZnDGfs9+EIm96Ga2zleEWNTMmmw0C2NI/xBiRMkhKwZLfUxJC
    u1KpEiiZvulvm1XugOzg+I2J1cF68NBQ6kcJuZBxOtEbdpuNrlZpP+ZORnoiRMO8
    PWIXXDHDNDHUvq6mbrKr9xKZoKoZhNhPpmTQkD/3w6iyDWZo6ICuU/mndB1X/V8X
    +44jt6CvwU92lUhvJ5VNElr5bu/+bFM90Xj3JmhW7XIMk8QUNjCM8k5h7ZjEqf7p
    z9/2HuBkr7fd0hXfgEnQPEG2PoIjmV0co9iCN2MF+Vc2kTwMihtfsg==
    =Ox4x
    -----END PGP SIGNATURE-----
    
    --tKtFalx5NIx0HZ72--
    



    This archive was generated by hypermail 2b30 : Fri Apr 13 2001 - 15:00:56 PDT