XposedAPI Writeup - Proving Grounds
Created October 8, 2026 • Last updated October 8, 2026 • 3 min read
XposedAPI exposes an internal management API meant only for localhost. An X-Forwarded-For header bypasses its IP restriction, an LFI endpoint discloses its source code, and unsanitized input in an update endpoint gives command injection. A SUID wget binary then overwrites /etc/passwd for root.
Reconnaissance
Nmap
Scan the target.
PORT STATE SERVICE VERSION 22/tcp open ssh OpenSSH 13337/tcp open http Python/Flask
Explain command
| -p- | Scan all 65535 TCP ports. |
| -sCV | Run the default scripts and probe service versions. |
Port 13337 serves an API management interface, with a banner warning that it is “not meant to be exposed to remote users.” Its documented endpoints include /logs and /update.
Exploitation
WAF bypass with X-Forwarded-For
/logs returns 403 Forbidden remotely. Spoof the client origin to satisfy the IP check.
404 Not Found
Explain command
| -H | Set an HTTP request header. |
A 404 instead of a 403 confirms the IP restriction only checks this header, not the real client address.
LFI to source disclosure
/logs also accepts a file parameter.
root:x:0:0:root:/root:/bin/bash <snip> clumsyadmin:x:1000:1000::/home/clumsyadmin:/bin/bash
Arbitrary file read. Pull the application’s own source code.
os.system("curl{} -o /home/clumsyadmin/app".format(data['url']))
The /update endpoint passes the request’s url field straight into os.system() with no sanitization.
OS command injection via /update
Start a listener, then inject a reverse shell through the url field.
clumsyadmin@xposedapi:~$ id uid=1000(clumsyadmin) gid=1000(clumsyadmin) groups=1000(clumsyadmin)
Shell as clumsyadmin and local.txt.
Privilege Escalation
SUID wget to overwrite /etc/passwd
Search for SUID binaries.
/usr/bin/wget
wget is SUID and can write files as root. Per GTFOBins, overwriting /etc/passwd with a new UID-0 entry gives root. Generate a password hash for the new user.
$1$user3$rAGRVf5p2jYTqtqOW5cPu/
Build a modified passwd file based on the target’s own, with an extra root-level entry appended.
user3:$1$user3$rAGRVf5p2jYTqtqOW5cPu/:0:0:/root:/root:/bin/bash
Host it and overwrite the target’s copy through the SUID binary.
Switch to the new UID-0 account.
Password: pass123 root@xposedapi:~# id uid=0(root) gid=0(root) groups=0(root)
The forged /etc/passwd entry gives a root shell.