# AWS - EKS Post Exploitation

{{#include ../../../../banners/hacktricks-training.md}}

## EKS

For mor information check

{{#ref}}
../../aws-services/aws-eks-enum.md
{{#endref}}

### Enumerate the cluster from the AWS Console

If you have the permission **`eks:AccessKubernetesApi`** you can **view Kubernetes objects** via AWS EKS console ([Learn more](https://docs.aws.amazon.com/eks/latest/userguide/view-workloads.html)).

### Connect to AWS Kubernetes Cluster

- Easy way:

```bash
# Generate kubeconfig
aws eks update-kubeconfig --name aws-eks-dev
```

- Not that easy way:

If you can **get a token** with **`aws eks get-token --name <cluster_name>`** but you don't have permissions to get cluster info (describeCluster), you could **prepare your own `~/.kube/config`**. However, having the token, you still need the **url endpoint to connect to** (if you managed to get a JWT token from a pod read [here](aws-eks-post-exploitation/README.md#get-api-server-endpoint-from-a-jwt-token)) and the **name of the cluster**.

In my case, I didn't find the info in CloudWatch logs, but I **found it in LaunchTemaplates userData** and in **EC2 machines in userData also**. You can see this info in **userData** easily, for example in the next example (the cluster name was cluster-name):

```bash
API_SERVER_URL=https://6253F6CA47F81264D8E16FAA7A103A0D.gr7.us-east-1.eks.amazonaws.com

/etc/eks/bootstrap.sh cluster-name --kubelet-extra-args '--node-labels=eks.amazonaws.com/sourceLaunchTemplateVersion=1,alpha.eksctl.io/cluster-name=cluster-name,alpha.eksctl.io/nodegroup-name=prd-ondemand-us-west-2b,role=worker,eks.amazonaws.com/nodegroup-image=ami-002539dd2c532d0a5,eks.amazonaws.com/capacityType=ON_DEMAND,eks.amazonaws.com/nodegroup=prd-ondemand-us-west-2b,type=ondemand,eks.amazonaws.com/sourceLaunchTemplateId=lt-0f0f0ba62bef782e5 --max-pods=58' --b64-cluster-ca $B64_CLUSTER_CA --apiserver-endpoint $API_SERVER_URL --dns-cluster-ip $K8S_CLUSTER_DNS_IP --use-max-pods false
```

<details>

<summary>kube config</summary>

```yaml
describe-cache-parametersapiVersion: v1
clusters:
  - cluster:
      certificate-authority-data:  
      server: https://6253F6CA47F81264D8E16FAA7A103A0D.gr7.us-west-2.eks.amazonaws.com
    name: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
contexts:
  - context:
      cluster: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
      user: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
    name: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
current-context: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
kind: Config
preferences: {}
users:
  - name: arn:aws:eks:us-east-1:<acc-id>:cluster/<cluster-name>
    user:
      exec:
        apiVersion: client.authentication.k8s.io/v1beta1
        args:
          - --region
          - us-west-2
          - --profile
          - <profile>
          - eks
          - get-token
          - --cluster-name
          - <cluster-name>
        command: aws
        env: null
        interactiveMode: IfAvailable
        provideClusterInfo: false
```

</details>

### From AWS to Kubernetes

Historically, the **creator** of an **EKS cluster** received hidden Kubernetes admin access that was not visible in `aws-auth`. In current EKS clusters, this depends on the cluster access configuration. `bootstrapClusterCreatorAdminPermissions` controls whether the creator is added as a cluster-admin access entry during creation, and EKS access entries make that admin path visible and revocable through the EKS API. Older clusters or clusters that still rely on `aws-auth` might still have legacy creator behavior, so confirm the `accessConfig`, list access entries, and review CloudTrail instead of assuming the creator always has unremovable `system:masters`.

#### Abusing configmap

The traditional way to grant **access to over K8s to more AWS IAM users or roles** is using the **configmap** **`aws-auth`**.

> [!WARNING]
> Therefore, anyone with **write access** over the config map **`aws-auth`** will be able to **compromise the whole cluster**.

For more information about how to **grant extra privileges to IAM roles & users** in the **same or different account** and how to **abuse** this to [**privesc check this page**](../../../kubernetes-security/abusing-roles-clusterroles-in-kubernetes/index.html#aws-eks-aws-auth-configmaps).

Check also[ **this awesome**](https://blog.lightspin.io/exploiting-eks-authentication-vulnerability-in-aws-iam-authenticator) **post to learn how the authentication IAM -> Kubernetes work**.

#### Abusing Access Entries

AWS implements an additional way to grant IAM users access to the Kubernetes cluster through access entries. If you have the `eks:CreateAccessEntry` and `eks:AssociateAccessPolicy` permissions, you may also be able to assign a Kubernetes administrator role to either your user or a specific role.

First, **create an access entry for your user or role**:

```
aws eks create-access-entry --cluster-name <cluster_name> --region <region> --principal-arn <arn_from_your_user_or_role> --type STANDARD
```

With that entry created, you may now be able to assign a policy directly to it. There is a built-in AWS policy called *AmazonEKSClusterAdminPolicy* that may be used directly. Keep in mind that if your environment has some other custom policies that also grant elevated privileges in EKS, you may change the `--policy-arn` to any of those:

```
aws eks associate-access-policy --cluster-name <cluster_name> --region <region> --principal-arn <arn_from_your_user_or_role> --policy-arn arn:aws:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy --access-scope type=cluster
```

You can search for this policy in AWS official documentation [**here**](https://docs.aws.amazon.com/eks/latest/userguide/access-policy-permissions.html#access-policy-permissions-amazoneksclusteradminpolicy)

From this point on, you may now be able to request a *k8s* token and interact with the cluster as an administrator:

```
aws eks get-token --cluster-name <cluster_name> --output json | jq -r '.status.token'
```

### From Kubernetes to AWS

It's possible to allow an **OpenID authentication for kubernetes service account** to allow them to assume roles in AWS. Learn how [**this work in this page**](../../../kubernetes-security/kubernetes-pivoting-to-clouds.md#workflow-of-iam-role-for-service-accounts-1).

### GET Api Server Endpoint from a JWT Token

Decoding the JWT token we get the cluster id & also the region. ![image](https://github.com/HackTricks-wiki/hacktricks-cloud/assets/87022719/0e47204a-eea5-4fcb-b702-36dc184a39e9) Knowing that the standard format for EKS url is

```bash
https://<cluster-id>.<two-random-chars><number>.<region>.eks.amazonaws.com
```

Didn't find any documentation that explain the criteria for the 'two chars' and the 'number'. But making some test on my behalf I see recurring these one:

- gr7
- yl4

Anyway are just 3 chars we can bruteforce them. Use the below script for generating the list

```python
from itertools import product
from string import ascii_lowercase

letter_combinations = product('abcdefghijklmnopqrstuvwxyz', repeat = 2)
number_combinations = product('0123456789', repeat = 1)

result = [
	f'{''.join(comb[0])}{comb[1][0]}'
	for comb in product(letter_combinations, number_combinations)
]

with open('out.txt', 'w') as f:
	f.write('\n'.join(result))
```

Then with wfuzz

```bash
wfuzz -Z -z file,out.txt --hw 0 https://<cluster-id>.FUZZ.<region>.eks.amazonaws.com
```

> [!WARNING]
> Remember to replace & .

### Bypass CloudTrail

If an attacker obtains credentials of an AWS with **permission over an EKS**. If the attacker configures it's own **`kubeconfig`** (without calling **`update-kubeconfig`**) as explained previously, the **`get-token`** doesn't generate logs in Cloudtrail because it doesn't interact with the AWS API (it just creates the token locally).

So when the attacker talks with the EKS cluster, **cloudtrail won't log anything related to the user being stolen and accessing it**.

Note that the **EKS cluster might have logs enabled** that will log this access (although, by default, they are disabled).

### EKS Ransom?

By default the **user or role that created** a cluster is **ALWAYS going to have admin privileges** over the cluster. And that the only "secure" access AWS will have over the Kubernetes cluster.

So, if an **attacker compromises a cluster using fargate** and **removes all the other admins** and d**eletes the AWS user/role that created** the Cluster, ~~the attacker could have **ransomed the cluste**~~**r**.

> [!TIP]
> Note that if the cluster was using **EC2 VMs**, it could be possible to get Admin privileges from the **Node** and recover the cluster.
>
> Actually, If the cluster is using Fargate you could EC2 nodes or move everything to EC2 to the cluster and recover it accessing the tokens in the node.

{{#include ../../../../banners/hacktricks-training.md}}



