Kubernetes Security for ML Workloads
Uitgebreide analyse van Kubernetes-aanvalsoppervlakken die specifiek zijn voor machine-learning-workloads, waaronder exploitatie van de GPU operator, namespace-aanvallen op model serving en privilege-escalatie op clusterniveau via ML-componenten.
Machine-learning-workloads op Kubernetes introduceren een eigen verzameling beveiligingsuitdagingen die verder gaan dan de standaardrisico's van containerorkestratie. De combinatie van GPU-scheduling-vereisten, gespecialiseerde operators voor training en serving, gedeelde opslag voor modelartefacten, en de bevoorrechte toegangspatronen die CUDA-runtimes vereisen, creëert een aanvalsoppervlak dat noch traditionele Kubernetes-beveiliging noch ML-beveiliging op zichzelf volledig aanpakt.
Device plugins zijn het fundamentele mechanisme waarmee Kubernetes GPU-resources blootstelt aan ML-workloads. De NVIDIA GPU Operator, de AMD ROCm device plugin en de Intel GPU-plugins werken allemaal met verhoogde privileges die, wanneer ze verkeerd geconfigureerd zijn, doelen van hoge waarde worden voor laterale beweging.
ML-specifieke Kubernetes-architectuur
Een productie-ML-platform op Kubernetes omvat doorgaans verschillende aanvullende lagen bovenop standaarddeployments:
┌─────────────────────────────────────────────────────┐
│ Kubernetes Cluster │
│ │
│ ┌──────────────┐ ┌──────────────┐ ┌────────────┐ │
│ │ KubeFlow / │ │ Seldon / │ │ Training │ │
│ │ ML Platform │ │ KServe │ │ Operator │ │
│ └──────┬───────┘ └──────┬───────┘ └──────┬─────┘ │
│ │ │ │ │
│ ┌──────┴──────────────────┴──────────────────┴─────┐│
│ │ GPU Operator / Device Plugin ││
│ └──────────────────────┬───────────────────────────┘│
│ │ │
│ ┌──────────────────────┴───────────────────────────┐│
│ │ Node (GPU-enabled) ││
│ │ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ ││
│ │ │ CUDA │ │ Model │ │ Shared Storage │ ││
│ │ │ Runtime │ │ Weights │ │ (PVCs / NFS) │ ││
│ │ └──────────┘ └──────────┘ └──────────────────┘ ││
│ └───────────────────────────────────────────────────┘│
└─────────────────────────────────────────────────────┘
Elk component introduceert specifieke aanvalsvectoren die afwezig zijn in standaard Kubernetes-deployments.
Exploitatie van de GPU operator en device plugins
Aanvalsoppervlak van de NVIDIA GPU Operator
De NVIDIA GPU Operator draait als een bevoorrechte DaemonSet op elke GPU-node en beheert driver-installatie, configuratie van de container runtime en de levenscyclus van de device plugin:
# Enumerate GPU operator components in a cluster
import subprocess
import json
def enumerate_gpu_operator(namespace="gpu-operator"):
"""Identify GPU operator attack surface in a Kubernetes cluster."""
components = {}
# Vind GPU-operator-pods en hun privilegeniveaus
pods = json.loads(subprocess.check_output([
"kubectl", "get", "pods", "-n", namespace,
"-o", "json"
]))
for pod in pods["items"]:
pod_name = pod["metadata"]["name"]
containers = pod["spec"].get("containers", [])
for container in containers:
security_context = container.get("securityContext", {})
pod_security = pod["spec"].get("securityContext", {})
components[pod_name] = {
"privileged": security_context.get("privileged", False),
"host_pid": pod["spec"].get("hostPID", False),
"host_network": pod["spec"].get("hostNetwork", False),
"volume_mounts": [
vm["mountPath"] for vm in container.get("volumeMounts", [])
],
"capabilities": security_context.get("capabilities", {}),
}
return componentsExploitatie van de device-plugin-socket
GPU device plugins communiceren met de kubelet via Unix-sockets. Als een aanvaller toegang krijgt tot het node-bestandssysteem, kunnen deze sockets worden gemanipuleerd:
# Default device plugin socket locations
# /var/lib/kubelet/device-plugins/nvidia.sock
# /var/lib/kubelet/device-plugins/kubelet.sock
# An attacker with node access can:
# 1. Register a malicious device plugin that intercepts GPU allocation
# 2. Monitor device plugin traffic to observe which pods request GPUs
# 3. Manipulate device allocation to redirect GPU access| Aanvalsvector | Vereiste | Impact | Moeilijkheid |
|---|---|---|---|
| Kaping van device-plugin-socket | Toegang tot node-bestandssysteem | Manipulatie van GPU-allocatie | Hoog |
| Compromittering van GPU-operator-pod | Namespace-toegang tot gpu-operator | Bevoorrechte code-uitvoering op alle GPU-nodes | Gemiddeld |
| Manipulatie van CUDA-runtime | Container escape of host-toegang | Willekeurige code-uitvoering in GPU-context | Hoog |
| Manipulatie van MIG-partitie | GPU-operator-toegang | Cross-tenant GPU-geheugentoegang | Gemiddeld |
| Downgrade van driverversie | Toegang tot GPU-operator-config | Introductie van bekende kwetsbaarheden | Laag |
KubeFlow-aanvalsoppervlak
KubeFlow is een veelvuldig ingezet ML-platform op Kubernetes dat meerdere aanvalsoppervlakken van hoge waarde introduceert:
Exploitatie van notebookservers
KubeFlow-notebooks draaien als Kubernetes-pods met directe clustertoegang. Ze worden vaak voorzien van te ruim bevoorrechte serviceaccounts:
# Probe KubeFlow notebook server for Kubernetes access
import requests
import os
def assess_notebook_k8s_access():
"""Assess Kubernetes access from a KubeFlow notebook pod."""
findings = []
# Controleer op een serviceaccount-token
token_path = "/var/run/secrets/kubernetes.io/serviceaccount/token"
if os.path.exists(token_path):
with open(token_path) as f:
token = f.read()
findings.append({
"finding": "Service account token accessible",
"token_preview": token[:50] + "...",
})
# Probeer de pods in de namespace op te sommen
namespace_path = "/var/run/secrets/kubernetes.io/serviceaccount/namespace"
namespace = open(namespace_path).read() if os.path.exists(namespace_path) else "default"
k8s_host = os.environ.get("KUBERNETES_SERVICE_HOST", "kubernetes.default.svc")
k8s_port = os.environ.get("KUBERNETES_SERVICE_PORT", "443")
try:
resp = requests.get(
f"https://{k8s_host}:{k8s_port}/api/v1/namespaces/{namespace}/pods",
headers={"Authorization": f"Bearer {token}"},
verify="/var/run/secrets/kubernetes.io/serviceaccount/ca.crt",
timeout=5,
)
if resp.status_code == 200:
pod_names = [p["metadata"]["name"] for p in resp.json()["items"]]
findings.append({
"finding": "Can list pods in namespace",
"severity": "HIGH",
"pods": pod_names,
})
except Exception as e:
findings.append({"finding": "API access failed", "error": str(e)})
# Controleer op GPU-toegang vanuit de notebook
try:
import torch
if torch.cuda.is_available():
findings.append({
"finding": "GPU access from notebook",
"gpu_count": torch.cuda.device_count(),
"gpu_name": torch.cuda.get_device_name(0),
})
except ImportError:
pass
return findingsPipeline-injectie-aanvallen
KubeFlow Pipelines voeren door de gebruiker gedefinieerde DAG's uit als Kubernetes-pods. Een gecompromitteerde pijplijnstap kan de serviceaccount van de pijplijn benutten om privileges te escaleren:
# Malicious pipeline component that exploits Kubernetes access
# This demonstrates the attack pattern - not for use in unauthorized testing
apiVersion: argoproj.io/v1alpha1
kind: Workflow
spec:
templates:
- name: malicious-step
container:
image: python:3.11
command: ["python", "-c"]
args:
- |
# Pipeline pods often have broad namespace access
# for reading artifacts, secrets, and config maps
import subprocess
# Enumerate accessible secrets
result = subprocess.run(
["kubectl", "get", "secrets", "-A", "-o", "name"],
capture_output=True, text=True
)
print(result.stdout)Namespace-aanvallen op model serving
Beveiligingsmodel van KServe en Seldon
Model-serving-platforms zoals KServe en Seldon Core zetten inferentieservices in als Kubernetes-resources met voorspelbare naamgevingsconventies en netwerkpatronen:
# Enumerate model serving endpoints across namespaces
def enumerate_inference_services():
"""Find all inference services in a Kubernetes cluster."""
import subprocess
import json
services = {}
# KServe InferenceService-resources
try:
kserve = json.loads(subprocess.check_output([
"kubectl", "get", "inferenceservices", "--all-namespaces", "-o", "json"
]))
for item in kserve["items"]:
name = item["metadata"]["name"]
ns = item["metadata"]["namespace"]
url = item.get("status", {}).get("url", "unknown")
services[f"{ns}/{name}"] = {
"type": "kserve",
"url": url,
"ready": item.get("status", {}).get("conditions", []),
}
except subprocess.CalledProcessError:
pass
# Seldon-deployments
try:
seldon = json.loads(subprocess.check_output([
"kubectl", "get", "seldondeployments", "--all-namespaces", "-o", "json"
]))
for item in seldon["items"]:
name = item["metadata"]["name"]
ns = item["metadata"]["namespace"]
services[f"{ns}/{name}"] = {
"type": "seldon",
"replicas": item["spec"].get("replicas", 1),
"predictors": [
p["name"] for p in item["spec"].get("predictors", [])
],
}
except subprocess.CalledProcessError:
pass
return servicesCross-namespace-modeltoegang
In multi-tenant-ML-platforms zetten teams modellen doorgaans in naar afzonderlijke namespaces. Verschillende veelvoorkomende misconfiguraties maken echter cross-namespace-toegang mogelijk:
| Misconfiguratie | Beschrijving | Exploitatie |
|---|---|---|
| Ontbrekende NetworkPolicy | Geen netwerkisolatie tussen ML-namespaces | Directe HTTP-toegang tot de inferentie-endpoints van andere teams |
| Gedeelde PVC voor modelopslag | Meerdere namespaces mounten dezelfde PV | Lees of overschrijf de modelgewichten van andere teams |
| Te toegeeflijke Istio/Envoy-regels | Service mesh staat cross-namespace-verkeer toe | Onderschep of herleid inferentieverzoeken |
| Globale toegang tot model registry | Alle namespaces kunnen vanuit hetzelfde register pullen | Vergiftig modellen die door andere teams worden gebruikt |
| Gedeelde secrets voor cloudopslag | S3/GCS-credentials gedeeld over namespaces | Toegang tot trainingsdata en modelartefacten |
Beveiliging van trainingsjobs
Aanvalsoppervlak van gedistribueerde training
Gedistribueerde training met frameworks zoals Horovod, PyTorch Distributed of DeepSpeed creëert communicatiekanalen tussen pods die het aanvalsoppervlak vergroten:
# Assess distributed training network exposure
def assess_distributed_training_security(namespace="training"):
"""Check for insecure distributed training configurations."""
import subprocess
import json
findings = []
# Vind trainingspods met open communicatiepoorten
pods = json.loads(subprocess.check_output([
"kubectl", "get", "pods", "-n", namespace,
"-l", "training-job",
"-o", "json"
]))
for pod in pods["items"]:
containers = pod["spec"].get("containers", [])
for container in containers:
ports = container.get("ports", [])
env_vars = {
e["name"]: e.get("value", "")
for e in container.get("env", [])
}
# Controleer op NCCL- en Gloo-communicatiepoorten
nccl_port = env_vars.get("NCCL_SOCKET_IFNAME")
master_addr = env_vars.get("MASTER_ADDR")
master_port = env_vars.get("MASTER_PORT")
if master_addr and master_port:
findings.append({
"pod": pod["metadata"]["name"],
"master_addr": master_addr,
"master_port": master_port,
"severity": "MEDIUM",
"note": "Distributed training master endpoint exposed",
})
# Controleer op shared-memory-mounts (vereist voor NCCL)
volumes = pod["spec"].get("volumes", [])
for vol in volumes:
if vol.get("emptyDir", {}).get("medium") == "Memory":
findings.append({
"pod": pod["metadata"]["name"],
"finding": "Shared memory (dshm) mount detected",
"note": "Required for NCCL but may allow cross-container data access",
})
return findingsExploitatie van de training operator
Kubernetes training operators (PyTorchJob, TFJob, MPIJob) beheren de levenscyclus van trainingsjobs. Het compromitteren van de operator verleent controle over alle trainingsworkloads:
| Operator | CRD | Aanvalsoppervlak |
|---|---|---|
| PyTorch Operator | PyTorchJob | Aanmaken van master-/worker-pods, GPU-allocatie |
| TensorFlow Operator | TFJob | PS-/worker-topologie, checkpointpaden |
| MPI Operator | MPIJob | Distributie van SSH-sleutels, launcher-toegang |
| Volcano Scheduler | Queue, PodGroup | Prioriteitsmanipulatie, resource-uithongering |
RBAC-misconfiguraties in ML-platforms
ML-platforms vereisen vaak brede RBAC-permissies die de least-privilege-principes schenden:
# Common overly permissive RBAC for ML platform service accounts
# This pattern appears frequently in KubeFlow and similar platforms
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: ml-platform-admin
rules:
# Broad pod management for training jobs
- apiGroups: [""]
resources: ["pods", "pods/exec", "pods/log"]
verbs: ["*"]
# Secret access for model registry credentials
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "watch"]
# PVC management for datasets and models
- apiGroups: [""]
resources: ["persistentvolumeclaims"]
verbs: ["*"]
# CRD access for ML operators
- apiGroups: ["kubeflow.org"]
resources: ["*"]
verbs: ["*"]Checklist voor RBAC-beoordeling
def audit_ml_rbac(namespace="kubeflow"):
"""Audit RBAC permissions for ML platform service accounts."""
import subprocess
import json
dangerous_permissions = []
# Haal alle serviceaccounts in de ML-namespace op
sa_list = json.loads(subprocess.check_output([
"kubectl", "get", "serviceaccounts", "-n", namespace, "-o", "json"
]))
for sa in sa_list["items"]:
sa_name = sa["metadata"]["name"]
# Controleer wat deze SA kan doen met auth can-i
for resource in ["secrets", "pods/exec", "configmaps", "nodes"]:
for verb in ["get", "list", "create", "delete"]:
result = subprocess.run(
["kubectl", "auth", "can-i", verb, resource,
"--as", f"system:serviceaccount:{namespace}:{sa_name}",
"-n", namespace],
capture_output=True, text=True
)
if "yes" in result.stdout:
dangerous_permissions.append({
"service_account": f"{namespace}:{sa_name}",
"resource": resource,
"verb": verb,
})
return dangerous_permissionsAanvallen op gedeelde opslag
ML-workloads zijn sterk afhankelijk van gedeelde opslag voor datasets, modelgewichten, checkpoints en artefacten. Dit creëert aanvalsmogelijkheden over pods en namespaces heen:
Misconfiguraties van PersistentVolume Claims
# Commonly misconfigured shared storage for ML workloads
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: model-storage
spec:
accessModes:
- ReadWriteMany # Multiple pods can write simultaneously
resources:
requests:
storage: 500Gi
storageClassName: nfs-client # NFS often lacks access controls| Opslag-aanval | Vector | Impact |
|---|---|---|
| Vervanging van modelgewichten | Schrijftoegang tot gedeelde PVC | Een backdoored model serveren |
| Vergiftiging van trainingsdata | Schrijftoegang tot dataset-PVC | Trainingsruns corrumperen |
| Manipulatie van checkpoints | Schrijftoegang tot checkpointdirectory | Training kapen vanaf een specifiek punt |
| Exfiltratie van logs | Leestoegang tot experimentlogs | Hyperparameters, metrieken, datasamples onttrekken |
| Verzamelen van credentials | Leestoegang tot config-mounts | Cloudopslagsleutels, API-tokens bemachtigen |
Methodologie voor red-team-beoordeling
Volg bij het beoordelen van Kubernetes ML-infrastructuur deze systematische aanpak:
Fase 1: Reconnaissance
- Enumereer ML-specifieke CRD's (InferenceService, PyTorchJob, Notebook, Experiment)
- Identificeer GPU-nodes en hun operatorconfiguraties
- Breng de namespace-topologie en het netwerkbeleid in kaart
- Identificeer gedeelde opslagvolumes en hun access modes
Fase 2: Beoordeling van toegang
- Test serviceaccount-permissies vanuit ML-pods
- Probeer cross-namespace-netwerktoegang tot inferentie-endpoints
- Test de management-interfaces van de GPU operator
- Controleer op ongeauthenticeerde toegang tot het KubeFlow-dashboard
Fase 3: Exploitatie
- Probeer pijplijninjectie via KubeFlow Pipelines
- Test uitbraak uit de notebookserver via Kubernetes-API-toegang
- Test gedeelde opslag op schrijftoegang tot modelgewichten
- Beoordeel de communicatie tussen pods bij gedistribueerde training
Fase 4: Demonstratie van impact
- Modelvervanging via schrijftoegang tot gedeelde PVC
- Extractie van credentials uit ML-platform-secrets
- Cross-tenant-inferentietoegang door ontbrekend netwerkbeleid
- Uithongering van GPU-resources via prioriteitsmanipulatie
Gerelateerde onderwerpen
- Attacking AI Deployments -- fundamentele concepten van deployment-beveiliging
- Cloud AI Security -- cloud-specifieke risico's van ML-infrastructuur
- Infrastructure Exploitation -- geavanceerde technieken voor infrastructuuraanvallen
- GPU Cluster Attacks -- gerichte exploitatie van GPU-compute
- ML Pipeline CI/CD Attacks -- aanvallen op de automatisering van ML-pijplijnen
References
- "Kubernetes Security and Observability" - Brendan Creane & Amit Gupta (O'Reilly, 2021) - Foundation for Kubernetes security assessment including RBAC, network policy, and runtime security
- "Hacking Kubernetes" - Andrew Martin & Michael Hausenblas (O'Reilly, 2022) - Practical Kubernetes attack techniques applicable to ML workloads
- NVIDIA GPU Operator Documentation (2025) - Official documentation covering GPU operator deployment, security considerations, and MIG configurations
- KubeFlow Security Documentation (2025) - KubeFlow multi-tenancy and security hardening guidance
- MITRE ATLAS - ML-specific threat framework including infrastructure-layer attacks on ML systems
Wat maakt KubeFlow-notebookservers een bijzonder gevaarlijke aanvalsvector in Kubernetes ML-infrastructuur?