lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20040916005537.GA23205@fist.immunitysec.com>
From: bas.alberts at immunitysec.com (Bas Alberts)
Subject: Fwd: Theo's presentation on exploit prevention

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

http://lists.immunitysec.com/pipermail/dailydave/2004-September/000918.html

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
   constructors).

   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
   with.


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



Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ