Contexte technique
Le site developers.google.com utilise Flask pour gérer la session OAuth. Lors d’un appel à /oauth2authorize, le serveur crée un cookie de session au format payload.timestamp.signature. Le cookie observé mesure environ 1 200 octets, bien au‑delà d’un simple jeton CSRF, ce qui a attiré l’attention du chercheur. Flask signe les cookies avec itsdangerous mais ne les chiffre pas, rendant le contenu lisible après décodage base64 et, le cas échéant, décompression zlib.
Le décodage révèle un dictionnaire JSON contenant une clé google_oauth2_flow_<csrf> dont la valeur " b" représente des octets sérialisés avec pickle. Le pickle inclut les champs client_id et client_secret d’un compte OAuth Google, le secret étant stocké en clair dans le cookie.
Mécanisme de la vulnérabilité
Le secret OAuth sert également de SECRET_KEY pour dériver la clé de signature du cookie via HMAC‑SHA1 (derived_key = hmac.digest(client_secret, b"cookie-session", "sha1")). En recomposant la signature avec la même clé, le chercheur a reproduit exactement le signature présent dans le cookie, prouvant que le secret était le même pour le chiffrement et l’authentification. Ainsi, quiconque possédant le secret pouvait forger un cookie valide.
import hmac, base64, zlib, json
payload, timestamp, signature = cookie.rsplit('.', 2)
derived = hmac.digest(client_secret, b"cookie-session", "sha1")
expected = hmac.digest(derived, f"{payload}.{timestamp}".encode(), "sha1")
assert expected == base64.urlsafe_b64decode(signature)Le serveur désérialise ensuite le champ google_oauth2_flow_<csrf> avec pickle.loads sans aucune validation. Un pickle malveillant peut exécuter du code arbitraire grâce aux opcodes REDUCE qui invoquent des fonctions Python.
Exploitation et preuve de concept
Le chercheur a créé un pickle contenant une classe Sleep dont la méthode __reduce__ renvoie (time.sleep, (N,)). En injectant ce pickle dans le cookie et en signant le tout avec le secret récupéré, le serveur a exécuté time.sleep(N). Les temps de réponse mesurés (0 s, 3 s, 5 s, 8 s) correspondaient exactement aux valeurs N, confirmant l’exécution de code sur les serveurs Google.
Le même secret signait les cookies de sept domaines Google (firebase.google.com, developer.android.com, source.android.com, docs.partner.android.com, etc.), ce qui a permis une exécution de code trans‑domaines avec seulement deux requêtes HTTP.
Correctifs proposés
Quatre mesures sont nécessaires : (1) rotation immédiate des secrets OAuth exposés et révocation des sessions signées avec ceux‑ci ; (2) génération d’une SECRET_KEY haute entropie propre à chaque déploiement, stockée côté serveur et indépendante des credentials OAuth ; (3) stockage du flux OAuth uniquement côté serveur, le cookie ne contenant qu’une référence opaque ; (4) remplacement de pickle par un format de données sérialisé sans exécution (par ex. JSON avec validation de schéma). Chacune de ces mesures aurait suffi à interrompre la chaîne d’exploitation.
Google a reçu le rapport le 6 août 2026, l’a trié le 7 août, et a publié un correctif le 7 octobre 2026. La prime attribuée à la découverte s’élève à 90 000 $, dont 75 000 $ pour la vulnérabilité RCE et un facteur multiplicateur pour la qualité du rapport.