Slashdot Mirror


How To Exploit NULL Pointers

An anonymous reader writes "Ever wondered what was so bad about NULL pointer exceptions? An MIT Linux kernel programmer explains how to turn any NULL pointer into a root exploit on Linux. (There was also a previous installment about virtual memory and how to make NULL pointers benign.)"

23 of 139 comments (clear)

  1. Easy and concise by Lord+Grey · · Score: 5, Funny

    TFA is an extremely well-written, easy-to-follow tutorial. I "played along at home" (well, at work, actually) as the author recommended and exploited a system on the first try. Great stuff!

    Hang on, one of our SysAdmins wants to talk to me about something.

    BRB

    --
    // Beyond Here Lie Dragons
  2. Exceptons? by mccalli · · Score: 4, Informative

    "Ever wondered what was so bad about NULL pointer exceptions?..."

    Nothing. Because if they're an exception, they've been safely caught by the platform's exception handling mechanism. This article isn't about exceptions, it's about dereferencing your actual raw NUL pointers themselves in languages that either don't have the exception mechanism or where it simply hasn't been used.

    Cheers,
    Ian

    1. Re:Exceptons? by shutdown+-p+now · · Score: 4, Insightful

      Nothing. Because if they're an exception, they've been safely caught by the platform's exception handling mechanism. This article isn't about exceptions, it's about dereferencing your actual raw NUL pointers themselves in languages that either don't have the exception mechanism or where it simply hasn't been used.

      Actually, most JIT-based VMs don't do explicit null checks, but rather let the OS signal access violation (as it is supposed to be guaranteed for NULL pointers, unlike dangling or garbage ones), and if it happens, wrap it into the language-specific exception - it's much faster than explicit checks for every pointer dereference.

    2. Re:Exceptons? by Chris+Burke · · Score: 5, Informative

      Besides, the article is actually about NULL pointer dereferences within the kernel, where niceties like language-based exception handling mechanisms are often hard to come by. So the language you write your application code is immaterial.

      Also not just any dereference will do, it has to be a function pointer dereference.

      And recent kernels have protection against mmap()ing page 0.

      However the author has a good point that both NULL function pointer calls in the kernel and hackers getting around the mmap() protection have happened before. So while you can't exactly exploit any Linux system using the procedure he describes (several critical components require you to already have root :P) it does sound like a weakness.

      --

      The enemies of Democracy are
    3. Re:Exceptons? by Hurricane78 · · Score: 3, Interesting

      But then it is not an exploit, since the kernel always is root anyway.

      --
      Any sufficiently advanced intelligence is indistinguishable from stupidity.
    4. Re:Exceptons? by Chris+Burke · · Score: 4, Informative

      But then it is not an exploit, since the kernel always is root anyway.

      As given, no the procedure is not a working exploit for any meaningful definition ("I'm teh 1337 hacks-zor! I r00ted my home desktop!")

      However, if you could identify a case where the kernel dereferenced a NULL function pointer, and if you could get around the kernel's mmap() protection (neither implausible), then you can get the kernel to run your code using its privilege level. Meaning you can get root for yourself. And then yes indeedy you have an exploit.

      --

      The enemies of Democracy are
    5. Re:Exceptons? by eparis · · Score: 4, Insightful

      He demonstrates the simplest easiest to understand case, that of a NULL function pointer. But it really can extend to reads and writes of a NULL pointer as well (not always but often). If you can make the kernel read data from a NULL pointer you would be able to trick the kernel into reading a fake struct that you placed at NULL. Maybe that fake struct had a function pointer which you can easily set to another userspace address and voila, win. Maybe the code will read that struct and then write somewhere else in memory based on the information in that struct. Simply make that write happen in a place you choose which might lead to an eventual NULL function pointer.

      Any time the kernel accidentally dereferences a pointer (especially one outside of kernel space) and uses that data things can go bad. The mmap_min_addr checks were added to harden against the EXACT class of common bugs he describes and I'm saddened it was dismissed so out of hand.

  3. OS dependent by mdf356 · · Score: 3, Informative

    This is very OS dependent.

    For example, on AIX on POWER, page 0 in both real and virtual addressing modes is readable by all and writable by none. So a read from a NULL pointer produces junk data (actually interrupt machine code) and a write is fatal.

    --
    Terrorist, bomb, al Qaeda, nuclear, yellowcake, kill, assassinate. Carnivore is dead... long live Echelon.
    1. Re:OS dependent by hrimhari · · Score: 4, Informative

      Sorry to point out the redundancy, but the summary seems clear enough with its how to turn any NULL pointer into a root exploit on Linux .

      --
      http://dilbert.com/2010-12-13
    2. Re:OS dependent by Imagix · · Score: 4, Interesting

      But it's a bad summary. They missed the rather critical phrase "how to turn any NULL pointer dereference in the kernel into a root exploit". This isn't about any NULL pointer.

    3. Re:OS dependent by Megaweapon · · Score: 3, Funny

      But it's a bad summary.

      java.lang.RedundantSlashdotObservationException

      --
      I'm sure "SlashdotMedia" will improve on all the wonders that Dice Holdings blessed us all with
  4. Assumes a CALL to the NULL ptr (not any reference) by NumberField · · Score: 3, Interesting

    I was intrigued by the ./ posting, which claimed that the tutorial would show how to exploit any NULL pointer dereference. The actual article, however, requires a CALL to the NULL pointer. While some NULL pointer bugs are function pointers, many are not. Kernel code that merely reads or writes data to a NULL pointer will not be exploitable as shown.

  5. Bad summary by ElMiguel · · Score: 4, Insightful
    As usual, bad summary. TFA explains how to exploit a theoretical kernel bug that happens to "read a function pointer from address 0, and then call through it". That's a long shot from turning "any NULL pointer" into a root exploit as the summary claims.

    To be honest, I'm not sure why I bothered writing this comment. If the editors themselves don't care about the accuracy of the stories, why should I?

    1. Re:Bad summary by BJ_Covert_Action · · Score: 4, Insightful

      If the editors themselves don't care about the accuracy of the stories, why should I?

      Because you're not kdawson, and that's something to be proud of. ;)

    2. Re:Bad summary by argent · · Score: 3, Informative

      The OP's article wasn't very long, so you should be able to figure out that you just rephrased what he said: you need to have a null pointer function call kernel bug to exploit this. No combination of null pointer vulnerabilities in user space, and no null pointer reads and writes in kernel mode (which are more common) will get you root.

  6. Re:Assumes a CALL to the NULL ptr (not any referen by McNally · · Score: 4, Funny

    I was intrigued by the ./ posting, which claimed that the tutorial would show how to exploit any NULL pointer dereference. The actual article, however, requires a CALL to the NULL pointer.

    For further context, see my whitepaper on how to turn any kdawson-posted Slashdot story into a NULL issue.

  7. Re:I Know How To Do It by Stupid+McStupidson · · Score: 3, Funny

    Well, I upped my game. Now up yours.

  8. Not on embedded platforms by marcansoft · · Score: 5, Interesting

    One of the many exploits that we've used to own the Wii (in fact, the very first runtime IOS exploit that we used, which I found and implemented) was a NULL pointer dereference bug, and it wasn't even a function pointer.

    I wrote a detailed blog post about it recently. The short version is that they doubly dereference a near-NULL address and write to it, and NULL happens to be real physical memory that we control (call it 'insecure', if you wil). The double dereference lets us direct the write anywhere, including the stack, and it's game over. That's the "usermode" exploit. Privilege escalation into the kernel is trivial because they have some huge kernel holes. The fact that they map the 'insecure' memory as executable (!) in every application makes it even easier.

  9. If you have a bug in kernel code... by Alex+Belits · · Score: 5, Interesting

    If you have a bug in kernel code that causes NULL pointer dereference, it can be used for various nastiness (in this case, privilege escalation).

    This is why kernel shouldn't do it, and this is why it was an actual kernel bug that was exploited by so-called NULL pointer exploits. This is why those bugs were fixed.

    Apparently some readers have an impression that what was posted is an actual exploit that works on a current kernel by dereferencing NULL pointer in userspace. In reality it relies on a buggy module being introduced, so kernel NULL dereference can be triggered by the user.

    --
    Contrary to the popular belief, there indeed is no God.
  10. Re:Is the kernel address mapping part still true? by Chris+Burke · · Score: 5, Informative

    Yeah, shouldn't switch be easily take care of by a base register?

    Well it is. On x86 systems, the intuitively named Control Register 3 is a pointer to the base of the page tables. From a software point of view, switching address spaces is as easy as writing CR3.

    From a hardware point of view, that act has additional implications. You have to flush the TLBs, which sucks royal if it happens on every system call. If you have linearly tagged caches (or any other linearly tagged structure) then you'll have to flush those too. There are ways to partially mitigate these effects, but since you can't rely on them being there it's best to just avoid CR3 writes as much as possible -- which means there's less reason to implement the necessary widgets.

    --

    The enemies of Democracy are
  11. Re:The kernel is at fault. by 0123456 · · Score: 4, Informative

    Sorry, but if anything that simple can cause root access, then that’s a general error of the architecture and kernel.

    By default you need root access (or an exploitable bug) to map page zero into your address space, and you need to specifically configure the kernel to allow it, and then you need an exploitable kernel bug to make use of it.

    I wouldn't exactly call that 'simple'.

  12. kernel null function pointer by heli_flyer · · Score: 3, Insightful

    This is not "how to exploit NULL pointers" ... this is "how to exploit a kernel NULL function pointer". Well, duh. In other news, security researches find exploit for systems with blank root password.

  13. Re:Is the kernel address mapping part still true? by Chris+Burke · · Score: 3, Interesting

    I strongly disagree.

    With the entire industry. It's okay. You're not the only one to have maintained the belief that segments are not useless crap. ;)

    Segmented addressing got a bad name from the days of real mode

    That wasn't "segmentation" in the academic sense, and it's the academic sense of segmentation, what is actually implemented in 32-bit protected mode, that has the well-deserved bad reputation among the engineers implementing and coding for it. Since the default in 32-bit mode was to effectively eliminate segmentation, it only made sense to just get rid of it.

    That's not really hard to handle, especially since the code/data part is automatically handled by the processor.

    In the sense that you don't have to specify that your code accesses use the code segment and data accesses use the data segment by default. However you still have to explicitly change code and data descriptors when changing between OS and user land and those operations are also not performance-neutral. They are rather slow in fact. Not as bad as a CR3 switch, but bad enough you don't want to do two (per segment, so four) just so the kernel can return the value in it's time_t structure.

    And that's before adding on the performance penalty of having to do an extra addition for every access when not using zero-base segments. You realize how many man-years of performance widgets you've undone by doing that? :)

    Kernel code would have to explicitly distinguish between user mode access and kernel mode access (which IMHO is good).

    In theory, but the exact case in question (mmap) is one where you want the both kernel and application to have the fastest access to the mmap()ed region possible. Which, in case you were wondering, means you can't just map two linear addresses to the same physical page, one for the user and one for the kernel, because that results in TLB thrashing. And when you take that and then add all the other cases where the kernel needs to regularly access something that might be mapped in user land, and suddenly you've just recreated the need for far pointers, and passing around far pointers results in the same possibility for badly formed pointers as before. Remember, if making sure all your pointers were valid was easy we wouldn't have this problem in the first place.

    There's a reason why even when IA32 provided these segmentation facilities that nobody used them. And it's not prejudice from the 16-bit days, as if that could explain why nobody else has implemented segmentation.

    Good riddance to bad rubbish I say. Modern ISAs ftw, even if they're still CISCy. :)

    --

    The enemies of Democracy are