
🔪 PoC do ataque CRIME : um oracle de compressão ataca CVE-2012-4929 🔪
Ataque CRIME: um ataque de oráculo de compressão CVE-2012-4929 descoberto por Juliano Rizzo e Thai Duong;
Em um ataque de oráculo de compressão, o uso de compressão de dados adaptativa em uma mistura de texto simples escolhido e texto simples desconhecido pode resultar em alterações sensíveis ao conteúdo no comprimento do texto comprimido que podem ser detectadas mesmo que o conteúdo do próprio texto comprimido seja então criptografado. Isso pode ser usado em ataques de protocolo para detectar quando o texto simples conhecido injetado é até parcialmente semelhante ao conteúdo desconhecido de uma parte secreta da mensagem, reduzindo bastante a complexidade de uma busca por uma correspondência para o texto secreto. Os ataques CRIME e BREACH são exemplos de ataques de protocolo que usam esse fenômeno.
O ataque CRIME permite recuperar dados criptografados enviados por um cliente a um servidor usando o comprimento dos dados criptografados. Ele não permite recuperar a chave privada usada para criptografar a mensagem ou a solicitação HTTP.
Muitos artigos explicam como o ataque CRIME funciona, mas estas são as melhores explicações que encontrei na internet:
Este ataque não é realmente complexo; a parte realmente interessante é a implementação, que é um pouco diferente da "teoria".
Vamos verificar o método ingênuo conforme descrito no artigo; é uma boa maneira de entender como funciona:
O atacante pode controlar a solicitação enviada pelo cliente (usando JavaScript, por exemplo). O objetivo é recuperar o cookie secreto. O atacante envia várias solicitações como esta e verifica o comprimento dos dados criptografados:
| Solicitação | comprimento |
|---|---|
| GET /cookie= DATA cookie=quokkalight | 80 |
| GET /cookie=a DATA cookie=quokkalight | 81 |
| GET /cookie=b DATA cookie=quokkalight | 81 |
| GET /cookie=. DATA cookie=quokkalight | 81 |
| GET /cookie=q DATA cookie=quokkalight | 80 |
Como cookie=q corresponde a cookie=quokkalight do cookie secreto, o comprimento dos dados criptografados será o mesmo e o atacante sabe que encontrou um byte.
Mas esse método falha algumas vezes e não pode ser confiável; então, em vez disso, usaremos outro método.
Primeiro, enviamos uma solicitação com o caractere que queremos encontrar seguido de vários caracteres que não podem ser encontrados na solicitação inicial, como alguns caracteres especiais: chr(i) + "#:/[@/&". Então enviamos uma segunda solicitação, mas invertemos o payload assim: "#:/[@/&" + chr(i) e comparamos os dois comprimentos. Se len(enc(req1)) < len(enc(req2)), então encontramos um byte. Esse método é chamado de two_tries e é muito mais confiável:
| Solicitação para recuperar o byte q | comprimento |
|---|---|
| GET /cookie=a~#:/[@/& DATA cookie=quokkalight | 81 |
| GET /cookie=~#:/[@/&a DATA cookie=quokkalight | 81 |
| GET /cookie=b~#:/[@/& DATA cookie=quokkalight | 81 |
| GET /cookie=~#:/[@/&b DATA cookie=quokkalight | 81 |
| GET /cookie=q~#:/[@/& DATA cookie=quokkalight | 80 |
| GET /cookie=~#:/[@/&q DATA cookie=quokkalight | 81 |
O atacante encontrou um byte!
if len(enc(request1)) < len(enc(request2)):
print("found byte")
O método two_tries que implementei é totalmente recursivo, mas por quê? Às vezes, mais de um byte pode ser encontrado porque a compressão corresponde a vários padrões.
Vamos pegar o segredo: cookie=quokkalight. Se executarmos o algoritmo two_tries, encontraremos o seguinte resultado:
result 1: cookie=quokie=quokie=quokie=quokie=quokie=
result 2: cookie=quokkalight
O algoritmo precisa percorrer todos os caminhos na árvore para encontrar todas as soluções possíveis. Podemos ver todos os resultados como uma árvore que pode ser representada assim:

A prova de conceito do ataque CRIME contra o modo de cifra de fluxo pode ser encontrada no arquivo: CRIME-RC4-poc.py. Esta é uma implementação em Python da explicação anterior.
python3 CRIME-RC4-poc.py
Demonstração completa e resultado:
Quando o modo de cifra CBC é usado com AES ou DES, o ataque não é tão simples quanto com RC4. Como tudo é dividido em blocos, o ataque é um pouco mais complicado (não muito).
Por exemplo, digamos que usamos AES com modo de cifra CBC: o bloco será dividido com um comprimento de 16 e um padding será adicionado ao final se len(data)%16 != 0.
No modo CBC, é importante notar que o payload payload=rand produzirá um comprimento de 16 e não 12, pois um padding será adicionado ao final dos dados antes da criptografia. Portanto, nosso ataque anterior não funciona.
Exemplo:
| bloco1 | bloco2 | bloco3 | comprimento |
|---|---|---|---|
| GET /cookie= DA | TA cookie=quokka | light + PAD(11) | 48 |
| GET /cookie=a DA | TA cookie=quokka | light + PAD(10) | 48 |
| GET /cookie=b DA | TA cookie=quokka | light + PAD(10) | 48 |
| GET /cookie=. DA | TA cookie=quokka | light + PAD(10) | 48 |
| GET /cookie=q DA | TA cookie=quokka | light + PAD(11) | 48 |
Neste exemplo, o comprimento será sempre o mesmo, porque se adicionarmos ou removermos um byte, o comprimento será sempre o mesmo; apenas o padding mudará. O atacante vê apenas os dados criptografados e não tem como saber o padding usando os dados criptografados.
Solução: manipular a especificação do modo CBC, para que o comprimento do padding seja 1, adicionando um valor aleatório na variável GARB (no parâmetro GET, já que o atacante controla os dados GET e POST).
| bloco1 | bloco2 | bloco3 | bloco4 | comprimento |
|---|---|---|---|---|
| GET /GARBc | ookie= DATA coo | kie=quokkalight + PAD(1) | 48 | |
| GET /GARBc | ookie=a DATA coo | kie=quokkalight | PAD(16) | 64 |
| GET /GARBc | ookie=b DATA coo | kie=quokkalight | PAD(16) | 64 |
| GET /GARBc | ookie=. DATA coo | kie=quokkalight | PAD(16) | 64 |
| GET /GARBc | ookie=q DATA coo | kie=quokkalight + PAD(1) | 48 |
Se o byte corresponder a um padrão, o comprimento será o mesmo; se não corresponder, o comprimento será diferente.
Em seguida, basta usar o mesmo método explicado na parte RC4; apenas adicionamos uma etapa antes.
adjust_padding() para que possamos ter um padding de comprimento 1two_tries_recursive() e podemos encontrar a FLAG secreta!python3 CRIME-cbc-poc.py
em breve...
\ /
\ _ /
----/_\----
x--------------( . )--------------x
x|x | |_|\_/|_| | x|x
x x x x