Re: Non-executable stack patch

Solar Designer (solar@false.com)
Wed, 11 Jun 1997 07:46:37 -0300 (GMT+3)


Hello!

Well, thanks for your support... you're missing a few thing though...

> 1) A buffer overflow exploit that works on any revision of any normal
> distribution of linux (i.e. slackware/debian/redhat/caldera) that has had
> both these patches applied properly and configured properly. The exploit
> must be able to give someone with normal user access a root shell.

There're cases when a buffer overflow can be exploited with both patches
applied, and I didn't try to make that completely impossible (the patch is
useful if it makes at least some vulnerabilities unexploitable). For example,
I only make the stack non-executable, other data areas are still executable
(it's not possible to make them non-executable without moving the user code
descriptor to the LDT; also some programs depend on them being executable,
this could be fixed by a similar GPF handler approach though).

Let's take a very buggy program, which shouldn't have been setuid root, but
it was in some Linux distributions: SuperProbe. This one got several buffer
overflows, including the one where it copies argv[0] to a buffer in the bss.

It is possible to make an overflow exploit that overwrites a pointer to a
structure which has a function pointer as one of its fields (I have actually
done that in my exploit since it wasn't possible to touch the return address
for other reasons, read my old BugTraq message on that). In my old exploit,
I made it point to the shellcode on the stack, so the exploit won't work if
running with my non-executable stack patch and GCC trampolines autodetection
disabled (this is the very rare case when you get to the shellcode via a
CALL, not a RET, since a function pointer is overwritten).

Now, combining these two things -- argv[0] being copied in the bss and the
replaced function pointer on the stack -- we can make an exploit working
with my patches applied, even with GCC trampolines autodetection disabled.
Everyone could do that easily by taking my old exploit, looking at SuperProbe
sources to find the argv[0] thing, and editing the exploit a bit. However,
this requires a special approach for each exploit (where possible at all),
so a generic exploit where you just change a few values (like Aleph One's
in Phrack 49) isn't possible.

And one more important thing to note: vulnerabilities in daemons and clients
are even more dangerous, since they don't require an account on the machine
being broken into. My patch would still be useful even if it didn't protect
against local exploits at all.

> 2) A normal program that this patch breaks along with an explination of
> why it breaks them. Programs which use VM86 do not apply (dosemu). The

Well, just change the address in my mmap() patch to 0x00110000, and VM86
should work fine (at least dosemu does for me, including the DPMI support).

> program must be available (either commertial or pref. ftp able) (i.e. it
> cannot be something designed for the sole reason of dying with this patch.
> Furthermore the program cannot be 86 specifit (a person with the source
> could compile it on an alpha or other linux running platform without
> modification).

Well, there's a problem with the way Doom allocates its framebuffer, it will
disappear when I release the mmap() patch though, since Doom is a.out anyway.

And there's always the new binary header flag -- if something doesn't work
with the patch, just set the flag. :)

> Note, this offer expires one month from this date or if these patches are
> included as a kernel option.

Why didn't anyone say anything on the ring 2 and LDT problem I mentioned a
while back? I really do not like the patch the way it is, using ring 2 for
user code. It is not the right way for doing such a thing. And a bad thing
about the other solution, moving the descriptors to LDT, is that existing
versions of dosemu and Wine would be broken (very simple patches for them
would solve the problem though), and that it might be not that easy to do
as it seems at first... Any thoughts on this real problem (compared to the
ones being discussed on the subject) are welcome.

Actually, I'll most likely leave the patch the way it is if it's not going
to the mainstream kernel (it works fine for me, and using LDT would break
dosemu and Wine, which wouldn't get fixed if the patch doesn't spread wide).

It's like this: if there's a chance of the patch getting into the mainstream
kernel, tell me (and the Ring 2 vs. LDT choice), and I'll clean it up a bit.

If not, no problem, I don't insist.

> Anyone finding a kernel level solution to fixing VM86 stuff while still
> keeping the second patch's funcionatlity will win the applause of the

No real problem there, already done.

Signed,
Solar Designer