O cookie que era um objeto: identificando deserialização em Java
O desafio
O app Java da Pennywharf guarda sua sessão em um cookie e confia nele quando ele volta. O cookie não é um token assinado e não é JSON: é o objeto de sessão bruto, codificado. Isso importa, porque se o servidor reconstrói um objeto direto a partir de bytes enviados por um cliente, quem decide o que será construído é o cliente. Decodifique o cookie no workbench e leia a assinatura logo no início. Diga em que formato este cookie realmente está.
O que você vai aprender
- Decodificar um blob em base64 e ler seus magic bytes iniciais
- Reconhecer ac ed 00 05 como o cabeçalho do stream de serialização do Java
- Explicar por que deserializar bytes controlados pelo cliente é perigoso
- Listar os sinais no início do blob para Java, pickle, .NET e PHP
- Indicar a alternativa segura: ids de sessão opacos e formatos só de dados
Habilidades testadas
Pré-requisitos
- O que é base64
- A ideia de que arquivos e blobs começam com uma assinatura
Como funciona
Um cookie que guarda estado pode fazer isso de duas formas seguras: um id opaco que aponta para dados no servidor, ou um token assinado que contém apenas dados. Também pode fazer da forma perigosa, enviando o próprio objeto, serializado. Quando o servidor lê esse cookie de volta, ele reconstrói um objeto diretamente a partir de bytes que o cliente enviou.
Cada formato de serialização se anuncia no início. Streams Java começam com ac ed 00 05 (base64 rO0AB). Decodificar este cookie mostra exatamente isso, seguido de um descritor de classe. Reconstruir um objeto assim executa caminhos de código escolhidos pelo atacante, e com as classes certas presentes isso vira execução remota de código. Nenhuma chave está envolvida, porque nada foi criptografado.
Identificar o formato do blob é o primeiro passo: 80 04 / gASV é um pickle do Python, AAEAAAD///// é .NET, O:4: é PHP.
Erros comuns
- Tratá-lo como um JWT. Não há pontos nem header/payload/signature; ele não decodifica para JSON.
- Parar no nome da classe. O
com.loomhaus.Sessionlegível é uma pista, mas a assinaturaac ed 00 05é a prova. - Procurar uma chave. O cookie é codificado, não criptografado; From Base64 é toda a decodificação.
- Responder
base64. Base64 é só o invólucro de transporte, não o que os bytes são.
Como se proteger
Não reconstrua objetos a partir de entrada que o cliente pode definir.
- Mantenha o estado da sessão no servidor, atrás de um id opaco, aleatório e imprevisível. O cookie deve carregar o id, nunca o objeto.
- Se o estado precisar passar pelo cliente, use um formato só de dados (JSON) interpretado em campos conhecidos, e assine-o para que não possa ser adulterado.
- Se um caminho legado precisar deserializar, use allowlists estritas de classes permitidas e mantenha bibliotecas de gadgets perigosos fora do classpath.