A researcher has published exploit code for a new vulnerability he discovered in the Linux kernel. The vulnerability is an especially interesting one in that the researcher who discovered it, Brad Spengler, has demonstrated that he can use the weakness to defeat many of the add-on security protections offered by SELinux and AppArmor.
The vulnerability affects both the 2.6.30 and 2.6.30.1 releases of the Linux kernel, and in a message to the Daily Dave mailing list Spengler said that he was able to exploit the flaw. He said that he was able to defeat the protection against exploiting NULL pointer dereferences on systems running SELinux and those running typical Linux implementations. SELinux is a set of security enhancements to the Linux OS developed by the National Security Agency.
Spengler said that when he first saw the Linux bug he knew that he would be able to get arbitrary code execution by using it. “Within about two hours I was able to get the code execution, figure out how to turn off SELinux, AppArmor and LSM,” he said.
He based his exploit technique on work published last month by Julien Tinnes and Tavis Ormandy on exploiting NULL pointer derefernces in Linux, specifically.
Spengler also said he is able to turn off the auditing processes in SELinux, AppArmor and the Linux Security Module. Once SELinux was disabled, Spengler said he was able to make it appear as though the protections were still running. He posted a video demonstration of the exploit in action on YouTube.
The SANS Internet Storm Center explains how the exploit works:
“While technical details about this are a bit complex, generally what’s happening can be easily explained. The vulnerable code is located in the net/tun implementation. Basically, what happens here is that the developer initialized a variable (sk in the code snippet below) to a certain value that can be NULL. The developer correctly checked the value of this new variable couple of lines later and, if it is 0 (NULL), he just returns back an error. The code looks like this:
struct sock *sk = tun->sk; // initialize sk with tun->sk
…
if (!tun)
return POLLERR; // if tun is NULL return error
This code looks perfectly ok, right? Well, it is, until the compiler takes this into its hands. While optimizing the code, the compiler will see that the variable has already been assigned and will actually remove the if block (the check if tun is NULL) completely from the resulting compiled code. In other words, the compiler will introduce the vulnerability to the binary code, which didn’t exist in the source code. This will cause the kernel to try to read/write data from 0x00000000, which the attacker can map to userland – and this finally pwns the box.”
There also is a separate issue that Spengler discovered with SELinux that affects multiple vendors’ versions of the Linux kernel. The problem lies in the fact that in some kernel implementations, when the kernel loads the SELinux protections it overrides the NULL pointer dereference protection.
“I think that’s a bigger deal probably than the other problem,” Spengler said in an interview.
Until recently, exploiting NULL pointer dereferences was thought to be virtually impossible. But work done by Mark Dowd of IBM ISS last year put the lie to that. Dowd designed his technique to exploit a problem in Adobe Flash, but was able to extend it to exploit similar conditions in other applications.