Exploit-DB #9191
Description: Linux Kernel 2.6.30 < 2.6.30.1 / SELinux (RHEL 5) - Local Privilege Escalation
Type: local
Platform: linux
Date: 2009-07-17
Author: spender

Exploit:
/* super fun 2.6.30+/RHEL5 2.6.18 local kernel exploit in /dev/net/tun
   A vulnerability which, when viewed at the source level, is unexploitable!
   But which, thanks to gcc optimizations, becomes exploitable :)
   Also, bypass of mmap_min_addr via SELinux vulnerability!
   (where having SELinux enabled actually increases your risk against a
    large class of kernel vulnerabilities)

   for 2.6.30 without SELinux enabled, compile with:
   cc -fPIC -fno-stack-protector -shared -o exploit.so exploit.c
   (on a 64bit system -m64 may be necessary to compile a 64bit .so)
   cc -o pwnkernel pwnkernel.c
   then just ./cheddar_bay.sh
   for 2.6.30 with SELinux enabled, compile with:
   cc -fno-stack-protector -o exploit exploit.c
   then just ./exploit

   for RHEL5 2.6.18 compile with:
   cc -fno-stack-protector -DRHEL5_SUCKS -o exploit exploit.c
   then just ./exploit

   Now on with the show...

   This exploit looks like something I know, something I wrote loooong ago
   in a place... called Cheddar Bay
   the year was 2007, POGS were just rising in the fad section
   I believe you could talk about Friends, it was a viable conversation 
   topic back then
   And back then I had an exploit too, ohhh and what an exploit she was!

   exploiting the 'unexploitable' -- null ptr dereference directly to
   arbitrary code execution, and disabling SELinux & LSM atomically
   the first exploit of its kind!

   2 years later, some code has shifted around, 3 (or 4 depending on how 
   you count) vulnerabilities found in the mainline null ptr dereference 
   protection (added in reaction to the embarrassment from my exploit, 
   not from any proactive initiative), silently-fixing vulnerabilities 
   has become standard operating procedure among the kernel developers, 
   confusing even their own ranks as to what needs to be backported to 
   distro kernels or the stable tree.  So with all this great progress 
   in Linux security, what do I present now 2 years later?

   ********************************************************************
   Bypassing the null ptr dereference protection in the mainline kernel
   via two methods ->
     if SELinux is enabled, it allows pulseaudio to map at 0
     UPDATE: not just that, SELinux lets any user in unconfined_t map at
     0, overriding the mmap_min_addr restriction!  pulseaudio is not
     needed at all!  Having SELinux enabled actually *WEAKENS* system
     security for these kinds of exploits!
     if SELinux is disabled, use personality SVR4 to auto-map at 0 
   Turning a vulnerability which is unexploitable from a review of 
   the source code, where only trojan data can be supplied to a
   structure where no function pointers are called into an arbitrary OR 
   of 0x1 on any byte in memory
   Turning this arbitrary OR into arbitrary code execution by ORing
   an unused file_op on the device we're exploiting
   Abusing this arbitrary code execution to:
	* Disable auditing
	* Disable SELinux
	* Disable AppArmor
	* Disable LSM
	* Make userspace believe SELinux remains in enforcing mode
	* Give ourselves full privileges and capabilities
	* Appropriately increment refcnts so as to be
	* 100% reliable and repeatable
    Whilst providing an entertaining tale of the curse of Cheddar Bay!

    Discovery time of bug in public: 	7/6/09
    Began working on exploit:		7/9/09 6:00PM
    Completed exploit:			7/9/09 8:00PM
    Began port to 64bit:		7/11/09 11:00AM
    Completed port to 64bit:    	7/11/09 12:00PM
    Began port to RHEL5 2.6.18-157:	7/12/09 12:00PM
    Completed port to RHEL5 2.6.18-157:	7/12/09 12:30PM
    Rest of time was spent adding an incredible visual and audio experience

    Greets to Julien Tinnes & Tavis Ormandy for the null ptr dereference
    protection bypass (of which there are more ;) ) 5th time's the charm? :)
    also of course to pipacs for helpful ideas and for pointing out the
    fix for this bug that screamed of suspiciousness ;)
    also to cloud for the wonderful crab
    also to #social for being social
    and to emoflip (under duress so he doesn't stab me next month)

    to xorl.wordpress.com in the hopes that he reports more on silently 
    fixed Linux kernel vulnerabilities :)

    funtimeinternet for the curse of Cheddar Bay:
    http://www.youtube.com/watch?v=l--BvXpaGq4
    Be sure to check out the response videos (which funtimeinternet 
    called "AWESOME"):
    http://www.youtube.com/watch?v=UdkpJ13e6Z0
    http://www.youtube.com/watch?v=P7uyCMdAldM

    Finally to sgrakkyu for his two incredible exploits and nice email chats
    (and for making me realize the more interesting compiler issue here ;))
    http://kernelbof.blogspot.com
    disabling SELinux remotely with a single dword write is just classy ;)

    The commit that introduced the vulnerability (Feb 6th):
    http://mirror.celinuxforum.org/gitstat/commit-detail.php?commit=33dccbb050bbe35b88ca8cf1228dcf3e4d4b3554
    Though it was committed before the release of the 2.6.29 kernel, it 
    did not (thankfully) make it into the 2.6.29 kernel.  It first 
    appeared in 2.6.30.

    Crash appears on April 9th showing a null ptr dereference:
    http://article.gmane.org/gmane.linux.network/124939

    The buggy commit was backported to a RHEL5 test kernel on April 15th
    (the latest test kernel is still vulnerable and likely without this
    exploit being released, the code would have made it into the next
    RedHat kernel update)
    https://bugzilla.redhat.com/show_bug.cgi?id=495863

    Fix appears on July 6th:
    http://lkml.org/lkml/2009/7/6/19
    As you'll note in the fix, the problem was a NULL tun variable, 
    which from the source should have been unexploitable due to the 
    immediate check for !tun.  The dereference of tun to grab ->sk
    would have caused only a crash (or not, if NULL was mapped).  So how 
    was the b