Dailydave mailing list archives

Re: re: PaX PoC-exploit.


From: pageexec () freemail hu
Date: Mon, 03 May 2004 12:29:21 +0200

The problem is that, in my experience, most people see PaX/Grsecurity
as a silver bullet that automagically stops any and all buffer overflows.

i think it's hardly specific to PaX/grsec. consider that there are people
who use OpenBSD or even Exec-Shield with the same beliefs. what is different
however that in the PaX docs you can find all possible ways you can break
the protection (something other systems are less willing to provide 'cos
they're so weak), it is not my fault if someone doesn't read and understand
that part (and frankly, such/most end users are better off by using
'ready-made' distros, and not cook up their own).

Simple stack overflows is still a very common type of vulnerability though,
and PaX alone is not adequate protection against it.

since PaX doesn't protect against bugs but exploit techniques, the above is
irrelevant, what you wanted to state is that PaX alone does not (yet) protect
against return-to-libc style attacks explicitly - whether you can do that 'cos
you've got a stack overflow or something else doesn't change the fact that it
is possible.

   Mapping libraries to addresses with NUL-bytes.

back in 2002 PaX had this (the patches for 2.2.21 and 2.4.18 have the code)
but i decided that the reduced randomization wasn't worth the (questionable)
security provided by the 0 MSB (at least when considering the threat model
of PaX).

anyway, here's the chunk from the 2.4.18 patch, adapt as necessary. note that
that patch also put the stack at a 0 MSB address, that's why the reference to
mm->start_stack in mm/mmap.c (this approach had to be abandoned because back
then LinuxThreads made a bad assumption about the stack location and threaded
apps wouldn't work anymore, so be careful if you want to revive that chunk as
well ;-).

--- linux-2.4.18/mm/mmap.c      2002-02-25 20:38:14.000000000 +0100
+++ linux-2.4.18-pax/mm/mmap.c  2002-03-31 16:32:00.000000000 +0200
@@ -603,6 +621,24 @@
        }
        addr = PAGE_ALIGN(TASK_UNMAPPED_BASE);

+#ifdef CONFIG_PAX_RANDMMAP
+       /* PaX: randomize base address if requested */
+       if (current->flags & PF_PAX_RANDMMAP) {
+               vma = find_vma(current->mm, current->mm->start_stack);
+               if (vma)
+                       addr = vma->vm_end + PAGE_SIZE + ((0xFFUL << PAGE_SHIFT) & current->mm->delta_mmap);
+               for (vma = find_vma(current->mm, addr); addr + len <= 0x01000000UL; vma = vma->vm_next) {
+                       /* At this point:  (!vma || addr < vma->vm_end). */
+                       if (TASK_SIZE - len < addr)
+                               return -ENOMEM;
+                       if (!vma || (addr + len <= vma->vm_start && addr + len < 0x01000000UL))
+                               return addr;
+                       addr = vma->vm_end;
+               }
+               addr = PAGE_ALIGN(TASK_UNMAPPED_BASE) + current->mm->delta_mmap;
+       }
+#endif
+
        for (vma = find_vma(current->mm, addr); ; vma = vma->vm_next) {
                /* At this point:  (!vma || addr < vma->vm_end). */
                if (TASK_SIZE - len < addr)
--- linux-2.4.18/fs/exec.c      2001-12-21 18:41:55.000000000 +0100
+++ linux-2.4.18-pax/fs/exec.c  2002-03-31 16:18:34.000000000 +0200
@@ -299,6 +300,16 @@

        stack_base = STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE;

+#ifdef CONFIG_PAX_RANDMMAP
+       if (current->flags & PF_PAX_RANDMMAP) {
+               if (current->rlim[RLIMIT_STACK].rlim_cur <= 0x00F00000UL)
+                       stack_base = current->rlim[RLIMIT_STACK].rlim_cur + 0x00100000UL - MAX_ARG_PAGES*PAGE_SIZE - 
current->mm->delta_stack;
+               else
+                       stack_base = STACK_TOP - MAX_ARG_PAGES*PAGE_SIZE - current->mm->delta_stack;
+               stack_base &= PAGE_MASK;
+       }
+#endif
+
        bprm->p += stack_base;
        if (bprm->loader)
                bprm->loader += stack_base;

   Enforce a minimum delay before a SIGSEGV:ed program can be executed again
   (and before a parent process with a SIGSEGV:ed child can fork() again). 

how's that different from e.g., RES_CRASH 1 1s?

Btw, in case spender reads this, a feature I would like to see in grsecurity
would be to enforce fd 0, 1 and 2 being open upon execution of SUID/SGID
programs, as with OpenWall that opens /dev/null on those descriptors in case
they are closed. The kind of bugs possible without that feature can be pretty
sneaky.

grsec had this till 1.9.4-2.4.18, but i don't know anymore why it was removed.

what are these conditions?

1. ability to create an (executable) file
2. ability to execute the above created (or arbitrary) executable file

False. Interpreters like Perl, Python or any other of the powerful script
languages could be used to make a similar exploit too (even bash alone
could be used actually).

i think we have a definition crisis of some sort here ;-). the PaX/grsec
guarantee i was talking about is for introducing/executing new *machine*
code, what you are describing is not that (albeit similar in effect), it's
introducing new data that drives already existing code. it's of course a
valid security hazard but there's about nothing one can do about it (halting
problem and the like comes to mind). i still stand by my claim that you
cannot execute your own (machine) code (under the circumstances i specified,
PaX/grsec/ACLs).

You also seem to have completely forgotten that this technique can be used
with remote exploits too, in those cases condition one and two obviously
does not apply.

nothing forgotten, it's just irrelevant to PaX/grsec whether you have
a local or remote bug, the guarantee about executing your own code still
stands (all modulo kernel bugs of course).

Last but not least, in reality few systems actually enforce strict ACLs
that disallow users from creating and executing files on the system.

first, that's a deployment issue, independent of the underlying security
system, second, as i pointed it out, it's irrelevant what a given user
can execute, what matters is what the attacked program can execute.

Not to mention that some of the systems that disallow execution of
user provided files can be circumvented by executing them indirectly e
via the dynamic linker, bugs in "allowed programs", etc or by simply
using an interpreter instead.

not sure what 'some of the systems' refer to, if you meant grsecurity
based ones, then it's not possible, as i mentioned it previously, the
executable feature (as defined by the ACLs) is enforced at the kernel's
internal mmap() level, it doesn't matter who does the mmap() (kernel
or someone in userland), a non-executable file cannot be mapped with
PROT_EXEC.

if you meant the circumvention of a noexec mount, then it's not possible
either, mainline linux kernels (already in 2.4 and 2.6 and soon in 2.2 as
well) prevent it in the trivial case, and PaX prevents it for good (reminds
me, someone should write a PoC for that and post it to lkml ;-).

why are these not true?

"Why may not these be true" or "Why are these not true in all cases"
would have been more appropriate.

given what 'code' means (machine code) i stand by my claim ;-). if you
still contest it, please provide a PoC or at least the concept.

   when i stated in the PaX docs that PaX can be used to prevent the
   introduction/execution of arbitrary code (which is that this PoC
   relies on), it wasn't a figure of speech, it's reality and Joel's
   PoC doesn't prove it wrong either.

The PoC does not directly introduce/execute arbitrary code though, it
executes code that already exists in the address space of the process
but in an unintended manner. It simply alters the execution flow.

it does rely on the ability to create/execute new machine code (a new file
that can be executed). the PaX (or better, grsec) guarantee is not only
for doing this directly in memory but in general and you didn't prove
that wrong.

   of course it's perfectly fine to exploit a weakened deployment but
   then please say so, otherwise the casual reader will misunderstand
   your conclusions.

Actually, it's the other way around. My exploit works in the kind of
deployment that is pretty standard and you tell me that the exploit

what you didn't do is mention this 'tiny detail' in your PoC and just
made a sweeping conclusion (blaming the security measures instead of
the way it's deployed by some), that's the only part that bothered me.

could have been prevented if properly implemented ACLs were used,
which is of course true. But what if the program that was exploited
should be able to execute /bin/sh under "normal" circumstances (not
that unlikely, since functions like system() and popen() uses it).

then you could execute /bin/sh - and the point is? that's still not
introduction/execution of arbitrary code as i discussed it above. sure,
it's a success for an attacker but then noone claimed otherwise either
(and 'success' is a relative term too, think of a grsec chroot and/or
ACLs - a full system compromise will need more than your traditional
execve(/bin/sh) shellcode).

Where did "kernel info leaking" come into the picture..? You mean like listing
the addresses in /proc/<pid>/maps?

no, maps won't give you __guard. what i meant was that kernel info leaking
can give you access to the physical pages used by another process, including
its stack (lots of copies of __guard) or whereever __guard resides itself
(linux maps the first 1GB or so RAM directly in the kernel, so one process
can see another's pages, when executing in the kernel).

Actually, many exploit coders that I have shown the exploit for during the
last few months have been rather surprised to see that such an exploit was
still possible with PaX. Since the technique is well known most people seem
to have assumed that PaX had some kind of protection against it by now.

'many exploit coders' need to RTFM ;-).

Some people I talked with had assumed more entropy was involved and some
thought libraries were mapped on addresses with NUL-bytes (which is not
a fool-proof protection either of course, but it helps). Some people just
hadn't thought further than "PaX protects against overflows, period".

from http://marc.theaimsgroup.com/?l=bugtraq&m=106089684213186&w=2 (that'd
be from 9 months ago) you can get http://mapage.noos.fr/hrchallenge/bpax.tgz .
that's something i consider a novel (and gargantuan ;-) PoC.

grsecurity's RES_CRASH is a pseudo resource, details are in the manual:
http://www.grsecurity.net./gracldoc.htm#Resource_Restrictions .

Thanks for the documentation reference. I still don't see why that pseudo
resource cannot be provided without enabling the ACL system.

because it's not a true (standard) resource hence making it available
to userland via the usual interfaces could break other stuff (not to
mention that userland would have to be modified to make use of this,
i think neither me nor spender has the time for that).

Ah, so they still don't restrict mprotect()..

indeed, but even if they did, 'retf' is still there.

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


Current thread: