About two or three days ago, me and slasher had our special version of wargames. We quickly noticed that although the system we came across used a vulnerable kernel, it actually had all the writable partitions mounted as noexec. So what could we do?
It is of common belief that interpreted languages like perl, ruby or python, are pretty useful when you are under strict noexec permissions. The source scripts can be executed without requiring +x on the target .pl, .rb or .py file. So that was the next thing we looked for and we immediately found out that the target box had perl and python installed.
Perl and python are both very nice programming languages, but personally I prefer python. Well, actually it is not only a matter of personal taste. Python supports a feature called FFI (Foreign Function Interface) which allows any python coder to directly call any C function from any shared object. FFI is not a python specific feature, in fact, the term FFI usually refers to interpreter infrastructure. For more info you can have a look here and here. Python’s FFI includes support for structures, unions and… pointers!
Great news! Since python permits pointer usage via the ctypes FFI library, it is also implied that we can allocate, deallocate, dereference and even find the address of a buffer within the context of an interpreted language (does perl have a feature like that?). By combining what was said so far, we can build or port any exploit in python. We chose to port the public exploit for the proto_ops[] NULL pointer dereference, a bug discovered by Julien Tinnes and Travis Ormandy of Google security, and we did have a great success.
sh-3.2$ uname -a
Linux xxx 2.6.27.8-xxx #4 SMP PREEMPT Sun Aug 9 20:31:40 EEST 2009 i686 Intel(R) Core(TM)2 Duo CPU T5450 @ 1.66GHz GenuineIntel GNU/Linux
sh-3.2$ python proto_ops_exp.py
Linux <= 2.6.30.4 proto_ops[] NULL pointer dereference exploit
Using Python's FFI to bypass noexec!
# Current uid=101 and current gid=102
# Reported page size is 4096 bytes
# Copying uid and gid in the heap
# Copied 4 bytes at 0x082c3940
# Copied 4 bytes at 0x082c3930
# Copying "/bin/sh" string in the heap
# Copied 7 bytes at 0x082c4f50
# Copying exit_code() in the heap
# Copied 15 bytes at 0x08276678
# Copying exit_stack[] in the heap
# Copied 4096 bytes at 0x082dfb80
# Loading kernel_code() in the null page
# Copied 406 bytes of shellcode at 0x00000000
# If you don't get root you are an idiot
bash-3.2# id
uid=0(root) gid=0(root) groups=102(xxx)
bash-3.2# echo burp && exit
burp
exit
For very obvious reasons, I won’t publish the python code of the above exploit. It is fairly easy for any programmer to code one of his own (python manuals are self explanatory and the vulnerability is public since around August 13th). So, have a nice time porting your codes!
– dp