You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eks-post-exploitation/README.md
+2-3Lines changed: 2 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -78,7 +78,7 @@ users:
78
78
79
79
### From AWS to Kubernetes
80
80
81
-
The **creator** of the **EKS cluster** is **ALWAYS** going to be able to get into the kubernetes cluster part of the group **`system:masters`** (k8s admin). At the time of this writing there is **no direct way** to find **who created** the cluster (you can check CloudTrail). And the is **no way** to **remove** that **privilege**.
81
+
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`.
AWS implementes 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 rol.
96
+
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.
97
97
98
98
First, **create an access entry for your user or role**:
99
99
@@ -182,4 +182,3 @@ So, if an **attacker compromises a cluster using fargate** and **removes all the
Copy file name to clipboardExpand all lines: src/pentesting-cloud/gcp-security/gcp-services/gcp-containers-gke-and-composer-enum.md
+17-3Lines changed: 17 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -88,10 +88,26 @@ kubectl get serviceaccounts -A -o yaml | grep -n 'iam.gke.io' -B 5 -A 8
88
88
kubectl get pods -A -o custom-columns='NS:.metadata.namespace,NAME:.metadata.name,SA:.spec.serviceAccountName,NODE:.spec.nodeName'
89
89
```
90
90
91
-
If a service account has the annotation `iam.gke.io/gcp-service-account`, review the IAM service account policy for `roles/iam.workloadIdentityUser` grants to Kubernetes service account principals. Also check IAM allow policies for direct workload identity principals or broad principal sets.
91
+
If a service account has the annotation `iam.gke.io/gcp-service-account`, review the IAM service account policy for `roles/iam.workloadIdentityUser` grants to Kubernetes service account principals. Also check IAM allow policies for direct workload identity principals or broad `principalSet://` grants, such as namespace-wide or cluster-wide workload access. The annotation `iam.gke.io/credential-quota-project` only moves IAM Service Account Credentials API quota to another project; the workload principal still needs `serviceusage.services.use` on that quota project and separate IAM access to the target resource.
92
92
93
93
Metadata access depends on cluster mode, node pool configuration, and workload settings. Do not assume every pod can steal the node service account. In Workload Identity-enabled environments, ordinary pods should use the GKE metadata server to obtain the workload identity intended for their Kubernetes service account. Node compromise, `hostNetwork` pods in some Standard configurations, and legacy node metadata exposure can still change the blast radius, so verify the actual node pool metadata mode, node service account, OAuth scopes, and pod placement.
94
94
95
+
If a Workload Identity-enabled pod cannot get a token, also check NetworkPolicy egress before assuming the IAM binding is wrong. GKE Standard clusters using NetworkPolicy must allow the metadata-server path required by the cluster version and dataplane, and Dataplane V2 uses the `169.254.169.254` path for metadata-server access.
96
+
97
+
### Autopilot privileged workload allowlists
98
+
99
+
GKE Autopilot blocks most privileged workloads by default, but approved exceptions can exist. Review privileged admission settings, `AllowlistSynchronizer` objects, and installed `WorkloadAllowlist` objects before assuming a privileged pod is impossible:
kubectl get allowlistsynchronizers.auto.gke.io -A -o yaml
106
+
kubectl get workloadallowlists.auto.gke.io -A -o yaml
107
+
```
108
+
109
+
Allowlist paths can be GKE-owned (`gke://...`) or customer-owned Cloud Storage paths (`gs://...`). Wildcards and broad bucket paths increase the blast radius because future allowlist files under that path might become valid for the cluster. When a `WorkloadAllowlist` is installed, compare its exemptions and matching criteria to the pod spec, especially image digests, host namespaces, writable hostPath mounts, host ports, Linux capabilities, and whether `autopilot.gke.io/no-connect` prevents `exec` access to the privileged workload.
110
+
95
111
### TLS Boostrap Privilege Escalation
96
112
97
113
Initially this privilege escalation technique allowed to **privesc inside the GKE cluster** effectively allowing an attacker to **fully compromise it**.
Even if the API **doesn't allow to modify resources**, it could be possible to find **sensitive information** in the response. The endpoint /pods was found using [**Kiterunner**](https://github.com/assetnote/kiterunner).
After node access, also review how the node pulls private images. Useful evidence includes runtime image metadata (`crictl images`), Pod or ServiceAccount `imagePullSecrets`, containerd registry configuration such as `/etc/containerd/config.toml` and `/etc/containerd/certs.d`, and kubelet image credential provider flags such as `--image-credential-provider-config` and `--image-credential-provider-bin-dir`.
191
+
192
+
Do not assume that a cached private image means you have reusable registry credentials. It might only prove that the image exists on this node. However, static runtime registry credentials, Docker config JSON pull secrets, or a credential provider that can mint short-lived pull credentials can expose private registry access. Recent Kubernetes versions also support service-account-token based kubelet credential providers for image pulls, so check whether the provider is using Pod-bound service account tokens and which audience it requests before reporting the impact.
193
+
188
194
### Find node kubeconfig
189
195
190
196
If you cannot find the kubeconfig file in one of the previously commented paths, **check the argument `--kubeconfig` of the kubelet process**:
- NodePorts are normally exposed on node addresses, but kube-proxy can restrict the address ranges with `--nodeport-addresses` or `nodePortAddresses` in its configuration. Check the active kube-proxy or CNI service-proxy replacement configuration before assuming the NodePort is reachable on every node IP.
105
106
- `externalTrafficPolicy: Local` preserves the original client source IP for NodePort/LoadBalancer traffic and avoids forwarding to endpoints on other nodes. A node without a local ready endpoint may drop the traffic even if the Service has endpoints elsewhere.
106
107
- `externalTrafficPolicy: Cluster` is the default and can forward through any node, but backend logs may see node IPs instead of the real external client IP.
107
108
- `internalTrafficPolicy: Local` limits in-cluster Service traffic to endpoints local to the source node. This is locality routing, not an authorization boundary.
@@ -169,6 +170,8 @@ spec:
169
170
170
171
When looking up the host `my-service.prod.svc.cluster.local`, the cluster DNS Service returns a `CNAME` record with the value `my.database.example.com`. Accessing `my-service` works in the same way as other Services but with the crucial difference that **redirection happens at the DNS level** rather than via proxying or forwarding.
171
172
173
+
Security review note: if an Ingress controller, Gateway implementation, service mesh, or application accepts an ExternalName Service as a backend, the controller may resolve and reach the external name from its own network position. That can expose internal-only services through public routing infrastructure when users can create both the route object and the ExternalName Service. Review the specific controller implementation and version, ExternalName support flags or allowlists, route status, and the exact target domain before treating this as safe. For example, Skipper patched a Kubernetes ExternalName SSRF issue in v0.24.0 by disabling ExternalName backends by default and documenting an allowlist option.
174
+
172
175
List all ExternalNames:
173
176
174
177
```bash
@@ -256,21 +259,30 @@ List Gateway API exposure objects:
256
259
kubectl get gatewayclasses
257
260
kubectl get gateways --all-namespaces
258
261
kubectl get httproutes --all-namespaces
262
+
kubectl get grpcroutes,tlsroutes,tcproutes,udproutes --all-namespaces
263
+
kubectl get referencegrants --all-namespaces
264
+
kubectl get backendtlspolicies --all-namespaces
259
265
kubectl get gateway -n <namespace> <gateway-name> -o yaml
260
266
kubectl get httproute -n <namespace> <route-name> -o yaml
261
267
```
262
268
263
-
Check Gateway listeners, allowed route namespaces, Route `parentRefs`, hostnames, filters, backend references, and status conditions such as whether the route was accepted. A Route that is accepted by a shared Gateway can expose a backend even when no legacy Ingress object exists.
269
+
Check Gateway listeners, allowed route namespaces, Route `parentRefs`, hostnames or SNI matches, filters, backend references, and status conditions such as `Accepted`, `ResolvedRefs`, and `Programmed`. A Route that is accepted by a shared Gateway can expose a backend even when no legacy Ingress object exists.
270
+
271
+
Do not check only HTTPRoute. GRPCRoute, TLSRoute, TCPRoute, and UDPRoute can expose non-HTTP services such as admin ports, brokers, databases, service-mesh gateways, or pass-through TLS backends. Also review `ReferenceGrant` objects for cross-namespace backend or certificate references and `BackendTLSPolicy` for the TLS identity the Gateway uses when connecting to backend Services. Backend TLS policy is not proof of public reachability by itself, but it is useful evidence when a programmed Gateway route reaches a ready Service with weak, shared, or wrong backend identity validation.
Copy file name to clipboardExpand all lines: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration.md
+30Lines changed: 30 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -209,6 +209,36 @@ kubectl get pods -A -o custom-columns='NS:.metadata.namespace,NAME:.metadata.nam
209
209
-`metadata.finalizers` and `metadata.deletionTimestamp` explain resources stuck in deletion and can reveal cleanup controllers or persistence/disruption tricks.
210
210
-`status`, Events, and conditions can reveal node placement, pod IPs, image IDs, failure messages, scheduling issues, admission denials, and controller progress. They are useful clues, but audit logs are still required to prove who performed an action.
211
211
212
+
### Dynamic Resource Allocation and device evidence
213
+
214
+
If the cluster uses GPUs, NICs, FPGAs, or other specialized hardware, check whether Kubernetes Dynamic Resource Allocation (DRA) is present. DRA uses `resource.k8s.io` objects such as `DeviceClass`, `ResourceSlice`, `ResourceClaim`, and `ResourceClaimTemplate` to describe available devices and claim them for Pods. These objects can reveal which nodes can access valuable hardware, which driver manages it, and which workload has an allocation.
215
+
216
+
```bash
217
+
kubectl api-resources --api-group=resource.k8s.io
218
+
kubectl get deviceclasses.resource.k8s.io 2>/dev/null
219
+
kubectl get resourceslices.resource.k8s.io 2>/dev/null
220
+
kubectl get resourceclaims.resource.k8s.io -A 2>/dev/null
221
+
kubectl get resourceclaimtemplates.resource.k8s.io -A 2>/dev/null
222
+
kubectl get pods -A -o jsonpath='{range .items[*]}{.metadata.namespace}{"/"}{.metadata.name}{" claims="}{.spec.resourceClaims}{" node="}{.spec.nodeName}{"\n"}{end}'
223
+
kubectl get daemonsets,pods -A -o wide | grep -Ei 'dra|device|gpu|nvidia|amd|intel|sriov|fpga'
224
+
```
225
+
226
+
During review, restrict writes to cluster-scoped `DeviceClass` and `ResourceSlice` objects to admins and DRA drivers, and keep `ResourceClaim` / `ResourceClaimTemplate` rights scoped to the namespaces that need them. Driver permissions to update `ResourceClaim` status should be explicit and narrow. On nodes, the kubelet PodResources API is commonly exposed through `/var/lib/kubelet/pod-resources/kubelet.sock`; monitoring DaemonSets may mount that directory to inspect assigned devices, so review those Pods like other privileged node agents.
227
+
228
+
### ClusterTrustBundle and add-on certificate trust
229
+
230
+
Recent clusters may expose `ClusterTrustBundle` objects in the `certificates.k8s.io` API group. They are cluster-scoped X.509 trust anchor bundles that Pods can mount through projected volumes. Broad read access is expected, but write access is sensitive because changing trusted roots can affect webhooks, aggregated APIs, service meshes, and applications that consume cluster-distributed CA material.
kubectl get clustertrustbundles.certificates.k8s.io 2>/dev/null
235
+
kubectl get clustertrustbundle <name> -o yaml 2>/dev/null
236
+
kubectl get pods -A -o yaml | grep -n -E 'clusterTrustBundle|trustBundle|caBundle'
237
+
kubectl get apiservices -o jsonpath='{range .items[*]}{.metadata.name}{" insecure="}{.spec.insecureSkipTLSVerify}{" service="}{.spec.service.namespace}{"/"}{.spec.service.name}{"\n"}{end}'
238
+
```
239
+
240
+
During review, record `signerName`, bundle fingerprints, writer identities, projected-volume consumers, and any trust-distribution controller such as cert-manager trust-manager. Treat `APIService` objects with `insecureSkipTLSVerify: true`, stale `caBundle` values, or broad permissions to patch APIService/webhook trust fields as certificate-trust findings rather than ordinary object inventory.
Copy file name to clipboardExpand all lines: src/pentesting-cloud/kubernetes-security/kubernetes-network-attacks.md
+18-1Lines changed: 18 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -111,6 +111,24 @@ This fact implies that, by default, **every pod running in the same node** is go
111
111
> [!WARNING]
112
112
> Therefore, it's possible to perform A**RP Spoofing attacks between pods in the same node.**
113
113
114
+
### NetworkPolicy and admin policy layers
115
+
116
+
Kubernetes `NetworkPolicy` is a pod traffic control at L3/L4, but it is enforced by the CNI plugin and not by the API server itself. A cluster can store NetworkPolicy objects while still allowing traffic if the active CNI does not implement them, so always validate with a controlled allowed source and a blocked negative-control source.
117
+
118
+
Do not stop at `kubectl get networkpolicy -A`. Clusters using Cilium, Calico, OVN-Kubernetes, Antrea, or managed-provider dataplanes may also have policy APIs such as `CiliumNetworkPolicy`, `CiliumClusterwideNetworkPolicy`, Calico `GlobalNetworkPolicy`, `AdminNetworkPolicy`, or `BaselineAdminNetworkPolicy`. These can add explicit deny, tier/order, cluster scope, L7/DNS rules, or admin guardrails that ordinary additive Kubernetes NetworkPolicy semantics do not explain.
kubectl get adminnetworkpolicy,baselineadminnetworkpolicy -A 2>/dev/null
128
+
```
129
+
130
+
For bypass analysis, check whether the intended block is avoided through an allowed proxy, DNS or egress gateway, `hostNetwork` pod, node-local path, broad namespace or pod label selector, or a higher-precedence admin/global policy. Report the source pod labels, namespace labels, destination Service or EndpointSlice, CNI/policy implementation, deciding policy rule, and traffic proof.
131
+
114
132
### DNS
115
133
116
134
In kubernetes environments you will usually find 1 (or more) **DNS services running** usually in the kube-system namespace:
@@ -334,4 +352,3 @@ It will install agents in the selected pods and gather their traffic information
0 commit comments