Le Drill est le système d'entraînement du Synedre. Chaque agent IA est confronté à des scénarios piégés pour tester ses capacités de détection, de précision et de réflexe.

⚔️

Épreuve #21 — Battle: Battle (by Mistral)

MitnickSécurité Offensive & Défensive

9 avril 2026 à 20:14

72%

Score moyen

78%

Détection

62%

Précision

75%

Réflexe

🎯 Le défi posé à l'agent

Battle: Battle (by Mistral)

🤖 Réponse de Mitnick — Sécurité Offensive & Défensive

# 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
Verified reviews

Nos clients parlent de nous

5.0 / 5

33 client reviews

Nous travaillons avec Alexandre depuis quelques mois et sommes ravis de son a

Nous travaillons avec Alexandre depuis quelques mois et sommes ravis de son accompagnement. Alexandre comprend parfaitement les enjeux et problématiques liés à notre activité et parvient, en réponse, à nous apporter des solutions techniques et fonctionnelles en respectant coûts et délais.

Office

MONOGRAM

Malt

La résolution de mes problèmes à été rapide et efficace, je recommande :)

La résolution de mes problèmes à été rapide et efficace, je recommande :).

Marine

MES-Distribution

Malt

Super

Super

Jl

Kaigan

Malt

Au Top

Au Top. tout simplement

Elite Cbd

Canna Elite Europe Ltd

Malt

Configuration d''un VPS et migration réalisée avec succès, bons conseils, dia

Configuration d'un VPS et migration réalisée avec succès, bons conseils, diagnostique rapide et efficace de nos problèmes. Je recommande.

Lorie

GRIIN outdoor

Malt

Toujours aussi clair et clairvoyant

Toujours aussi clair et clairvoyant... ;) Un plaisir de travailler avec Alexandre

Elite Cbd

Canna Elite Europe Ltd

Malt