Fwd: Theo's presentation on exploit prevention

From: Bas Alberts (bas.alberts_at_immunitysec.com)
Date: 09/16/04

  • Next message: KF_lists: "Re: [Full-Disclosure] Severe exploit found, all UNIX are affected!"
    Date: Wed, 15 Sep 2004 20:55:37 -0400
    To: full-disclosure@lists.netsys.com

    Some interesting comments on pro-active security appeared on the daily
    dave just now.


    Pasted for your convenience:

    [Dailydave] Theo's presentation on exploit prevention
    pageexec at freemail.hu pageexec at freemail.hu

    Theo's presentation on exploit prevention or the siren [1] sang again.
    lest we die in ignorance though, let's look at that song.

    slides 1-2:

       we're getting lured into the belief that something genuine is going to
       happen here. we're about to learn how the OpenBSD project smartened up
       finally and copied the intrusion prevention technologies that others had
       developed in the previous few years and more! we're promised a much more
       hostile system environment and backwards compatibility, no less.

       one begins to suspect why the stupid greek sailors all died in the end.

    slide 3:

       here we learn in more detail about the noble goals of this effort. it's
       not quite clear how one's supposed to not break behaviour that the apps
       depend on while still prevent the exploits from making use of the same
       behaviour... but let's not rush ahead so fast. we're going to follow
       POSIX and still do nasty nasty things to those attackers - or so the
       song promises.

    slides 4-5:

       let's cut to the meat! buffer overflows. to add insult to injury, it's
       the stack based ones. oh, not THEM again. we thought we'd been past that
       for years now! while marveling at the beauty of the 1000th buffer overflow
       depiction we keep wondering when the OpenBSD Team will eventually learn
       about the clever attacker that is exploiting more than buffer overflows.

       anyway, let's look at this old buddy again. we learn that the buffer is
       ALWAYS at the same place. how nice. how secure. stuff like environment
       strings, program arguments and whatnot surely have no role in the stack
       pointer value. apparently not on OpenBSD. proactive insecurity, isn't it.

       so what shall we do about it? shift the stack by a random amount! where,
       how, how much? apparently on OpenBSD the top of the stack is what normal
       mortals consider the bottom of it... honest to god mistake, we understand
       where the real gap is. at the bottom. no pun intended.

       and then look at those failures! all due to that unbelievable 15 bits of
       randomness OpenBSD managed to cram into that space! and we learn that all
       this costs us at most one physical page of RAM. what we don't learn is
       that it also costs us 256 kB of virtual address space (or more precisely,
       whatever our admin deemed acceptable for his sense of security), but we
       have got plenty of that and as we'll see later, it's a drop in the water
       only (we're sailors, don't miss the pun!) compared to what will follow
       later. so, what is 15 bits of randomness worth really? at one attempt
       a second, it's less than half a day on average (assuming we're actually
       going for the full 15 bits and can't get away with less), for stuff that
       forks only it's even guaranteed in that time. on localhost it's a matter
       of minutes.

       and you're wondering why other vendors haven't picked it up (one wonders
       where OpenBSD picked it up from). maybe because they can count further
       than 15. what about 24, or 32 or whatever the address space reasonably
       allows? sounds better, doesn't it.

    slide 6:

       here we learn about the fantastic japanese stuff (great sailors of their
       time) that many in the world, including OpenBSD, have blissfully ignored
       for... a few years at least. but now they have rediscovered the precious,
       and it's all theirs and theirs and... we get this stack overflow focus
       again. the one ring that binds them all. and we forget about information
       leaking bugs that render this and other randomization based approaches
       pretty vulnerable to attack. we also forget about localhost where we get
       unexpected help for this: the kernel (and the nice bugs in it). the best
       use of SSP is in the kernel itself. having a single canary value sitting
       like a duck for the uptime of the system is the best idea men, err, sirens
       could come up with. having it change per process and syscall crosses only
       the minds of mad sailors.

    slide 7:

       we can see that SSP found a few exploitable bugs. but where are the
       advisories? surely not swept under the carpet, right?

    slides 8-9:

       W^X! no, we didn't want to curse at you, honest! this pearl is the OpenBSD
       attempt at PaX a few years late ([2], [3]), and on the surface it actually
       does what it promises: separate writable (not writeable) pages from
       executable ones unless the program Wants Just That. problem is that as
       any female reader can attest, a boy Wants Just That. including those
       badass blackhats who dare to challenge the security of OpenBSD. and since
       the OpenBSD Team made it the policy to obey the program's wishes, they
       stand a chance to actually wish something very pleasant. no, not that
       (that fish is thorny, not horny), just a r00t shell or the like. but
       let's do things at their own pace.

    slides 10-15:

       we've got a bunch of messy diagrams here, no wonder no sailor has ever
       found his way back from here. looks like the author got lost too and
       confused things like ctors/dtors with the C++ language constructs
       (__attribute__((constructor)) is not at all equivalent to C++ class

       first we see that the black sheep in the family a.k.a. the stack (it
       can't even identify its own bottom as we saw above) is executable. and
       all that because someone put the signal trampoline there. so they
       move it to its own page, adding a whole bunch of logic to the kernel
       instead of figuring out that libc could very well host it in its own
       .text, not unlike how any Linux system has been doing it for a few
       years now.

       then come other evil animals that also host writable and executable
       pages. getting rid of them is a matter of splitting them up into their
       own pages so they fall into either of the allowed categories. or change
       between them. as the runtime linker or the application (read: attacker)
       wish. not to mention that mprotect'ing the GOT/PLT on every lazily
       resolved entry must surely be a huge performance benefit and clearly
       superior to the PT_GNU_RELRO approach preferred by RedHat [4].

       last but not least we get to hear about the sad story of i386 where
       per-page non-executable rights are just an impossibility. they seriously
       mean it. look at that monster address space layout. if you consider the
       fragmentation and waste you realize that the 256 kB stack gap pales in
       comparison. while not exactly the semantics one would expect under POSIX,
       we'll happily forgive it because this implementation offers us a true
       gem. the userland code segment comes in only two sizes, and while most
       people learn early to not put all their eggs in one basket (both code
       segment descriptors in the GDT), this old adage has apparently fallen
       on the collective deaf ears of the OpenBSD Team. so what this allows our
       hypothetical attacker to do is a simple return to a 'retf' instruction
       that will further return to the injected shellcode in the all-executable
       code segment... voila, proactive security at its best.

    slides 16-17:

       here we are told that i386 is not all that bad provided one uses its
       64 bit cousin and learns to program in PAE mode. apparently the latter
       is a serious challenge for the OpenBSD Team (read: they couldn't just
       lift the code from FreeBSD). so the sirens are now trying to lure the
       unsuspecting vendors into implementing yet another way of doing
       non-executable pages, as if it wasn't already messy enough.

    slide 18:

       so what did W^X buy us? security! performance! compatibility! we! all!
       believe! in! sirens! obviously something's wrong here. security concerns
       were discussed above, performance numbers can be hardly argued without
       actually having them... so let's see compatibility. nothing breaks. sure,
       X didn't break either then. including its homegrown module loader that
       every non-executable page implementation ran into over time. and there're
       no OpenBSD specific defines for this reason in the X module loader code
       either. 'cos nothing broke. honest. at least it's fixed now.

       what about JIT engines like in Java? we are told that on split I-D cache
       systems they would not have worked anyway without proper use of msync and
       mprotect. weird, i386 has split caches yet it's never ever needed any of
       these to generate code at runtime. obviously the problem is not the split
       cache itself but that it's not coherent on every system (and some systems
       offer simple userland accessible primitives for flushing the caches, no
       need for expensive syscalls at all).

    slides 19-20:

       this one is a true gem as well: library order randomization. we are led
       to believe that it's a worthwile effort. let's see... 'n' libraries can
       be loaded in n! order, that's a nice exponential value in 'n' (one would
       think of more than 'n' bits of extra randomness that an attacker has to
       get right). question is whether that is its true security value as well
       or not. considering that an attacker normally wants to use a single
       library in a ret-to-libc style attack (libc... get it?), we can easily
       conclude that for this purpose the load order will be 'right' once in
       every 'n' attempt. that in turn means that all this gained is log(n)
       bits of extra randomization... hardly worth a mention at all, not to
       mention its cost in code complexity and performance impact in ld.so.

       then we're shown the 'wee bit' of virtual address space that is wasted
       in library base address randomization. heavily fragmented all 256 MB of
       it. double that as the waste is mirrored above the executable limit as
       well (most if not all libraries contain both code and data). that's
       1/6th of the entire address space. a wee bit understated, indeed.

    slide 21:

       confused yet? rhetorical question but see, those dumb attackers really
       are, no question about it. they're facing incredible amounts of entropy,
       they can no longer execute their payload, and worst, they are stuck at
       these classic buffer overflows! of course information leaking bugs are
       unheard of in siren land, as are non-linear overflows. and the many
       kinds of memory corruption bugs that the creative human mind comes up

    slide 22:

       good old mmap randomization (3+ years in PaX), except it doesn't only
       depend on the presence of MAP_FIXED but also the address hint (non-0
       hints above p_vmspace->vm_daddr won't be randomized).

    slide 23:

       there is hope! apparently someone did hear about heap overflows and
       related exploits in the OpenBSD Team. a pity they haven't actually
       delved in the fine details of it [5], else they would know that adding
       randomization within a page gives only 2-8 bits of randomness, hardly
       a challenge.

    slide 24:

       this is probably the most useless security feature one can ever come
       up with. while making .rodata non-executable looks like good housekeeping
       on the surface, it's pretty useless as a security measure. the readership
       is challenged to find (or produce) a real-life bug that cannot be
       exploited except when .rodata is executable. we have yet to see one.

       we also learn the underlying concept of all these address space tweaks:
       the noble goal of least privilege. except the security-challenged OpenBSD
       Team doesn't know that memory protection rights come in pair: one set
       defines the active permissions and another the attainable ones. restricting
       the former only while leaving free reign over the latter means that it
       is possible to circumvent the former. and it wasn't until 3.4 where one
       could call mprotect() with random stack garbage as arguments and have
       the kernel still accept the protection flags it knew about and ignore
       the rest.

    slide 25:

       besides the usual trashing of the quality of "Open Source" (one wonders
       if it applies to OpenBSD as well then), we note that there is a reason
       why ElectricFence is not used in production, it just kills performance
       due to the heavy address space fragmentation. and this thing is at least
       a decade old... does everything take this long to be 'discovered' in the
       OpenBSD world?

    slides 26-27:

       this is a cool hack! it's not quite clear though what advantage it has
       over SSP given that they both detect the same kind of attacks. and we
       are of course forever indebted for the reference to PaX [3], in those
       hard days when the OpenBSD Team hadn't heard of us for another year or
       two. seriously. they said so therefore it must be true.

    slides 28-32:

       least privilege again, this time of more mundane ones, not memory access
       rights. of the two methods, privilege revocation does actually make sense
       however privilege separation (not seperation) doesn't. for noone has a
       bugfree kernel. especially not OpenBSD that wasn't written from scratch
       by its maintainers who have often little idea what a given piece of code
       does. examples like the improper use of the i386 GDT mentioned above and
       other (sometimes not yet public) snafus clearly prove the point.

       so what does a kernel bug do? a good one will allow the skilled attacker
       to run his code with kernel privileges (say ring-0 on i386) and effectively
       circumvent anything that the OpenBSD Team have dreamt up for protection.

       in other words, it doesn't matter where you shift the buggy code, it can
       already exploit any of the kernel bugs to gain whatever privileges the
       attacker needs. put that into the second stage of a normal remote exploit
       and you're back at square one, remote root, whatever way you look at it.

    slides 33-34:

       finally, we can see the difficulties facing the defenders:

       - no clear concept let alone implementation against exploits of memory
         corruption bugs (tree vs. forest problem), effectively you can never
         be sure if a given bug is exploitable under these measures and what
         kind of damage it can cause,

       - performance and compatibility information is unreliable, you're still
         best off by simply testing it yourself, that's especially important
         for 3rd party apps that might break due to the unconventional address
         space layout and memory protection semantics,

       - exploitable bugs are fixed silently, how to learn to update then?

    this concludes our odyssey and for the rest of you, happy sailing!
    just don't forget the earplugs when the sirens begin to sing.

    [1] http://dictionary.reference.com/search?q=siren
    [2] http://marc.theaimsgroup.com/?l=openbsd-tech&m=97416533704634&w=2
    [3] http://stackghost.cerias.purdue.edu/stackghost/node32.html
    [4] http://people.redhat.com/drepper/nonselsec.pdf
    [5] http://www.blackhat.com/presentations/bh-europe-03/BBP/bh-europe-03-bbp.pdf

  • Next message: KF_lists: "Re: [Full-Disclosure] Severe exploit found, all UNIX are affected!"

    Relevant Pages

    • Fwd: Theos presentation on exploit prevention
      ... Some interesting comments on pro-active security appeared on the daily ... depiction we keep wondering when the OpenBSD Team will eventually learn ... about the clever attacker that is exploiting more than buffer overflows. ... the kernel (and the nice bugs in it). ...
    • [Full-Disclosure] Fwd: Theos presentation on exploit prevention
      ... Some interesting comments on pro-active security appeared on the daily ... depiction we keep wondering when the OpenBSD Team will eventually learn ... about the clever attacker that is exploiting more than buffer overflows. ... the kernel (and the nice bugs in it). ...
    • Re: thoughts on kernel security issues
      ... > I'm not talking about bugs, I'm talking about mitigation of unknown bugs. ... > You have to remember that I think mostly in terms of proactive security. ... > down what exploits an attacker can actually use. ... > non-circumventable protection. ...
    • Re: philosophical question...
      ... >>But from a security point of view, if an attacker can guess ... > OpenBSD first and ported to FreeBSD once it has proved itself. ... mean that nobody else is allowed to improve security. ...
    • [UNIX] OpenBSDs IPv6 mbufs Kernel Buffer Overflow
      ... Get your security news from a reliable source. ... OpenBSD's IPv6 mbufs Kernel Buffer Overflow ... The OpenBSD kernel contains a memory corruption vulnerability in the code ... The OpenBSD team has released a "security fix" to correct the mbuf ...