Docker Pentesting

Last modified: 2023-10-11

Container Privilege Escalation

Docker is a set of platform as a service products that use OS-level virtualization to deliver software in packages called containers. Default ports are 2375, 2376.


Find Docker Binary

If we cannot use docker command by default, we need to find the docker binary.

find / -name "docker" 2>/dev/null

Basic Commands

# List images
docker images
docker image ls
# The history of an image
docker image history <image-name>

# List containers running
docker container ls
# or
docker ps

# List all containers
docker container ls -a
# or
docker ps -a

# List secrets
docker secret ls

# Check configuration of container
docker inspect --format='{{json .Config}}' <container_id_or_name>

# Get a port which is used by the container
docker port <container_id_or_name>

# Scan vulnerabilies (CVEs)
docker scan cves <image>
docker scan cves alpine

# View the SBOM (Software Bill of Materials) for an image
# We can investigate vulnerabilities from the list of packages.
docker sbom alpine:latest
# Json format
docker sbom alpine:latest --format syft-json

# Spawn the shell in the container
docker exec -it <container_id> /bin/bash

# Kill the running docker container
docker kill <container_id>

Check if Containers Running

In target machine, observe the network status by running netstat or ss command.

netstat -punta
# or
ss -ltu

# -------------------------------------------------------

tcp  0  0*  LISTEN  -

Basic Operations

Run a New Container

First check the docker images listed.

docker images

Then run a new container from the image.

# -d: detached mode (background)
# -p: map the port of the host to the port in the container
docker run -dp 80:80 <image-name>

If you want to run a new container from a remote repository, run the following.

# --rm: Removes the anonymous volumes when the container is removed
# -i: interactive
# -t: tty
# --network=host: The container is not isolated from the Docker host. The IP address is your own home IP address.
docker run --rm -it --network=host <repository>/<image>

# /bin/bash: spawn a shell within the container
docker run -it nginx /bin/bash

Start a Container which is stopped

# List all containers and check the target ID
docker container ls -a

# Start the container
docker container start <container-id>

Run Commands in a Container

# List containers running and check the target container ID
docker ps

# Run commands by giving the container ID
docker exec <container-id> whoami
docker exec <container-id> cat sample.txt

Stop a Container

# List running containers and check the target container ID
docker ps

# Stop the container by giving the ID
docker stop <container-id>

Remove a Container

# List all containers and check the target container ID
docker ps -a

# Remove the container by givine the ID
docker rm <container-id>
# Force to remove the running container (-f)
docker rm -f <container-id>

Build a Container Image

First off, create a Dockerfile in the root directory of the project.

FROM node:12-alpine

RUN apk add --no-cache python2 g++ make
COPY . .
RUN yarn install --production
CMD ["node", "src/index.js"]

Now run the following command to build the container image.
This command uses the Dockerfile.

# -t: name a tag of the image
docker build -t <tag-name> .

Scan a Container Image

docker scan <image-name>

Pull a Docker Image

We need to download a docker image to start a container at first.

docker pull <image>
docker pull nginx

# Specify a tag
docker pull <image>:<tag>
docker pull nginx:latest
docker pull nginx:stable

Remove a Docker Image

# List images and check the target image ID
docker images

# Remove the image by giving the ID
docker rmi <image-id>

Publish a Docker Image

Before doing below, you need to sign up the Docker Hub and sign in, then create a new repository in your dashboard.

# Login
docker login -u <your-username>

# Tag a new image
docker tag <source-image> <your-username>/<target-image>

# Push
docker push <your-username>/<target-image>