Dailydave mailing list archives

Re: Theo's presentation on exploit prevention


From: Dave Aitel <dave () immunitysec com>
Date: Wed, 15 Sep 2004 23:33:03 -0400

For those of you don't know pageexec, he's a crazy genius behind such things as PaX. :>

In terms of a general comment on W^X, one of the VSC bugs Sinan Eren did is against Execsheild, and it is reliable remotely. So, ya know, don't panic.

-dave



pageexec () freemail hu wrote:

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

_______________________________________________
Dailydave mailing list
Dailydave () lists immunitysec com
http://www.immunitysec.com/mailman/listinfo/dailydave

_______________________________________________
Dailydave mailing list
Dailydave () lists immunitysec com
http://www.immunitysec.com/mailman/listinfo/dailydave


Current thread: