Vulnerabilidade LOG4J
Um projeto baseado em Java que apresenta como explorar a vulnerabilidade CVE-2021-44228.
https://user-images.githubusercontent.com/13152452/147803050-458593e9-4b54-4e1f-ba07-802866b9b43e.mp4
Requisitos
- Um sistema operacional baseado em Linux: usei Ubuntu Desktop 20.10 64 bits
- OpenJDK 17.0.1: Para construir o programa de exploração. Versões mais recentes também podem funcionar.
- Oracle Java Development Kit (JDK) 1.8.0_181: Isso é essencial para que a exploração funcione. Não é necessário tê-lo instalado, mas o projeto precisa dele extraído no diretório raiz. O JDK pode ser encontrado na página de Downloads de Arquivos do Oracle Java SE 8 (JDK 8u202 e anteriores).
- Apache Maven 3.6.3: Para gerenciar dependências e gerar arquivos jar. Versões posteriores também podem funcionar.
- Docker 20.10.12: Para gerenciar o contêiner que contém o serviço a ser explorado. Versões posteriores também podem funcionar.
- Docker-compose 1.29.2: Para ajudar a orquestrar a geração da imagem, bem como a criação, execução e remoção do contêiner. Versões posteriores também podem funcionar.
- GNU Make 4.3: Este projeto usa Makefile para ajudar a verificar e gerar arquivos obrigatórios. Versões posteriores também podem funcionar.
- OpenBSD Netcat (também conhecido como nc): Para criar a comunicação com o servidor invadido. Este pacote pode ser instalado através do gerenciador de pacotes da sua distribuição Linux (como apt).
- (Recomendado) IntelliJ IDEA Community Edition 2021.3.1: Se você quiser verificar o que está por baixo dos panos desses projetos, então recomendo instalar esta IDE. Mais uma vez, versões posteriores também podem funcionar.
Execução
- Clone este repositório para sua máquina local.
- Baixe o Oracle Java SE 8 Archive Downloads (JDK 8u202 and earlier) page e extraia-o no diretório raiz do projeto. Mantenha-o dentro do diretório
jdk1.8.0_181 criado durante a extração.
- Execute
make all para construir todos os projetos e criar uma imagem Docker com o serviço vulnerável.
- Abra três terminais e execute os seguintes comandos:
- Primeiro terminal:
make start-vulnerable-service para iniciar um contêiner Docker executando o serviço a ser explorado. O serviço estará acessível através da porta 8080 da máquina local
- Segundo terminal:
make start-nc para iniciar um listener TCP que aguardará a conexão com o servidor invadido ser estabelecida.
- Terceiro terminal:
make start-exploiter para iniciar o programa que nos ajudará a explorar a vulnerabilidade.
- Após iniciar o terceiro terminal, o programa explorador apresentará uma URL para acessar. Cole-a no seu navegador para iniciar a exploração.
- Se tudo ocorrer como esperado, o navegador não receberá uma resposta e ficará travado em um status de carregamento.
- Agora verifique o segundo terminal (aquele onde
make start-nc foi executado). Você pode ter recebido uma mensagem como Connection received on 172.24.0.2 46638 (o endereço IP e a porta TCP podem não ser os mesmos apresentados aqui). Isso significa que a exploração funcionou e agora temos um shell conectado ao servidor/contêiner Docker.
- Para ter certeza se tudo ocorreu como esperado, tente executar um comando
whoami. Você pode receber root como saída.
- Agora tente executar
cat ../private-directory/my-secret-file.txt para ver o que acontece. 🙂
- Assim que terminar de bagunçar o servidor, pressione
CTRL+C para fechar a conexão.
- Você também pode pressionar
CTRL+C nos outros terminais para interromper os processos.
Como funciona?
Antes de responder a isso, vamos dar uma olhada nos processos criados ao longo do fluxo.

Contêiner Docker
Este contêiner Docker servirá um serviço HTTP simples responsável por receber requisições GET no caminho /log com um parâmetro input. Uma vez recebido, ele registra a entrada no console.
https://user-images.githubusercontent.com/13152452/147826880-8ee10391-bcb7-46d3-8d69-2f7ddb4a7b37.mp4
Para explorar a vulnerabilidade, algumas configurações específicas são necessárias:
- A versão do ambiente de execução Java (JRE) usada para executar o serviço é
1.8.0_181. Isso é necessário para permitir que uma classe Java seja carregada de um serviço externo.
- As dependências do projeto Java precisam ser fortemente modificadas para substituir o padrão
spring-boot-starter-logging:2.6.1 por spring-boot-starter-log4j2:2.6.1. Este último traz log4j-core:2.14.1 para o projeto, que é uma versão vulnerável ao CVE-2021-44228.

- O arquivo Jar do serviço foi criado com o compilador Java versão
1.8.0_181.
Programa Netcat (nc)
Não há explicações ou ajustes importantes aqui. Este é um programa simples usado para ler e escrever dados através dos protocolos TCP e UDP. Nós o usaremos para manter a escuta de conexões TCP de entrada na porta 9001 (algo mais abrirá essa conexão para nós no lado do servidor. 😉).
Uma vez que a conexão é estabelecida, todos os dados recebidos serão exibidos no console. Além disso, toda entrada escrita será enviada através desta conexão.
Explorador
Agora é onde a diversão começa!
Este programa encapsula várias etapas necessárias para explorar a vulnerabilidade. Vamos detalhar:
Argumentos de execução
Para executar este programa, precisamos informar três parâmetros:
- Endereço IP/nome do host do servidor HTTP e do Netcat: Para explorar a vulnerabilidade, precisaremos do endereço IP do servidor HTTP relativo ao serviço vulnerável para que nossa resposta LDAP possa redirecioná-lo para baixar a classe Java compilada através dele. Também será usado pela própria classe Java para abrir uma conexão TCP com o Netcat (explicado acima).
- Porta do servidor HTTP: A porta onde o servidor HTTP responsável por enviar a classe Java compilada aceitará conexões. Também será enviada com a resposta LDAP para informar a porta de onde a classe Java compilada será baixada.
- Porta do Netcat: A porta onde o Netcat está escutando por conexões. Será usada pela classe Java compilada para abrir uma conexão TCP com o Netcat.
Classe Java de exploração
Assim que o programa iniciar, ele escreverá um código Java baseado em um template. Este template requer dois argumentos: O endereço IP e a porta do Netcat.
Uma vez escrito o código, o programa o compilará em um arquivo de classe binário usando o compilador Java (javac) versão 1.8.0_181. Isso é importante para manter a mesma versão de código do serviço explorado.