Skip to content

Commit

Permalink
Revamp README
Browse files Browse the repository at this point in the history
  • Loading branch information
christophetd committed Apr 11, 2023
1 parent a735676 commit 030c2b4
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 53 deletions.
138 changes: 86 additions & 52 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,80 +1,106 @@
# Managed Kubernetes Auditing Toolkit (MKAT)

**Note**: At this time (pre-release), this is highly beta.
MKAT is a toolkit for identifying common security issues in managed Kubernetes environments. It is focused on AWS EKS at the moment, but will be extended to other managed Kubernetes environments in the future.

## Building
## Pre-requisites

Make sure you are authenticated against your cluster, and to AWS. MKAT uses your current AWS and kubectl authentication contexts.

```bash
make
./mkat --help
aws eks update-kubeconfig --name <cluster-name>
```

## Usage
## Features

For now, please refer to the autogenerated CLI documentation in [docs](./docs). Pre-requisites:
### Identify trust relationships between K8s service accounts and AWS IAM roles

* You need to be authenticated against an EKS cluster
* For find-role-relationships, you also need to be authenticated against the same AWS account as where the EKS cluster is running
[IAM Roles for Service Accounts](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) is
a popular mechanism to allow pods to assume AWS IAM roles, by exchanging a Kubernetes service account token for AWS credentials through the AWS STS API (`AssumeRoleWithWebIdentity`).

## Sample outputs
MKAT can identify the trust relationships between K8s service accounts and AWS IAM roles, and display them in a table or as a graph.

### Find role relationships
```bash
$ mkat eks find-role-role-relationships
_ _
_ __ ___ | | __ __ _ | |_
| '_ ` _ \ | |/ / / _` | | __|
| | | | | | | < | (_| | | |_
|_| |_| |_| |_|\_\ \__,_| \__|
2023/04/12 00:25:15 Connected to EKS cluster mkat-cluster
2023/04/12 00:25:15 Retrieving cluster OIDC issuer
2023/04/12 00:25:16 Listing roles in the AWS account
2023/04/12 00:25:18 Listing K8s service accounts in all namespaces
2023/04/12 00:25:19 Analyzing the trust policy of 5 IAM roles that have the cluster's OIDC provider in their trust policy
+-----------+----------------------+-------------------+-------------------------------------------------------+
| NAMESPACE | SERVICE ACCOUNT | POD | ASSUMABLE ROLE ARN |
+-----------+----------------------+-------------------+-------------------------------------------------------+
| default | apigw-sa | apigw | arn:aws:iam::677301038893:role/apigw-role |
| | | | arn:aws:iam::677301038893:role/s3-reader |
| | inventory-service-sa | inventory-service | arn:aws:iam::677301038893:role/inventory-service-role |
| | | | arn:aws:iam::677301038893:role/s3-reader |
| | kafka-proxy-sa | kafka-proxy | arn:aws:iam::677301038893:role/kafka-proxy-role |
| | rate-limiter-sa | rate-limiter | arn:aws:iam::677301038893:role/rate-limiter-role |
+-----------+----------------------+-------------------+-------------------------------------------------------+
```

It can also generate a `dot` output for graphic visualization:

```bash
$ mkat eks find-role-relationships datadog-pde-test-eks-cluster-us-east-1

2023/04/05 12:33:57 Retrieving cluster OIDC issuer
2023/04/05 12:33:58 Listing roles in the AWS account
2023/04/05 12:33:59 Listing K8s service accounts
+-------------+------------------------------+-----------------------------------------------+--------------------------------------------------------------------------------------------+
| NAMESPACE | SERVICE ACCOUNT | POD | ASSUMABLE ROLE ARN |
+-------------+------------------------------+-----------------------------------------------+--------------------------------------------------------------------------------------------+
| kube-system | aws-load-balancer-controller | aws-load-balancer-controller-56bbd74695-9sw79 | arn:aws:iam::677301038893:role/AmazonEKSLoadBalancerControllerRole |
| | | aws-load-balancer-controller-56bbd74695-9sw79 | arn:aws:iam::677301038893:role/ChristopheSampleIRSARoleThatCanBeAssumedByAnyPodInCluster |
| | | aws-load-balancer-controller-56bbd74695-b7hb2 | arn:aws:iam::677301038893:role/AmazonEKSLoadBalancerControllerRole |
| | | aws-load-balancer-controller-56bbd74695-b7hb2 | arn:aws:iam::677301038893:role/ChristopheSampleIRSARoleThatCanBeAssumedByAnyPodInCluster |
+-------------+------------------------------+-----------------------------------------------+--------------------------------------------------------------------------------------------+
| default | christophe-test-sa | christophe-irsa-deployment-7b476dfdb5-hkxdg | arn:aws:iam::677301038893:role/ChristopheSampleIRSARoleThatCanBeAssumedByAnyPodInCluster |
| | | christophe-irsa-deployment-7b476dfdb5-hkxdg | arn:aws:iam::677301038893:role/ChristopheSampleIRSARoleThatCanBeAssumedByAnyPodInDefaultNS |
| | | christophe-irsa-deployment-7b476dfdb5-hkxdg | arn:aws:iam::677301038893:role/ChristopheSamplePodIRSARole |
+-------------+------------------------------+-----------------------------------------------+--------------------------------------------------------------------------------------------+
$ mkat eks find-role-role-relationships --output-format dot --output-file roles.dot
$ dot -Tpng -O roles.dot
$ open roles.dot.png
```

### Find secrets
![Mapping trust relationships](./examples/irsa.png)

(Note: the secrets displayed below are fake)
### Find hardcoded AWS credentials in K8s resources

MKAT can identify hardcoded AWS credentials in K8s resources such as Pods, ConfigMaps, and Secrets.
It has a low false positive rate, and only alerts you if it finds both an AWS access key ID and a secret access key in the same Kubernetes resource.
It's also able to work with unstructured data, i.e. if you have a ConfigMap with an embedded JSON or YAML document that contains AWS credentials.

```bash
$ mkat eks find-secrets
2023/04/05 12:34:30 Searching for AWS secrets in ConfigMaps...
2023/04/05 12:34:32 Analyzing 21 ConfigMaps...
2023/04/05 12:34:32 Searching for AWS secrets in Secrets...
2023/04/05 12:34:32 Analyzing 52 Secrets...
2023/04/05 12:34:32 Searching for AWS secrets in Pod definitions...
2023/04/05 12:34:33 Analyzing 17 Pod definitions...
+-----------+-----------+--------------------------------------------------------+------------------------------------------+
| NAMESPACE | TYPE | NAME | VALUE |
+-----------+-----------+--------------------------------------------------------+------------------------------------------+
| default | ConfigMap | my-config (key my-app-config) | AKIAZ3MSJV4WWNKWW5FG |
| default | ConfigMap | my-config (key my-app-config) | HP8lBRs8X50F/0nCAXqEPQ95+jlG/0pLdlNui2XF |
| default | Pod | nginx-with-aws-creds (environment variable AWS_ACCESS) | AKIAZ3MSJV4WWNKWW5FG |
| default | Pod | nginx-with-aws-creds (environment variable AWS_SECRET) | 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 |
+-----------+-----------+--------------------------------------------------------+------------------------------------------+
_ _
_ __ ___ | | __ __ _ | |_
| '_ ` _ \ | |/ / / _` | | __|
| | | | | | | < | (_| | | |_
|_| |_| |_| |_|\_\ \__,_| \__|
2023/04/12 00:33:24 Connected to EKS cluster mkat-cluster
2023/04/12 00:33:24 Searching for AWS secrets in ConfigMaps...
2023/04/12 00:33:25 Analyzing 10 ConfigMaps...
2023/04/12 00:33:25 Searching for AWS secrets in Secrets...
2023/04/12 00:33:25 Analyzing 45 Secrets...
2023/04/12 00:33:25 Searching for AWS secrets in Pod definitions...
2023/04/12 00:33:25 Analyzing 8 Pod definitions...
+-----------+--------+-----------------------------------------+------------------------------------------+
| NAMESPACE | TYPE | NAME | VALUE |
+-----------+--------+-----------------------------------------+------------------------------------------+
| default | Secret | kafka-proxy-aws (key aws_access_key_id) | AKIAZ3MSJV4WWNKWW5FG |
| default | Secret | kafka-proxy-aws (key aws_secret_key) | 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 |
+-----------+--------+-----------------------------------------+------------------------------------------+
```
### Test IMDS access from pods
### Test if pods can access the AWS Instance Metadata Service (IMDS)
Pods accessing the EKS nodes Instance Metadata Service is a [common and dangerous attack vector](https://blog.christophetd.fr/privilege-escalation-in-aws-elastic-kubernetes-service-eks-by-compromising-the-instance-role-of-worker-nodes/)
that can be used to escalate privileges. MKAT can test if pods can access the IMDS. It tests it by creating a temporary pod that tries to access the IMDS, and then deletes it.
```eks
```bash
$ mkat eks test-imds-access
2023/04/05 12:35:27 Testing if IMDS is accessible to pods by creating a pod that attempts to access it
IMDS is accessible and allows any pod to retrieve credentials for the AWS role eksctl-datadog-pde-test-eks-clust-NodeInstanceRole-1BO32251HD3PV
_ _
_ __ ___ | | __ __ _ | |_
| '_ ` _ \ | |/ / / _` | | __|
| | | | | | | < | (_| | | |_
|_| |_| |_| |_|\_\ \__,_| \__|

2023/04/12 00:35:10 Connected to EKS cluster mkat-cluster
2023/04/12 00:35:10 Testing if IMDS is accessible to pods by creating a pod that attempts to access it
2023/04/12 00:35:15 IMDS is accessible and allows any pod to retrieve credentials for the AWS role eksctl-mkat-cluster-nodegroup-ng-NodeInstanceRole-AXWUFF35602Z
```
## Vision tl;dr
* We show cloud-specific risks, not generic ones
* We only show effective risk, not "potential" / graph-based risk
## How does MKAT compare to other tools?
| **Tool** | **Description** |
Expand All @@ -87,3 +113,11 @@ IMDS is accessible and allows any pod to retrieve credentials for the AWS role e
| [kdigger](https://github.com/quarkslab/kdigger) | kdigger is a general-purpose context discovery tool for Kubernetes penetration testing. It does not attempt to be specific to managed K8s environments. |
| [kubeletmein](https://github.com/4ARMED/kubeletmein) | kubeletmein _is_ specific to managed K8s environments. It's an utility to generate a kubeconfig file using the node's IAM credentials, to then use it in a compromised pod. |
| [hardeneks](https://github.com/aws-samples/hardeneks) | hardeneks _is_ specific to managed K8s environments, but only for EKS. It identifies issues and lack of best practices inside of the cluster, and does not focus on cluster to cloud pivots. |
## Roadmap
We currently plan to:
* Add a feature to identify EKS pods that are exposed through an AWS load balancer, through the [aws-load-balancer-controller](https://github.com/kubernetes-sigs/aws-load-balancer-controller)
* Add support for GCP GKE
* Allow scanning for additional types of cloud credentials
* Enhance the IAM role trust policy evaluation logic to take into account additional edge cases
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ func getDotOutput(cluster *eks.EKSCluster) (string, error) {
if pod.ServiceAccount == nil || len(pod.ServiceAccount.AssumableRoles) == 0 {
continue
}
podLabel := fmt.Sprintf(` "Pod %s/%s" `, namespace, pod.Name)
podLabel := fmt.Sprintf(` "Pod %s" `, pod.Name)
graphViz.AddNode(subgraph, podLabel, map[string]string{
"fontname": "Helvetica",
"shape": "box",
Expand Down
10 changes: 10 additions & 0 deletions examples/demo-cluster/terraform/secrets.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
resource "kubernetes_secret" "creds" {
metadata {
name = "kafka-proxy-aws"
}
data = {
# Note: These are fictional keys
aws_access_key_id = "AKIAZ3MSJV4WWNKWW5FG",
aws_secret_key = "HP8lBRs8X50F/0nCAXqEPQ95+jlG/0pLdlNui2XF"
}
}
Binary file modified examples/irsa.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 030c2b4

Please sign in to comment.