Cookies Hacking
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Las cookies vienen con varios atributos que controlan su comportamiento en el navegador del usuario. Aquí hay un resumen de estos atributos en una voz más pasiva:
La fecha de caducidad de una cookie se determina por el atributo Expires
. Por el contrario, el atributo Max-age
define el tiempo en segundos hasta que se elimina una cookie. Opta por Max-age
ya que refleja prácticas más modernas.
Los hosts que recibirán una cookie se especifican mediante el atributo Domain
. Por defecto, esto se establece en el host que emitió la cookie, sin incluir sus subdominios. Sin embargo, cuando el atributo Domain
se establece explícitamente, abarca también los subdominios. Esto hace que la especificación del atributo Domain
sea una opción menos restrictiva, útil para escenarios donde es necesario compartir cookies entre subdominios. Por ejemplo, establecer Domain=mozilla.org
hace que las cookies sean accesibles en sus subdominios como developer.mozilla.org
.
Un camino de URL específico que debe estar presente en la URL solicitada para que se envíe el encabezado Cookie
se indica mediante el atributo Path
. Este atributo considera el carácter /
como un separador de directorios, permitiendo coincidencias en subdirectorios también.
Cuando dos cookies tienen el mismo nombre, la que se elige para enviar se basa en:
La cookie que coincide con la ruta más larga en la URL solicitada.
La cookie establecida más recientemente si las rutas son idénticas.
El atributo SameSite
dicta si las cookies se envían en solicitudes que provienen de dominios de terceros. Ofrece tres configuraciones:
Strict: Restringe el envío de la cookie en solicitudes de terceros.
Lax: Permite que la cookie se envíe con solicitudes GET iniciadas por sitios web de terceros.
None: Permite que la cookie se envíe desde cualquier dominio de terceros.
Recuerda, al configurar cookies, entender estos atributos puede ayudar a garantizar que se comporten como se espera en diferentes escenarios.
Tipo de Solicitud
Código de Ejemplo
Cookies Enviadas Cuando
Enlace
<a href="..."></a>
NotSet*, Lax, None
Prerender
<link rel="prerender" href=".."/>
NotSet*, Lax, None
Formulario GET
<form method="GET" action="...">
NotSet*, Lax, None
Formulario POST
<form method="POST" action="...">
NotSet*, None
iframe
<iframe src="..."></iframe>
NotSet*, None
AJAX
$.get("...")
NotSet*, None
Imagen
<img src="...">
NetSet*, None
Tabla de Invicti y ligeramente modificada. Una cookie con el atributo SameSite mitigará ataques CSRF donde se necesita una sesión iniciada.
*Ten en cuenta que desde Chrome80 (feb/2019) el comportamiento predeterminado de una cookie sin un atributo de cookie SameSite será lax (https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/). Ten en cuenta que temporalmente, después de aplicar este cambio, las cookies sin una política SameSite en Chrome serán tratadas como None durante los primeros 2 minutos y luego como Lax para solicitudes POST de nivel superior entre sitios.
Esto evita que el cliente acceda a la cookie (a través de Javascript, por ejemplo: document.cookie
)
Si la página está enviando las cookies como respuesta a una solicitud (por ejemplo, en una página PHPinfo), es posible abusar de la XSS para enviar una solicitud a esta página y robar las cookies de la respuesta (ver un ejemplo en https://hackcommander.github.io/posts/2022/11/12/bypass-httponly-via-php-info-page/.
Esto podría ser evadido con solicitudes TRACE HTTP ya que la respuesta del servidor (si este método HTTP está disponible) reflejará las cookies enviadas. Esta técnica se llama Cross-Site Tracking.
Esta técnica es evitada por navegadores modernos al no permitir el envío de una solicitud TRACE desde JS. Sin embargo, se han encontrado algunas evasiones en software específico como enviar \r\nTRACE
en lugar de TRACE
a IE6.0 SP2.
Otra forma es la explotación de vulnerabilidades de día cero en los navegadores.
Es posible sobrescribir cookies HttpOnly realizando un ataque de desbordamiento de Cookie Jar:
Es posible usar un ataque de Cookie Smuggling para exfiltrar estas cookies.
La solicitud solo enviará la cookie en una solicitud HTTP solo si la solicitud se transmite a través de un canal seguro (típicamente HTTPS).
Las cookies con el prefijo __Secure-
deben establecerse junto con la bandera secure
de páginas que están aseguradas por HTTPS.
Para las cookies con el prefijo __Host-
, se deben cumplir varias condiciones:
Deben establecerse con la bandera secure
.
Deben originarse de una página asegurada por HTTPS.
Se les prohíbe especificar un dominio, impidiendo su transmisión a subdominios.
La ruta para estas cookies debe establecerse en /
.
Es importante notar que las cookies con el prefijo __Host-
no pueden ser enviadas a superdominios o subdominios. Esta restricción ayuda a aislar las cookies de la aplicación. Por lo tanto, emplear el prefijo __Host-
para todas las cookies de la aplicación puede considerarse una buena práctica para mejorar la seguridad y el aislamiento.
Así, una de las protecciones de las cookies con prefijo __Host-
es prevenir que sean sobrescritas desde subdominios. Previniendo, por ejemplo, ataques de Cookie Tossing. En la charla Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities (paper) se presenta que era posible establecer cookies con prefijo __HOST- desde un subdominio, engañando al parser, por ejemplo, añadiendo "=" al principio o al final...:
O en PHP era posible añadir otros caracteres al principio del nombre de la cookie que iban a ser reemplazados por caracteres de subrayado, permitiendo sobrescribir cookies __HOST-
:
Si una cookie personalizada contiene datos sensibles, revísala (especialmente si estás participando en un CTF), ya que podría ser vulnerable.
Los datos sensibles incrustados en las cookies siempre deben ser examinados. Las cookies codificadas en Base64 o formatos similares a menudo pueden ser decodificadas. Esta vulnerabilidad permite a los atacantes alterar el contenido de la cookie e impersonar a otros usuarios codificando sus datos modificados de nuevo en la cookie.
Este ataque implica robar la cookie de un usuario para obtener acceso no autorizado a su cuenta dentro de una aplicación. Al usar la cookie robada, un atacante puede hacerse pasar por el usuario legítimo.
En este escenario, un atacante engaña a una víctima para que use una cookie específica para iniciar sesión. Si la aplicación no asigna una nueva cookie al iniciar sesión, el atacante, poseyendo la cookie original, puede hacerse pasar por la víctima. Esta técnica se basa en que la víctima inicie sesión con una cookie proporcionada por el atacante.
Si encontraste un XSS en un subdominio o controlas un subdominio, lee:
Cookie TossingAquí, el atacante convence a la víctima para que use la cookie de sesión del atacante. La víctima, creyendo que ha iniciado sesión en su propia cuenta, realizará inadvertidamente acciones en el contexto de la cuenta del atacante.
Si encontraste un XSS en un subdominio o controlas un subdominio, lee:
Cookie TossingHaz clic en el enlace anterior para acceder a una página que explica posibles fallas en JWT.
Los JSON Web Tokens (JWT) utilizados en cookies también pueden presentar vulnerabilidades. Para obtener información detallada sobre posibles fallas y cómo explotarlas, se recomienda acceder al documento vinculado sobre el hacking de JWT.
Este ataque obliga a un usuario autenticado a ejecutar acciones no deseadas en una aplicación web en la que actualmente está autenticado. Los atacantes pueden explotar cookies que se envían automáticamente con cada solicitud al sitio vulnerable.
(Revisa más detalles en la investigación original) Los navegadores permiten la creación de cookies sin un nombre, lo que se puede demostrar a través de JavaScript de la siguiente manera:
El resultado en el encabezado de la cookie enviada es a=v1; test value; b=v2;
. Intrigantemente, esto permite la manipulación de cookies si se establece una cookie con un nombre vacío, potencialmente controlando otras cookies al establecer la cookie vacía a un valor específico:
Esto lleva a que el navegador envíe un encabezado de cookie interpretado por cada servidor web como una cookie llamada a
con un valor b
.
En Chrome, si un código de sustitución Unicode es parte de una cookie establecida, document.cookie
se corrompe, devolviendo una cadena vacía posteriormente:
Esto resulta en que document.cookie
devuelve una cadena vacía, lo que indica una corrupción permanente.
(Revisa más detalles en la investigación original) Varios servidores web, incluidos los de Java (Jetty, TomCat, Undertow) y Python (Zope, cherrypy, web.py, aiohttp, bottle, webob), manejan incorrectamente las cadenas de cookies debido al soporte obsoleto de RFC2965. Lee un valor de cookie entre comillas dobles como un solo valor, incluso si incluye puntos y comas, que normalmente deberían separar pares clave-valor:
(Revisa más detalles en la investigación original) El análisis incorrecto de cookies por parte de los servidores, notablemente Undertow, Zope y aquellos que utilizan http.cookie.SimpleCookie
y http.cookie.BaseCookie
de Python, crea oportunidades para ataques de inyección de cookies. Estos servidores no delimitan adecuadamente el inicio de nuevas cookies, lo que permite a los atacantes suplantar cookies:
Undertow espera una nueva cookie inmediatamente después de un valor entre comillas sin un punto y coma.
Zope busca una coma para comenzar a analizar la siguiente cookie.
Las clases de cookies de Python comienzan a analizar en un carácter de espacio.
Esta vulnerabilidad es particularmente peligrosa en aplicaciones web que dependen de la protección CSRF basada en cookies, ya que permite a los atacantes inyectar cookies de token CSRF suplantadas, potencialmente eludiendo medidas de seguridad. El problema se agrava por el manejo de nombres de cookies duplicados en Python, donde la última ocurrencia anula las anteriores. También plantea preocupaciones para las cookies __Secure-
y __Host-
en contextos inseguros y podría llevar a eludir autorizaciones cuando las cookies se pasan a servidores de backend susceptibles a suplantación.
Según este blog, podría ser posible usar el atributo de cookie $Version=1
para hacer que el backend use una lógica antigua para analizar la cookie debido a la RFC2109. Además, otros valores como $Domain
y $Path
pueden ser utilizados para modificar el comportamiento del backend con la cookie.
Este análisis indica deshacer la codificación de valores escapados dentro de las cookies, por lo que "\a" se convierte en "a". Esto puede ser útil para eludir WAFS ya que:
eval('test') => prohibido
"\e\v\a\l\(\'\t\e\s\t\'\)" => permitido
En la RFC2109 se indica que se puede usar una coma como separador entre valores de cookies. Y también es posible agregar espacios y tabulaciones antes y después del signo igual. Por lo tanto, una cookie como $Version=1; foo=bar, abc = qux
no genera la cookie "foo":"bar, admin = qux"
sino las cookies foo":"bar"
y "admin":"qux"
. Nota cómo se generan 2 cookies y cómo se eliminó el espacio antes y después del signo igual.
Finalmente, diferentes puertas traseras se unirían en una cadena diferentes cookies pasadas en diferentes encabezados de cookies como en:
Lo que podría permitir eludir un WAF como en este ejemplo:
La cookie es la misma cada vez que inicias sesión.
Cierra sesión e intenta usar la misma cookie.
Intenta iniciar sesión con 2 dispositivos (o navegadores) en la misma cuenta usando la misma cookie.
Verifica si la cookie tiene alguna información y trata de modificarla.
Intenta crear varias cuentas con nombres de usuario casi idénticos y verifica si puedes ver similitudes.
Revisa la opción de "recordarme" si existe para ver cómo funciona. Si existe y podría ser vulnerable, siempre usa la cookie de recordarme sin ninguna otra cookie.
Verifica si la cookie anterior funciona incluso después de cambiar la contraseña.
Si la cookie permanece igual (o casi) cuando inicias sesión, esto probablemente significa que la cookie está relacionada con algún campo de tu cuenta (probablemente el nombre de usuario). Entonces puedes:
Intenta crear muchas cuentas con nombres de usuario muy similares y trata de adivinar cómo está funcionando el algoritmo.
Intenta fuerza bruta al nombre de usuario. Si la cookie se guarda solo como un método de autenticación para tu nombre de usuario, entonces puedes crear una cuenta con el nombre de usuario "Bmin" y fuerza bruta cada bit de tu cookie porque una de las cookies que intentarás será la que pertenece a "admin".
Intenta Padding Oracle (puedes descifrar el contenido de la cookie). Usa padbuster.
Padding Oracle - Ejemplos de Padbuster
Padbuster hará varios intentos y te preguntará cuál condición es la condición de error (la que no es válida).
Luego comenzará a descifrar la cookie (puede tardar varios minutos)
Si el ataque se ha realizado con éxito, entonces podrías intentar cifrar una cadena de tu elección. Por ejemplo, si quisieras encrypt user=administrator
Esta ejecución te dará la cookie correctamente encriptada y codificada con la cadena user=administrator dentro.
CBC-MAC
Tal vez una cookie podría tener algún valor y podría ser firmada usando CBC. Entonces, la integridad del valor es la firma creada utilizando CBC con el mismo valor. Como se recomienda usar como IV un vector nulo, este tipo de verificación de integridad podría ser vulnerable.
El ataque
Obtener la firma del nombre de usuario administ = t
Obtener la firma del nombre de usuario rator\x00\x00\x00 XOR t = t'
Establecer en la cookie el valor administrator+t' (t' será una firma válida de (rator\x00\x00\x00 XOR t) XOR t = rator\x00\x00\x00
ECB
Si la cookie está encriptada usando ECB podría ser vulnerable. Cuando inicias sesión, la cookie que recibes tiene que ser siempre la misma.
Cómo detectar y atacar:
Crea 2 usuarios con casi los mismos datos (nombre de usuario, contraseña, correo electrónico, etc.) y trata de descubrir algún patrón dentro de la cookie dada.
Crea un usuario llamado, por ejemplo, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" y verifica si hay algún patrón en la cookie (como ECB encripta con la misma clave cada bloque, los mismos bytes encriptados podrían aparecer si el nombre de usuario está encriptado).
Debería haber un patrón (con el tamaño de un bloque utilizado). Así que, sabiendo cómo están encriptados un montón de "a", puedes crear un nombre de usuario: "a"*(tamaño del bloque)+"admin". Luego, podrías eliminar el patrón encriptado de un bloque de "a" de la cookie. Y tendrás la cookie del nombre de usuario "admin".
Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE) Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE)