Wednesday, April 22, 2009

Local bypass of Linux ASLR through /proc information leaks

EDIT2: Thanks to the efforts of Jake Edge who noticed our presentation, /proc/pid/stat information leak is now at least partially patched in mainline kernel, since 2.6.27.23
EDIT1: This is featured in an LWN article by Jake Edge

Tavis Ormandy and myself talked about locally bypassing address space layout randomization (ASLR) in Linux in a lightning talk at CanSecWest.

From Linux 2.6.12 to Linux 2.6.21, you could completely bypass ASLR when targeting local processes by reading /proc/pid/maps. Since Linux 2.6.22, if you cannot ptrace "pid", then you will see an empty /proc/pid/maps.

It has been known for at least 7 years now that /proc/pid/stat and /proc/pid/wchan could also leak sensitive information. Reading this information has been prevented in GRSecurity since the beginning as well as in this patch.

The question was: could you exploit this information to bypass ASLR in practice?
If you want to find out, it's easy: we've just published the slides and Tavis' tool!

Thursday, April 16, 2009

Interesting vulnerability in udevd

I used to love exploiting memory corruption vulnerabilities. It usually requires some reverse engineering, good knowledge of the underlaying operating system and some ingenuity to write reliable exploits. And if you try to circumvent clever protections such as PaX, it can get very tricky.

But besides kernel vulnerabilities, exploitable memory corruption vulnerabilities these days are mostly buffer overflows. It's a bit monotonous.

I get more excited by other kind of vulnerabilities such as Solaris' telnet -froot or the Debian/OpenSSL fiasco.

Last night, my friend Raph pointed me to this udev flaw. If you read this patch you can notice an extra check in get_netlink_msg():
if ((snl.nl_groups != 1) || (snl.nl_pid != 0))

This checks if the message recieved by udevd had been sent to a specific multicast group (sending to netlink multicast groups is privileged and can only be done with CAP_NET_ADMIN) and also if it was sent from the kernel's unicast address.

From now on, the vulnerability is pretty obvious: before the patch, udevd didn't check the origin of messages it was recieving through netlink.

So can we spoof the kernel and send arbitrary messages to udevd? Yes! And it's easy, it suffices to create a NETLINK socket with the NETLINK_KOBJECT_UEVENT protocol and to send a unicast message to the correct unicast address. In udevd, this address will be the pid of the process who bound the NETLINK socket (udevd's parent). You can easily find it in /proc/net/netlink (thanks Phil)). Et voilà!

My idea to exploit this was to create a 666 device node that would give direct access to a mounted partition and to chmod +s some binary file we control by directly writing to the block device (there are userland tools and lib to do this easily, see debugfs for instance).

Phil also came-up with the idea of replacing /dev/urandom and /dev/random with /dev/zero (so called "debian emulation" backdoor).
Raph then found an even better way: on Ubuntu, Debian and others, you can exploit "95-udev-late.rules" and run arbitrary commands by using the "remove" action.

And that's it for a slick exploit. 40 lines of C (5 lines of Python for Phil). Pretty simple, cross architecture, reliable.
And it can escape chroots and some MAC-constrained environments (as long as you can create netlink sockets).

Saturday, April 4, 2009

26

Yesterday, a friend of mine turned 26. I know what you're thinking, this is very exciting. Indeed, not every year your age is between a square (5^2) and a cube (3^3)!

How often does this happen? Well actually, Wikipedia states that 26 is the only number between a square and a cube (which is not exactly true, but read on). I thought this was cool, let my friend know in a creepy happy birthday e-mail and got back to work.

But the same day, I was dragged to a Polish club by friends. It was horrible: the music was awful, absolutely nobody was dancing, nobody was talking and nothing happened. I was very bored, so I started working on the demonstration that 26 was the only number between a square and a cube. Excluding the fact that the bouncer seemed worried that I was standing still (and alone, remember) on the dance floor, it was the perfect activity to have in this club.
I first thought it would be easy, but as it turned out the demonstration ended up involving quadratic integer rings and unique factorization domains.

So let's start by demonstrating that 26 is the only number preceded by a square and succeeded by a cube. We want to find all integers a and b such as b^3=a^2+2.
You can easily prove that a and b are odd: if b is even, 2 divides a^2, so 2 divides a and 4 divides a^2. Consequently, 4 divides b^3 - a^2 so 4 divides 2. Impossible. So b is odd, which implies a^2 is odd and a is odd.

Then, my first intuition was to use the known solution to this equation to prove there was no other solution. a^2-5^2=b^3-3^3, so (a-5)(a+5)=(b-3)(b^2+3b+9). But this is tedious, there isn't much you can do with this annoying (b^2+3b+9).
Well this is as far as I've got in the club. I attempted to make others in the club party one more time and then decided to head home and started working on the proof again. Sad Friday night.

When I was in college, I really liked the kind of demonstrations where we used a superset of a given set to prove properties in the first set. Here, we see b^3=a^2+2 and feel hopeless. If only a^2+2 could be factorized... Well, it can be factorized. I didn't spend my youth learning about Cauchy sequences and how to construct R and his algebraic closure C for nothing! So let s be i*sqrt(2) and we have b^3=(a-s)(a+s). But what can we do now ?
I wanted to play with prime numbers, divisors and gcds and now we're stuck with complex numbers. Hold on! It turns out that the set of numbers written in the form x+y*s (with x and y integers), written Z[s] with the usual operations is not only a ring (called a quadratic integer ring), but also an Euclidian domain and that its units are 1 and -1 (proof of this another time). We can still have some fun (for some definitions of fun, including any that would qualify the aforementioned Polish club as fun).

So we now have (a-s)(a+s)=b^3. Let's prove that a-s and a+s are mutually prime. Let g be their gcd. g must divide (a+s) - (a-s) = 2s = -s^3. s is prime in Z[s], so g=+- s^x with x being 0, 1, 2 or 3. But g also divides a+s, if x>0, then s divides a+s and so s divides a. But we already know (from the club, remember), that a is odd. And s (i*sqrt(2)) cannot divide an odd number in Z[s]. So x=0 and a-s and a+s are mutually prime.

Since Z[s] is an Euclidian domain, the fundamental theorem of arithmetic holds (Z[s] is a unique factorization domain): any number in Z[s] can be written as the product of the elements of a unique set of prime numbers (and units). So we can write a-s, a+s and b^3 as products of prime numbers (and units). Since a-s and a+s are mutually prime, a-s and a+s are cubes multiplied by some units. Since 1 and -1 are both cubes, and the only units of Z[s], a-s and a+s are cubes.

So let's write a+s=(m+ns)^3 with m and n integers. We get: a+s=m^3-6mn^2+n*(3m^2-2n^2)s. The unicity of m' and n' such as x = m'+n'*s in Z[s] (with m' and n' in Z) gives: n*(3m^2-2n^2)=1. So n=+-1. If n = 1, we have 3m^2-2=1 and m = +-1. If n =-1 there is no solution for m. So n=1 and m = +-1. We also have a=m^3-6mn^2. So a = 5 or a = -5 wich in turn gives b=3.

So the only integer solutions to b^3=a^2+2 are (a,b)=(5,3) and (a,b)=(-5,3) and 26 is the only integer preceded by a square and followed by a cube.
Happy birthday Parisa!

Now what about an integer being preceded by a cube and followed by a square? If Wikipedia is right there is no integer solution to b^3=a^2-2. Well there is actually one trivial solution (b=-1 and a=+-1), so Wikipedia is wrong, but is it the only solution? We could be tempted to follow a similar approach, let s' be sqrt(2) and use Z[s'], which is also a ring. But -1 and 1 are not the only units: s-1 and s+1 are also units since (s'-1)(s'+1)=1 and so we have an infinite number of units written +-(s'-1)^m and +-(s'+1)^m.
Moreover, is Z[s'] still a unique factorization domain ? Not sure. But you may have to find out if you want to prove 0 is the only number preceded by a cube and followed by a square (for example to celebrate your 0-aged new born baby).

Wednesday, April 1, 2009

Massive exploitation of instant messaging applications proved feasible

EDIT: While most realized this was an April fool's joke, only a few figured out that it was also a genuine smiley shellcode encoder. However, the security implications are of course non existent. And we have been slashdoted!

Yoann Guillot and myself have been assessing the security of instant communication applications for a couple of years.
For quite some time now, we have both suspected that it was possible to conduct both stealth and massive attacks on popular chat clients such as MSN, AIM, Trillian or mIRC.

Today, we have verified our intuition by creating an encoder that can make any shellcode look like a smiley. It is possible to encode malicious shellcodes in emoticons, leaving exploits indistinguishable from genuine chat messages.

This would make massive attacks against instant messaging applications impossible to catch by anti-virus, IDS or similar signature based technologies. Moreover, it is possible to conduct attacks with plausible deniability.

The potential for mass exploitation is undeniable. We are urging Microsoft, AOL and other administrators of popular chat networks to ban smileys (especially animated ones) until all the consequences of this attack have been understood. Twitter and Facebook are likely vulnerable too, although we didn't conduct specific research yet on those networks.

This proof of concept program will compile the sample included shellcode, encode it into a valid MSN smiley and compile a test C program by using metasm. While the example shellcode and the compiled test program are both targeting Linux, you can supply any shellcode you want, including a Windows one, via the command line.

Please, use as follow:

"apt-get install libc6-dev-i386 mercurial ruby" if required
"hg clone https://metasm.cr0.org/hg/metasm/"
"cd metasm"
put smile.rb in the metasm directory
"ruby ./smile.rb"
"./test.lol"