Thursday, August 13, 2009

Linux NULL pointer dereference due to incorrect proto_ops initializations (CVE-2009-2692)

EDIT2: Here is RedHat's official mitigation recommendation
EDIT3: Brad Spengler also wrote an exploit for this and published it. The bug triggering is based on our exploit which leaked to Brad though the private vendor-sec mailing list. He implements the personality trick Tavis and I published in June to bypass mmap_min_addr and also makes use of a feature that allows any unconfined user to gain the right to map at address zero in Redhat's default SELinux policy. He wrote a reliable shellcode for this one that should work pretty much anywhere on x86 and x86_64 machines.
EDIT4: if you use Debian or Ubuntu on your machine, I have specifically updated the kernelsec Debian/Ubuntu GrSecurity packages to protect against this bug and others.
EDIT5: Zinx wrote an ARM Android root exploit
EDIT6: Ramon de Carvalho Valle wrote a PPC/PPC64/x86_64/i386 exploit

Tavis Ormandy and myself have recently found and investigated a Linux kernel vulnerability (CVE-2009-2692). It affects all 2.4 and 2.6 kernels since 2001 on all architectures. We believe this is the public vulnerability affecting the greatest number of kernel versions.

The issue lies in how Linux deals with unavailable operations for some protocols. sock_sendpage and others don't check for NULL pointers before dereferencing operations in the ops structure. Instead the kernel relies on correct initialization of those proto_ops structures with stubs (such as sock_no_sendpage) instead of NULL pointers.

At first sight, the code in af_ipx.c looks correct and seems to initialize .sendpage properly. However, due to a bug in the SOCKOPS_WRAP macro, sock_sendpage will not be initialized. This code is very fragile and there are many other protocols where proto_ops are not correctly initialized at all (vulnerable even without the bug in SOCKOPS_WRAP), see bluetooth for instance.

So it was decided that instead of patching all those protocols and continue to rely on this very fragile code, sock_sendpage would get patched to check against NULL. This was already the way sock_splice_read and others were handled.

Since it leads to the kernel executing code at NULL, the vulnerability is as trivial as it can get to exploit (edit: that's for local privilege escalation and on Intel architectures): an attacker can just put code in the first page that will get executed with kernel privileges. Our exploit took a few minutes to adapt from a previous one:

$ ./leeches
// ------------------------------------------------------
// sendpage linux local ring0
// ---------------- taviso@sdf.lonestar.org, julien@cr0.org
// leeches.c:Aug 11 2009
// GreetZ: LiquidK, lcamtuf, Spoonm, novocainated, asiraP, ScaryBeasts, spender, pipacs, stealth, jagger, redpig, Neel and all the other leeches we forgot to mention!
Enjoy some photography while at ring0 @ http://flickr.com/meder
For our webapp friends, here is an XSS executing at ring 0: javascript:alert(1);
shellcode now executing chmod("/bin/sh", 04755), welcome to ring0
Killed
$ sh
# id
uid=1000(julien) gid=1000(julien) euid=0(root)

On x86/x86_64, this issue could be mitigated by three things:
  • the recent mmap_min_addr feature. Note that this feature has known issues until at least 2.6.30.2. See also this LWN article.
  • on IA32 with PaX/GrSecurity, the KERNEXEC feature (x86 only)
  • not implementing affected protocols (a.k.a., reducing your attack surface by disabling what you don't need): PF_APPLETALK, PF_IPX, PF_IRDA, PF_X25, PF_AX25, PF_BLUETOOTH, PF_IUCV, IPPROTO_SCTP/PF_INET6, PF_PPPOX, PF_ISDN, but there may be more. (Update: See RedHat's mitigation)
This patch should be applied to fix this issue.

You can read our advisory here.

Note: this has been featured on Slashdot, OSNews, TheRegister, ZDNet and others

32 comments:

  1. AnonymousAug 13, 2009 12:56 PM
    It's not exploitable for code execution on all architectures. My sparc server for instance is safe ;)
    ReplyDelete
  2. AnonymousAug 13, 2009 02:04 PM
    It's already been patched, just make sure you've run the update.
    ReplyDelete
  3. AnonymousAug 13, 2009 02:06 PM
    I'm safe, I run Windows
    ReplyDelete
  4. AnonymousAug 13, 2009 02:21 PM
    One more reason I'm glad to have PaX and GrSecurity.
    ReplyDelete
  5. AnonymousAug 13, 2009 02:22 PM
    good thing i run plan9
    ReplyDelete
  6. AnonymousAug 13, 2009 02:31 PM
    How about some exploit code??
    First person to release c0de gets a beer on me!
    ReplyDelete
  7. AnonymousAug 13, 2009 02:55 PM
    What if you have IPX completely disabled in your kernel? Looking at your discovery, I can see how this would be a problem for people with very modular kernels/
    ReplyDelete
  8. AnonymousAug 13, 2009 02:56 PM
    http://www.securityfocus.com/bid/36038/exploit
    beer please now
    ReplyDelete
  9. AnonymousAug 13, 2009 03:59 PM
    This is one reason so many 64b systems (Tru64 on Alpha being a good example) prevent mapping the first 32 bits of address space. Surprising that Linux doesn't do the same.
    ReplyDelete
  10. AnonymousAug 13, 2009 06:04 PM
    > This is one reason so many 64b systems
    > (Tru64 on Alpha being a good example
    > prevent mapping the first 32 bits of
    > address space. Surprising that Linux
    > doesn't do the same.

    ?? First of all - the whole problem has nothing to do with architecture of the used CPU (intel, non-intel, 32bit, 64bit).

    Secondly - Linux also offers such protection, but it was somehow flawed until one of the kernel versions

    3rdly - It is guaranteed on some systems (SVR4) that the fisrt page is always mapped (PROT_READ afair), so linux tries to emulate that behavior via the personality mechanism - http://linux.die.net/man/2/personality - and that is where the bug lied (the one with mapping zero page).
    ReplyDelete
  11. nojoyAug 13, 2009 07:23 PM
    Good find, great work.
    ReplyDelete
  12. AnonymousAug 13, 2009 09:39 PM
    Exploit code has been available at http://grsecurity.net/~spender/wunderbar_emporium.tgz

    Works on all affected kernels: both x86 and x64, 4k stacks or 8k stacks, cred framework or not. Disables SELinux, AppArmor, LSM, and auditing. Also plays an embedded movie if the host is up to it.

    -Brad
    ReplyDelete
  13. AnonymousAug 14, 2009 01:12 AM
    Can anybody explain why http://www.securityfocus.com/bid/36038/exploit only works once?
    ReplyDelete
  14. FanfAug 14, 2009 01:20 AM
    Congrats for the discover !
    ReplyDelete
  15. AnonymousAug 14, 2009 03:42 AM
    Yet another reason to use some alternative with better track record wrt security, like Solaris or *BSD.
    ReplyDelete
  16. AnonymousAug 14, 2009 07:13 AM
    Looks like it's finally kernel upgrade time!
    Goodbye Linux_2.6.19, I'll miss you.

    Codifex
    ReplyDelete
  17. AnonymousAug 14, 2009 08:32 AM
    Don't use the one from securityfocus, they have an old version of the exploit.
    ReplyDelete
  18. AnonymousAug 14, 2009 12:04 PM
    UNABLE TO MAP ZERO PAGE! on up to date Fedora with SELinux. Problem addressed by Red Hat when fixing CVE-2009-1895 recently?
    ReplyDelete
  19. AnonymousAug 14, 2009 12:29 PM
    Why can't the kernel track the process that map page zero and does extra stuff when switching from user mode to kernel mode (update mmu to make it not excecutable, ...)

    Of course this will slowdown these processes but are there performance program that depend of that ?
    Wine ?
    ReplyDelete
  20. ChristophAug 14, 2009 12:46 PM
    Looks like you where to fast when you thanked Dan, because SELinux does indeed stop this:

    $ LANG=C sh wunderbar_emporium.sh
    runcon: invalid context:
    unconfined_u:unconfined_r:initrc_t:s0-s0:c0.c1023: Invalid argument
    UNABLE TO MAP ZERO PAGE!
    ReplyDelete
  21. ChristophAug 14, 2009 01:43 PM
    Doesn't work with SELinux, although you claim the opposite in the source:

    sh wunderbar_emporium.sh
    runcon: invalid context:
    unconfined_u:unconfined_r:initrc_t:s0-s0:c0.c1023: Invalid argument
    UNABLE TO MAP ZERO PAGE!

    and the raw audit message for this:
    localhost.localdomain type=AVC msg=audit(1250278420.753:27501): avc: denied { mmap_zero } for pid=16933 comm="exploit" scontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=memprotect

    So obviously you were to fast when you thanked Dan for "great SELinux bypass".
    ReplyDelete
  22. LamAug 15, 2009 03:00 AM
    Fedora's SELinux policy (asuuming you leave it enforcing) protects from the exploit (runcon can't change the type).
    ReplyDelete
  23. EmsiAug 15, 2009 08:06 AM
    So there's actually two bugs. One is NULL pointer dereference and the other is allowing to mmap (presumably unmmapable) memory at 0x0 location (even if /proc/sys/vm/mmap_min_addr > 0).
    ReplyDelete
  24. Julien TinnesAug 15, 2009 09:13 AM
    Here's a reply to some of the comments (not all, sorry):

    - @Anonymous: you're correct, about SPARC. Interestingly, IA32 could also be safe but is not for performances reasons (unless you use Linux 2.0 or PaX KERNEXEC/UDEREF). x86_64 however killed segmentation :(
    - About mapping to Null. This should be protected by mmap_min_addr since Linux 2.6.23. Last month, Tavis and I published a way to bypass it by using personalities and Pulseaudio. Brad Spengler then implemented this technique in an exploit and noticed that it worked even without the Pulseaudio trick. The reason was the default SELinux policy allowing unconfined users to mmap at address zero.
    ReplyDelete
  25. AnonymousAug 15, 2009 11:43 PM
    This definetly does not work on fedora with selinux enforcing.
    ReplyDelete
  26. AnonymousAug 16, 2009 02:30 AM
    my fedora 11 with SELinux enforcing is also safe, the exploit doesnt work or did i miss something?
    ReplyDelete
  27. AnonymousAug 16, 2009 05:23 PM
    It did exploit Fedora SELinux up until August 13, then was patched. I successfully exploited Kernel 2.6.29.6-213.fc11.i586 with this mechanism.
    ReplyDelete
  28. AnonymousAug 27, 2009 03:33 AM
    http://www.doecirc.energy.gov/bulletins/t-217.shtml
    Julien can u give more info about this vuln and how to trigger it.
    thanks
    ReplyDelete
  29. yenimodaSep 7, 2009 02:15 PM
    oo thanx bro. good bilgi..
    ReplyDelete
  30. John CooperSep 26, 2009 02:59 PM
    Is it not normal procedure to inform the Kernel maintainers before publishing an exploit to the world? It took until 13th August for a patch to be released.
    ReplyDelete
  31. Julien TinnesSep 27, 2009 12:41 PM
    @John: I have no idea what you're talking about. We also worked on the patch, which was released even before the advisory.

    I even link to it from the blog post.
    ReplyDelete
  32. saksitNov 30, 2009 10:28 AM
    I have no idea
    ReplyDelete