Magic Writeup - HackTheBox
Magic is a Linux box that chains a SQL injection auth bypass into a polyglot image upload for RCE, then reuses a database password to reach a real OS account, and finishes with a PATH hijack against a custom SUID binary. Set the working variables:
Reconnaissance
Port scan
RustScan for a fast look at open ports:
PORT STATE SERVICE REASON 22/tcp open ssh syn-ack ttl 63 80/tcp open http syn-ack ttl 63
Service and version detail on the two open ports:
22/tcp open ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) 80/tcp open http Apache httpd 2.4.29 Service Info: Host: 127.0.1.1; OS: Linux
OpenSSH 7.6p1 and Apache 2.4.29. SSH has no obvious version bug, so the web app is the way in.
Web Enumeration
Directory brute force with ffuf. The first pass without a size filter was noisy because the wordlist comment lines reflected back as false 200s at size 4052, so I filtered them out:
login.php [Status: 200, Size: 4221, Words: 1179, Lines: 118] index.php [Status: 200, Size: 4051, Words: 491, Lines: 60]
login.php is a login portal. That is the next target.
Initial Access
SQL injection auth bypass
Default creds failed on login.php. A classic boolean auth bypass in the username field worked:
' OR 1=1-- -
That logged straight in and dropped me into the app, which has an image upload feature.
Polyglot image upload to RCE
The upload validates on image content, so I built a polyglot: valid JPEG magic bytes followed by a PHP payload. Apache still executes it as PHP because of the .php.jpg double extension:
Upload succeeded. Now I need to find where it landed.
Locating the shell
feroxbuster to map the upload path:
301 GET http://$TARGET_IP/images => /images/ 301 GET http://$TARGET_IP/images/uploads => /images/uploads/ 200 GET http://$TARGET_IP/images/uploads/logo.png 200 GET http://$TARGET_IP/login.php <snip static assets and stock gallery images under /images/fulls and /assets>
Uploads land in /images/uploads/. Confirm execution:
It is working!www-data
Arbitrary command execution as www-data.
Reverse shell
Fire a Python one liner through the cmd parameter:
Catch it:
Shell as www-data. Time to hunt for credentials.
Lateral Movement
Database credentials on disk
The web root holds a config file with DB creds:
<?php
class Database
{
private static $dbName = 'Magic' ;
private static $dbHost = 'localhost' ;
private static $dbUsername = 'theseus';
private static $dbUserPassword = '$THESEUS_DB_PASSWORD';
<snip>
DB login is theseus with $THESEUS_DB_PASSWORD. No MySQL client on the box though:
Command 'mysql' not found, but can be installed with: apt install mysql-client-core-5.7
MySQL is bound to localhost. I will tunnel it back to my box.
Chisel tunnel to MySQL
Attacker side:
Target side:
client: Connected (Latency 294ms)
The target's 127.0.0.1:3306 is now reachable locally at 127.0.0.1:3306.
Loot the login table
MySQL [(none)]> use Magic MySQL [Magic]> show tables; +-----------------+ | Tables_in_Magic | +-----------------+ | login | +-----------------+ MySQL [Magic]> select * from login; +----+----------+-------------------+ | id | username | password | +----+----------+-------------------+ | 1 | admin | $ADMIN_PASSWORD | +----+----------+-------------------+
The admin password $ADMIN_PASSWORD is worth testing for reuse. SSH rejects it because the account is key only:
theseus@$TARGET_IP: Permission denied (publickey).
But su from the existing webshell does not care about SSH policy:
Password: theseus@ubuntu:/tmp$
Shell as theseus, user access reached. Now for root.
Privilege Escalation
SUID enumeration
-rwsr-x--- 1 root users 22040 Oct 21 2019 /bin/sysinfo <snip standard distro and snap-core SUID binaries: passwd, newgrp, sudo, pkexec, su, mount, umount, ping, chfn, chsh, gpasswd, ssh-keysign, none of them abnormal>
/bin/sysinfo is non standard, owned root:users and part of no stock package. That is the lead.
Analyzing sysinfo
====================Hardware Info==================== lshw -short ====================Disk Info==================== fdisk -l ====================CPU Info==================== cat /proc/cpuinfo ====================MEM Usage===================== free -h
It shells out to free, fdisk, lshw by bare name, no absolute paths. Running SUID root, that is a PATH hijack.
PATH hijack to root
Plant a malicious free in /tmp, prepend /tmp to $PATH, and run the binary:
... ====================MEM Usage===================== root@ubuntu:/tmp#
sysinfo resolved free from /tmp and ran /bin/bash -p as root.
Stable root session
The SUID shell printed output roughly, so I kicked back a clean reverse shell:
connect from $TARGET_IP # whoami root
Root reached.