RCE en Google DevSite: cómo un secreto filtrado habilitó la ejecución remota de código
Un investigador encontró una vulnerabilidad crítica en la plataforma DevSite de Google donde se utilizaba un secreto de cliente OAuth para firmar cookies de sesión, lo que permitía la ejecución remota de código en múltiples dominios.
Traducido automáticamente del original en inglés.
El investigador de seguridad Simon Koeck descubrió una vulnerabilidad crítica de ejecución remota de código (RCE) en la plataforma compartida DevSite de Google en agosto de 2026. El fallo permitía a un atacante ejecutar código arbitrario en servidores que alojaban documentación para desarrolladores de servicios como Firebase y Android, explotando una cookie de sesión Flask mal configurada. Google otorgó a Koeck $90,000 por el informe tras confirmar que el problema afectaba a varios subdominios de alto perfil.
Qué ocurrió
Koeck estaba mapeando el flujo de autenticación OAuth utilizado en los sitios de documentación para desarrolladores de Google, incluyendo developers.google.com. Notó que la cookie de sesión Flask emitida durante el handshake OAuth era inusualmente grande, de aproximadamente 1,200 bytes. Dado que las cookies de Flask están firmadas pero no cifradas, decodificó la carga útil para inspeccionar su contenido. Dentro, encontró un objeto serializado con pickle que contenía una instancia de oauth2client.client.OAuth2WebServerFlow. Crucialmente, este objeto mantenía el client_id y el client_secret de Google OAuth en texto plano.
La presencia del secreto de cliente en una cookie del lado del cliente ya constituía un hallazgo significativo de seguridad. Sin embargo, Koeck comprendió que las implicaciones iban más allá cuando probó si este secreto también se usaba como la SECRET_KEY de Flask para firmar la propia cookie. Derivando la clave de firma del secreto de cliente expuesto utilizando la lógica estándar de la librería itsdangerous de Flask, logró reproducir la firma de la cookie sin conexión. Esto significaba que el servidor estaba usando un secreto almacenado dentro de los mismos datos que intentaba proteger para verificar la integridad de dichos datos.
Con la capacidad de forjar firmas de sesión válidas, Koeck pudo eludir los controles de seguridad previstos. La lógica de la aplicación recuperaba el objeto de flujo OAuth de la sesión y lo deserializaba utilizando pickle.loads(). Debido a que el módulo pickle de Python puede ejecutar código arbitrario durante la deserialización si encuentra ciertos opcodes, y dado que Koeck podía ahora crear cookies válidamente firmadas, había logrado una ejecución remota de código sin autenticación. Lo demostró inyectando cargas útiles que hacían que el servidor entrara en suspensión durante duraciones específicas, probando que el código se ejecutaba en el backend sin acceder a datos sensibles de producción.
Cómo funciona
La vulnerabilidad dependía de una cadena de tres configuraciones erróneas específicas. Primero, la aplicación almacenaba credenciales sensibles (el secreto de cliente OAuth) directamente en la cookie de sesión del usuario. Segundo, utilizaba ese mismo secreto de cliente como clave criptográfica para firmar la cookie de sesión, creando una dependencia circular donde la clave era pública para cualquiera que inspeccionara la cookie. Tercero, la aplicación deserializaba datos controlados por el usuario desde la cookie utilizando el módulo pickle de Python, que es inherentemente inseguro para entradas no confiables porque permite la instanciación de objetos y llamadas a métodos durante el proceso de carga.
Flask utiliza la librería itsdangerous para firmar cookies, derivando típicamente una clave de firma específica de la SECRET_KEY principal mediante HMAC-SHA1. Koeck replicó esta derivación localmente utilizando el secreto de cliente filtrado. Una vez confirmado que la firma coincidía, creó una nueva cookie de sesión. Insertó una carga útil maliciosa de pickle bajo la clave de sesión esperada, la firmó con la clave derivada y la envió al servidor. El servidor verificó la firma correctamente, extrajo el pickle y ejecutó las instrucciones incrustadas, como llamar a time.sleep().
Detalles clave
- La vulnerabilidad existía en la plataforma compartida DevSite, afectando a
developers.google.com,firebase.google.com,developer.android.com,source.android.comydocs.partner.android.com. - La cookie de sesión de Flask contenía un objeto
OAuth2WebServerFlowserializado con pickle que incluía elclient_secretde OAuth activo en texto plano. - El
client_secretde OAuth se utilizaba como laSECRET_KEYde Flask para firmar la cookie de sesión, permitiendo a los atacantes forjar sesiones válidas. - La ejecución remota de código se demostró utilizando cargas útiles
time.sleep(N), donde los tiempos de respuesta del servidor coincidían exactamente con la duración de suspensión inyectada. - Google clasificó el problema como RCE S0 (crítico) y otorgó una recompensa de $90,000, calculada como una base de $75,000 más un multiplicador de 1.2x por la calidad del informe.
- La solución implicó rotar secretos, separar las claves de firma de las credenciales OAuth, almacenar objetos de flujo en el servidor y reemplazar pickle con un formato de datos seguro.
Por qué importa
Este incidente destaca los peligros de usar formatos de serialización complejos como pickle para datos que cruzan límites de confianza. Aunque pickle es conveniente para preservar el estado de los objetos Python, no proporciona ningún mecanismo para restringir qué clases o funciones pueden invocarse durante la deserialización. Cuando se combina con una clave de firma comprometida, se convierte en un camino directo hacia la ejecución remota de código. Los desarrolladores a menudo asumen que las cookies firmadas son a prueba de manipulaciones, pero si la clave de firma se filtra o se gestiona deficientemente, esa garantía desaparece por completo.
Para los equipos de ingeniería, esto sirve como recordatorio para auditar cómo se gestionan y rotan los secretos. Usar una credencial para múltiples propósitos—como tanto la autenticación API como la firma de sesiones—aumenta el radio de impacto de una sola filtración. También subraya la importancia de mantener el estado sensible en el servidor. Las cookies deben contener solo referencias opacas o datos mínimos y no sensibles, especialmente cuando se trata de flujos de autenticación que involucran proveedores de terceros como Google OAuth.
Qué puedes hacer
- Audita la gestión de sesiones de tu aplicación para asegurar que las claves de firma sean distintas de otras credenciales como secretos API o tokens OAuth.
- Reemplaza
picklecon formatos de serialización seguros como JSON o Protocol Buffers para cualquier dato que viaje al cliente o cruce límites de confianza. - Almacena el estado sensible, como objetos de flujo OAuth, en sesiones o cachés del lado del servidor en lugar de en cookies del lado del cliente.
- Implementa políticas estrictas de seguridad de contenido y monitorea patrones de latencia inusuales que puedan indicar intentos de RCE ciego basado en tiempo.
- Rota inmediatamente todos los secretos expuestos si se sospecha una filtración e invalida las sesiones existentes firmadas con esas claves.
- Utiliza herramientas de análisis estático para detectar el uso de métodos de deserialización inseguros como
pickle.loads()sobre entradas no confiables.



