# DRILL — L'OMBRE DU WAF
## Rapport Mitnick — Analyse offensive complète
---
## VECTEUR D'ENTRÉE (Pré-requis scénario)
**Credentials GitLab CI/CD leakés → compte développeur compromis.**
C'est le point d'ancrage. Tout ce qui suit en découle. Ce vecteur lui-même mérite un P0 indépendant du reste.
> **Question immédiate :** Le compte développeur a-t-il accès au kubeconfig ? Au namespace prod ? Aux Kubernetes Secrets ? Si oui, le reste du scénario est déjà résolu en 2 minutes, pas 10.
---
## CLASSIFICATION PAR SÉVÉRITÉ
### P0 — CRITIQUES (exploitation immédiate, impact maximal)
---
**P0-1 — Redis session poisoning via wildcard client name**
- **Faille :** Clé `ac_custom_auth:{client_name}_session`. Un client nommé `*` ou `*X` matche tous les patterns Redis `KEYS ac_custom_auth:*`.
- **Exploitation :** Via `KEYS *` + injection de session forgée → élévation admin cross-tenant en une commande.
- **Pourquoi P0 :** Zero prerequisite côté crypto. Redis KEYS + SET suffisent. Impact = toutes les sessions de tous les clients.
- **Mitigation :** Préfixe UUID non devinable par client, interdire `KEYS` en prod (utiliser `SCAN`), namespace Redis isolé par tenant.
---
**P0-2 — Lua null byte bypass + accès backends internes**
- **Faille :** `ngx.var.http_host` sans sanitization. `Host: legit.example.com\0.evil.com` → le Lua route vers un backend selon la partie avant le null byte, mais le WAF (basé sur regex) lit la string C-terminée → voit `legit.example.com` uniquement.
- **Exploitation :** Accéder à `/api/v1/internal/` depuis l'extérieur en bypassant le WAF et le routing multi-tenant.
- **Pourquoi P0 :** Combine deux failles (Lua + WAF) pour un accès direct aux endpoints "protégés". Avec credentials CI/CD = accès direct.
- **Mitigation :** Sanitizer le Host header en Lua avant tout traitement (`ngx.re.gsub`), valider via allowlist de domaines connus, PAS de regex sur header raw.
---
**P0-3 — Token Prometheus md5(time() + secret) en clair dans les logs**
- **Faille :** `md5(time() + secret)` — window de bruteforce de ~±30 secondes autour du timestamp de génération. Si les logs sont dans Elasticsearch (accessible via le compte CI/CD leaké), le token est directement lisible.
- **Exploitation :**
1. Accès Elasticsearch via credentials CI/CD.
2. Lire les logs, extraire le token.
3. Appeler `/api/v1/internal/metrics` → toutes les métriques internes exposées (noms de pods, variables d'env, secrets potentiellement leakés dans les labels Prometheus).
- **Pourquoi P0 :** Double faille — algo faible + secret en clair. Les métriques Prometheus exposent souvent des infos structurelles critiques utilisables pour l'étape suivante (pivot).
- **Mitigation :** `secrets.token_hex(32)`, rotation automatique, **ne jamais logger un token en clair**.
---
**P0-4 — WAF désactivé en staging, promotion prod non vérifiée**
- **Faille :** Le WAF s'active via un label Kubernetes namespace. Si le pipeline CI/CD (compromis) peut modifier les labels, ou si staging est accessible publiquement, l'attaquant a un environnement WAF-free pour tester ses payloads avant de les affiner pour prod.
- **Exploitation :** Staging = laboratoire d'exploitation gratuit. Tester request smuggling, null bytes, injections sans déclencher d'alerte.
- **Pourquoi P0 :** Amplifie tous les autres vecteurs. Un attaquant qui a 10 minutes commence par staging.
- **Mitigation :** WAF actif par défaut sur TOUS les namespaces, opt-out explicite avec audit trail, pas opt-in.
---
**P0-5 — PrestaShop class override via upload dans `/modules/ac_custom_auth/classes/`**
- **Faille :** `spl_autoload_register()` sans vérification d'origine. Upload d'un fichier `Cart.php` ou `Employee.php` dans le dossier du module → override de la classe PS core.
- **Exploitation :** RCE ou élévation admin via override de `Employee::checkPassword()` ou hook `actionAuthentication`.
- **Pourquoi P0 :** RCE côté serveur. Si l'attaquant a accès au filesystem via les credentials CI/CD (volume mount, `kubectl cp`), c'est terminé.
- **Mitigation :** Vérification d'intégrité des classes (checksum), namespace des classes du module, désactiver l'autoloading global dans les modules customs.
---
### P1 — HAUTS (exploitation probable, conditions requises)
---
**P1-1 — HTTP Request Smuggling (CL.TE / TE.CL)**
- **Faille :** NGINX Ingress + backend hétérogène = désaccord sur la fin du body. `Content-Length: 5\r\nTransfer-Encoding: chunked` → smuggling.
- **Exploitation :** Injecter une requête "cachée" qui sera interprétée par le backend interne comme une nouvelle requête (ex: accès `/api/v1/internal/` via la "queue" d'une requête légitime).
- **Condition :** Backend doit interpréter différemment de NGINX. En K8s avec des services hétérogènes (Node, Python, Go) → probable.
- **Mitigation :** `proxy_http_version 1.1` + rejeter les requêtes ambiguës CL+TE simultanés, normaliser en NGINX avant le backend.
---
**P1-2 — NGINX mergeable config TOCTOU (race condition)**
- **Faille :** Entre `SIGHUP` et l'application effective de la config, une fenêtre où l'ancienne et la nouvelle config coexistent. Fichiers temporaires dans `/tmp/nginx-ingress-XXXXXX` potentiellement lisibles.
- **Exploitation :** Timer une requête pendant un rechargement config (déclenché par le compte CI/CD via `kubectl annotate`). Leak de la config intermédiaire.
- **Condition :** Nécessite de déclencher le reload et de timer précisément → faisable avec accès CI/CD.
- **Mitigation :** `/tmp` non lisible par l'utilisateur nginx, atomicité des config via `nginx -t` + swap atomique.
---
**P1-3 — Kubernetes Secrets accessibles via compte développeur**
- **Non mentionné dans le scénario — mais critique.**
- **Faille :** Le compte développeur (credentials CI/CD) a probablement un `ClusterRole` ou `Role` qui inclut `get/list secrets`. Le token admin est "stocké dans un pod" → il vit dans un Secret Kubernetes ou une variable d'environnement.
- **Exploitation :** `kubectl get secret -n prod -o yaml` → base64 decode → token admin. **10 minutes c'est déjà trop long pour ça.**
- **Mitigation :** RBAC minimal pour CI/CD (jamais `get secrets`), Sealed Secrets ou Vault pour les secrets, audit log RBAC.
---
**P1-4 — Network Policies absentes (implicite dans la description)**
- **Non mentionné dans le scénario.**
- **Faille :** Sans NetworkPolicy Kubernetes, tous les pods peuvent communiquer avec tous les autres. Le compte CI/CD peut spawner un pod et appeler directement Redis, Elasticsearch, l'API interne.
- **Exploitation :** `kubectl run attacker --image=redis:alpine -- redis-cli -h redis-service KEYS "ac_custom_auth:*"`.
- **Mitigation :** NetworkPolicy deny-all par défaut, allowlist explicite entre services.
---
**P1-5 — Elasticsearch mapping dynamique + injection JSON logs**
- **Faille :** Les champs loggués sont mappés en `text` → analysés. Un attaquant qui contrôle le contenu d'un log peut injecter des champs supplémentaires via un JSON malformé qui "ferme" l'objet et en ouvre un nouveau.
- **Exploitation :** Injecter `{"user":"admin","action":"login","extra":{"is_admin":true}}` dans un champ log → Kibana interprète `extra.is_admin` comme un champ structuré → possible exploitation de dashboards/alertes basés sur ces champs.
- **Condition :** Accès à Elasticsearch via credentials CI/CD pour lire + injecter.
- **Mitigation :** Mapping strict (pas dynamic), validation du schéma à l'ingestion Fluentd, index en read-only après rotation.
---
### P2 — MOYENS (surface d'attaque, exploitation complexe ou indirecte)
---
**P2-1 — Redis partagée entre tous les clients (design)**
- **Faille architecturale :** Même sans le wildcard, une Redis partagée = blast radius maximal en cas de compromission. Isolation zéro entre tenants.
- **Mitigation :** Redis par tenant (cf. `feedback_docker_network_isolation.md`), ou au minimum ACL Redis 6+ avec `AUTH` par client.
---
**P2-2 — Fluentd + Elasticsearch sans authentification forte**
- **Faille probable :** Fluentd pousse les logs souvent sans TLS ni auth vers Elasticsearch (pattern courant). Si le réseau interne K8s est accessible (P1-4), les logs de tous les clients sont lisibles.
- **Mitigation :** TLS + auth sur l'endpoint Elasticsearch, Fluentd avec certificat client.
---
**P2-3 — Index Elasticsearch rotatifs par projet — cross-tenant lisibles**
- **Faille :** Les index sont nommés par projet mais dans le même cluster. Un `_search` sur `*` ou sur un index mal nommé peut retourner des logs d'autres clients.
- **Mitigation :** Index-level permissions (Elasticsearch Security / X-Pack), ou cluster dédié par client.
---
**P2-4 — `/health` et `/metrics` exposition latérale**
- **Faille :** Ces endpoints retournent souvent des infos structurelles (version, dépendances, état interne). Même sans auth, ils permettent le fingerprinting de la stack.
- **Mitigation :** `/health` public OK (liveness), `/metrics` derrière NetworkPolicy + token fort (pas md5).
---
## FAUX POSITIFS
| Élément | Statut | Raison |
|---|---|---|
| Module `ac_custom_auth` | **Faux positif** | Explicitement fictif dans l'énoncé |
| Credentials GitLab "leakés" | **Vecteur scénario** | Hypothèse de départ, pas une faille à identifier ici |
| `ac_custom_auth:client123_session` | **Exemple pédagogique** | Clé d'illustration, pas une vraie clé en prod |
---
## SYNTHÈSE — CHEMIN D'ATTAQUE EN 10 MINUTES
```
0:00 — Credentials CI/CD → kubectl access
0:30 — kubectl get secret -n prod → token admin (P1-3)
OU kubectl get pods → exec dans un pod → env | grep TOKEN
2:00 — Si RBAC bloquant : Redis wildcard via pod attacker (P0-1 + P1-4)
4:00 — Elasticsearch access → extraire le token Prometheus (P0-3)
5:00 — /api/v1/internal/metrics → cartographie de la stack
7:00 — Staging WAF-free pour affiner les payloads (P0-4)
9:00 — Null byte Host header pour accès backends internes (P0-2)
```
**Résultat :** Le token admin est exfiltré avant la fin du scénario via **au moins 3 chemins indépendants**.
---
## VERDICT DRILL
**Score M