Por Vinicius Oliveira

O uso de métodos de compressão na transmissão de dados sempre esteve entre os objetivos das ofertas de aplicações e serviços que visavam reduzir, principalmente, o consumo de banda da rede e o tempo de transmissão dos dados.

Atualmente, boa parte destas aplicações e serviços oferecidos na Internet já utiliza métodos de compressão eficientes, tendência que deve se intensificar à medida em que mais serviços e aplicações são migrados para a nuvem, uma vez que a maioria dos modelos de contrato de serviços como Amazon Web Services ou Microsoft Azure é baseada, entre outros quesitos, na quantidade de dados transmitidos.

Paralelamente, o aumento e evolução das ameaças à segurança dos dados e o surgimento de regulamentações rigorosas para protegê-los, como a LGPD no Brasil e a GDPR na Europa, tornam a cifragem de dados um requisito tão ou mais importante do que sua compressão.

Contudo, muitas aplicações realizam a compressão de dados antes deles serem cifrados o que, em alguns casos, pode comprometer a confidencialidade dos dados transmitidos.

De forma genérica, um algoritmo de compressão tem como objetivo principal reduzir o espaço necessário para armazenar uma mesma quantidade de informações. O Deflate, por exemplo, é subdivido em dois outros algoritmos, o LZ77 e o Huffman Coding:

  • LZ77: Algoritmo responsável pela redução das redundâncias dos dados a serem comprimidos. Essas redundâncias são substituídas por referências indicando a posição onde a mesma sequência de símbolos apareceu previamente, o que possibilita a redução do tamanho original dos dados.
  • Huffman Coding: O resultado do LZ77 é utilizado como entrada para o Huffman Coding. Este algoritmo utiliza códigos de tamanho variável para representar os símbolos do texto. O tamanho do código não é idêntico para todos os símbolos. Cada código é gerado através de uma árvore binária que é construída com base em uma lógica na qual símbolos de menor frequência serão folhas mais distantes da raiz (gerando assim códigos com cadeia de bits maiores) e símbolos de maior frequência poderão ser encontrados mais próximos da raiz, gerando código com cadeias de bits menores.

Em uma requisição HTTP o campo do cabeçalho, Accept-Encoding, permite que o cliente explicite o uso de alguma codificação na comunicação (normalmente a própria compressão). Abaixo é possível observar os resultados de um teste no qual comparamos o tamanho e o tempo de resposta de duas requisições, uma que utiliza e outra que não utiliza compressão. Como os testes foram realizados no mesmo ambiente, com requisições para o mesmo website, é possível concluir que a diferença nos tempos de resposta é resultado da compressão dos dados (e não de algum fator externo), comprovando sua eficácia.

Requisição com compressão
Requisição sem compressão

Como mencionado anteriormente, apesar da importância da compressão para a redução do tamanho dos dados trafegados e, consequentemente, para a diminuição de custos e melhoria de desempenho, é de suma importância considerar também que os dados trafegados estejam em segurança. Atualmente são considerados, basicamente, dois cenários da utilização de compressão e cifragem de dados, a saber:

Comprimir depois de cifrar: Opção que não é considerada eficiente, dado que, como vimos na apresentação do algoritmo de compressão Deflate, para obter uma alta taxa de compressão, é necessário que os dados a serem comprimidos possuam redundâncias e repetições, o que não ocorre quando os dados estão cifrados.

Comprimir antes de cifrar: Opção que é utilizada na maioria dos casos. Conforme mostrado anteriormente, há uma significativa redução no tempo de transmissão dos dados e consumo de banda quando os serviços utilizam a compressão.

Apesar da opção de comprimir antes de cifrar ser a mais utilizada, ela está suscetível a ataques que podem comprometer a confidencialidade dos dados, como veremos a seguir.

Um dos possíveis ataques para se obter dados que foram comprimidos antes de terem sido cifrados envolve o uso de um código JavaScript a fim de executar no navegador da vítima um ataque de força bruta byte a byte. Esse ataque permite a um atacante inferir os dados transmitidos de forma cifrada a partir do tamanho desses dados comprimidos. Isso é possível devido a uma vulnerabilidade intrínseca ao funcionamento dos algoritmos de compressão.

Ataques desse tipo são chamado de ‘Side-Channel Attacks’. Um dos primeiros ataques de ‘Side-Channel’ com foco no protocolo HTTP recebeu o nome de ‘CRIME’, e foi utilizado para obter informações contidas nos cabeçalhos HTTP cuja compressão e cifragem tivessem sido realizadas pelo protocolo TLS. Esse ataque foi demonstrado pela primeira vez em 2012 na conferência de segurança Ekoparty, entretanto não foi muito utilizado na prática, uma vez que apenas uma pequena parcela dos servidores usavam o TLS para comprimir as requisições HTTP.

Quando alguns navegadores como o Google Chrome desabilitaram a compressão via TLS a viabilidade do CRIME diminuiu ainda mais, contudo, a metodologia deste ataque serviu de base para um outro tipo de ataque: o BREACH, apresentado em 2013 na conferência de segurança Black Hat. Enquanto o CRIME explora uma vulnerabilidade na compressão do TLS para obter informações no cabeçalho da requisição, o BREACH consegue obter informações no corpo da resposta do HTTPS quando o servidor utiliza a compressão do próprio HTTP.

Na Black Hat de 2018 foi apresentado mais um ataque capaz de comprometer a confidencialidade de dados comprimidos antes da cifragem: o VORACLE. Este ataque possibilita a obtenção de dados em túneis VPN que utilizam compressão. Para que este ataque seja viável, é necessário que a vítima esteja utilizando protocolos inerentemente inseguros, como o HTTP. Isto significa que, se a vítima visitar, por exemplo, um website que utiliza o protocolo HTTP e o atacante puder injetar dados no túnel VPN, o conteúdo cifrado e comprimido poderá ser inferido a partir do tamanho dos dados trafegados, pelo túnel VPN.

A utilização de cifragem é imprescindível em situações nas quais há tráfego de informações muito sensíveis. Contudo, nessas situações também pode ser bastante desejável a compressão dos dados pelos benefícios já elencados.

Uma vez que utilizar a compressão e a cifragem ao mesmo tempo pode comprometer a confidencialidade dos dados, é cada vez mais comum os sistemas adotarem a compressão apenas das partes que não possuam informações sensíveis. Nesse sentido, alguns dos servidores web mais populares, como o Nginx, permitem configurar diretivas para especificar quais páginas de um website deverão ser comprimidas pelo servidor ao serem acessadas.

Contudo, em alguns casos não é possível fazer a distinção das partes dos dados transmitidos. Por exemplo, no cenário dos túneis VPN citados na seção anterior, a OpenVPN, fornecedora de uma solução de VPN bastante popular, recomendou que toda compressão a nível de VPN fosse desabilitada a fim de mitigar o ataque de VORACLE. Essa recomendação da OpenVPN levou em consideração um estudo no qual foi mostrado que a compressão a nível de VPN é pouco eficaz quando comparada com a compressão usada nas camadas superiores do modelo OSI. Além disso, em muitos casos, boa parte dos dados que serão transmitidos já foram comprimidos pelos protocolos das camadas superiores ou cifrados, o que também diminui a eficácia da compressão, conforme já discutido acima.

Dessa forma, é possível observar que em determinados cenários (como o que envolve a OpenVPN), deve-se desabilitar a compressão dos dados a fim de assegurar a sua confidencialidade. Além disso, cada vez mais as instituições e as regulamentações têm passado a considerar quase todo dado de um usuário como informação sensível. Assim, mesmo que um dado sistema ofereça a possibilidade de comprimir apenas parte dos dados trafegados, como o Nginx, esse recurso não pode ser utilizado por muitos websites nos quais há informações do usuário em quase todas as suas páginas. Desse modo, para esses sites não ficarem suscetíveis a ataques que utilizam o Side-Channel da compressão, eles precisam desabilitar por completo a funcionalidade.

Considerando os cenários e protocolos descritos neste artigo, é possível observar que o fator em comum é a utilização da cifragem após a compressão. Partindo deste princípio, e considerando a possibilidade de um atacante injetar dados maliciosos antes mesmo dos processos de compressão e cifragem, a exploração de ataques do tipo Side-Channel da compressão se torna factível; por isso, mesmo considerando a presença cada vez maior da compressão de dados em aplicações de sistemas, sua utilização em conjunto com a cifragem não é a melhor opção.

.   .   .