
PoC in Python per CVE-2026-3456 che dimostra l'account takeover tramite race condition in OAuth2 PKCE, con un server di autenticazione vulnerabile e uno script di exploit con code-verifier concorrenti.
Una condizione di corsa nel server di autorizzazione OAuth2 consente a un attaccante di riutilizzare il codice di autorizzazione della vittima prima che il client legittimo lo riscatti, indovinando o forzando con brute force il code_verifier PKCE all'interno di una breve finestra temporale.
Gravità: Alta (Compromissione dell'account)
#!/usr/bin/env python3
"""
vulnerable_auth_server.py - Authorization server with race condition window.
"""
import time, random, hashlib, base64, secrets
from http.server import HTTPServer, BaseHTTPRequestHandler
import urllib.parse
# Simulated storage
auth_codes = {} # code -> {client_id, redirect_uri, code_challenge, scope, user}
tokens = {}
def generate_code():
return secrets.token_urlsafe(16)
class AuthHandler(BaseHTTPRequestHandler):
def do_GET(self):
parsed = urllib.parse.urlparse(self.path)
params = urllib.parse.parse_qs(parsed.query)
if parsed.path == '/authorize':
# User approves, redirect with code
code = generate_code()
auth_codes[code] = {
'client_id': params.get('client_id', ['unknown'])[0],
'redirect_uri': params.get('redirect_uri', [''])[0],
'code_challenge': params.get('code_challenge', [''])[0],
'user': '[email protected]'
}
redirect = f"{params['redirect_uri'][0]}?code={code}&state={params.get('state',[''])[0]}"
self.send_response(302)
self.send_header('Location', redirect)
self.end_headers()
elif parsed.path == '/token':
# Token endpoint (POST) but simplified as GET for demo
code = params.get('code', [''])[0]
verifier = params.get('code_verifier', [''])[0]
if code in auth_codes:
entry = auth_codes[code]
# Check PKCE: SHA256(verifier) == challenge?
challenge = base64.urlsafe_b64encode(hashlib.sha256(verifier.encode()).digest()).decode().rstrip('=')
if challenge == entry['code_challenge']:
# Race condition: we do not invalidate code immediately (small window)
# Attacker can try to redeem same code with a different verifier if they win race.
access_token = secrets.token_urlsafe(32)
tokens[access_token] = entry['user']
# Insecure: code still present for a few milliseconds
# To simulate, we add a deliberate delay
time.sleep(0.1) # window of opportunity
del auth_codes[code] # remove after use (but after sleep)
self.send_response(200)
self.end_headers()
self.wfile.write(f'access_token={access_token}'.encode())
else:
self.send_response(400)
self.end_headers()
self.wfile.write(b'invalid code_verifier')
else:
self.send_response(400)
self.end_headers()
self.wfile.write(b'invalid code')
else:
self.send_response(404)
self.end_headers()
server = HTTPServer(('0.0.0.0', 5000), AuthHandler)
print("Auth server on :5000")
server.serve_forever()
Una vulnerabilità nel flusso PKCE del server di autorizzazione OAuth2 consente a un attaccante di riscattare un codice di autorizzazione prima del client legittimo, aggirando PKCE tramite una condizione di corsa. Il server non invalida atomicamente il codice, lasciando una finestra in cui un verifier dannoso può essere provato.
python vulnerable_auth_server.py
python race_condition_exploit.py