* ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Descubre [**La Familia PEASS**](https://opensea.io/collection/the-peass-family), nuestra colección exclusiva de [**NFTs**](https://opensea.io/collection/the-peass-family)
* Obtén el [**merchandising oficial de PEASS y HackTricks**](https://peass.creator-spring.com)
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de Telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Comparte tus trucos de hacking enviando PRs al** [**repositorio de hacktricks**](https://github.com/carlospolop/hacktricks) **y al** [**repositorio de hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).
Encontré que el uso de `--break-on 'java.lang.String.indexOf'` hace que el exploit sea más **estable**. Y si tienes la oportunidad de cargar una puerta trasera en el host y ejecutarla en lugar de ejecutar un comando, el exploit será aún más estable.
Normalmente, este depurador se ejecuta en el puerto 8000 y si estableces una conexión TCP con el puerto y envías "**JDWP-Handshake**", el servidor debería responderte con la misma cadena.\
Al listar los **procesos**, si encuentras la cadena "**jdwk**" dentro de un **proceso de Java**, probablemente tenga activo el \*\*Protocolo de depuración con cable Java \*\*y es posible que puedas moverte lateralmente o incluso **elevar privilegios** (si se ejecuta como root).
**Arquitectura de depuración de la plataforma Java (JPDA)**: JDWP es un componente del sistema global de depuración de Java, llamado Arquitectura de Depuración de la Plataforma Java (JPDA)\[2]. A continuación se muestra un diagrama de la arquitectura general:
El Depurado consiste en una JVM de múltiples hilos que ejecuta nuestra aplicación objetivo. Para que sea posible depurar de forma remota, la instancia de JVM debe iniciarse explícitamente con la opción -Xdebug pasada en la línea de comandos, así como la opción -Xrunjdwp (o -agentlib). Por ejemplo, iniciar un servidor Tomcat con depuración remota habilitada se vería así:
Como se muestra en el diagrama de la arquitectura, el Protocolo de Depuración con Cable Java es el enlace central entre el Depurador y la instancia de JVM. Algunas observaciones sobre el protocolo incluyen:
* Es en su mayoría sincrónico. El depurador envía un comando a través de JDWP y espera recibir una respuesta. Sin embargo, algunos comandos, como los Eventos, no esperan una respuesta sincrónica. Enviarán una respuesta cuando se cumplan condiciones específicas. Por ejemplo, un Punto de Interrupción es un Evento.
Todas estas observaciones tienen total sentido ya que estamos hablando de un protocolo de depuración. Sin embargo, cuando un servicio de este tipo se expone a una red hostil o está expuesto a Internet, las cosas pueden salir mal.\
**Handshake**: JDWP dicta\[9] que la comunicación debe iniciarse con un simple handshake. Al establecer una conexión TCP exitosa, el Depurador (cliente) envía la cadena ASCII de 14 caracteres "JDWP-Handshake". El Depurado (servidor) responde a este mensaje enviando la misma cadena exacta. El siguiente rastreo de scapy\[3] muestra el handshake inicial de dos vías:
root:\~/tools/scapy-hg # ip addr show dev eth0 | grep “inet “ inet 192.168.2.2/24 brd 192.168.2.255 scope global eth0root:\~/tools/scapy-hg # ./run\_scapy
Welcome to Scapy (2.2.0-dev)\
**>>>** sniff(filter=”tcp port 8000 and host 192.168.2.9″, count=8)\
0007 15:49:30.407636 Ether / IP / TCP 192.168.2.2:59079 > 192.168.2.9:8000 A
Un auditor de seguridad experimentado puede haberse dado cuenta de que un handshake tan simple ofrece una forma fácil de descubrir servicios JDWP en vivo en Internet. Simplemente envía una sonda simple y verifica la respuesta específica. Más interesante aún, se observó un comportamiento en el Kit de Desarrollo Java de IBM al escanear con ShodanHQ\[4] con el servidor "hablando" primero con el mismo banner mencionado. Como consecuencia, existe una forma totalmente pasiva de descubrir un servicio JDWP activo (esto se aborda más adelante en este artículo con la ayuda del (in)famoso Shodan).\
\
**Comunicación**: JDWP define mensajes\[10] involucrados en las comunicaciones entre el Depurador y el Depurado. Los mensajes siguen una estructura simple, definida de la siguiente manera: 
Los campos Length e Id son bastante autoexplicativos. El campo Flag se utiliza únicamente para distinguir los paquetes de solicitud de las respuestas, un valor de 0x80 indica un paquete de respuesta. El campo CommandSet define la categoría del Comando, como se muestra en la siguiente tabla.\
| 0x40 | Acción que debe tomar la JVM (por ejemplo, establecer un Punto de Interrupción) |
| 0x40–0x7F | Proporcionar información de eventos al depurador (por ejemplo, la JVM ha alcanzado un Punto de Interrupción y está esperando más acciones) |
| 0x80 | Extensiones de terceros |
Teniendo en cuenta que queremos ejecutar código arbitrario, los siguientes comandos son los más interesantes para nuestros propósitos.
* VirtualMachine/IDSizes define el tamaño de las estructuras de datos manejadas por la JVM. Esta es una de las razones por las que el script de nmap jdwp-exec.nse\[11] no funciona, ya que el script utiliza tamaños codificados.
* ClassType/InvokeMethod te permite invocar una función estática.
* ObjectReference/InvokeMethod te permite invocar una función de un objeto instanciado en la JVM.
* StackFrame/(Get|Set)Values proporciona capacidades de empujar/sacar de la pila de hilos.
* Event/Composite obliga a la JVM a reaccionar a comportamientos específicos declarados por este comando. Este comando es clave para fines de depuración, ya que permite, entre muchas otras cosas, establecer puntos de interrupción, ejecutar pasos individuales a través de los hilos durante el tiempo de ejecución y recibir notificaciones al acceder/modificar valores de la misma manera que GDB o WinDBG.
No solo JDWP te permite acceder e invocar objetos que ya están en memoria, sino que también te permite crear o sobrescribir datos.
* VirtualMachine/CreateString te permite transformar una cadena en un java.lang.String que vive en el tiempo de ejecución de JVM.
* VirtualMachine/RedefineClasses te permite instalar nuevas definiciones de clases.
**"Todos tus JDWP nos pertenecen"**
Como hemos visto, JDWP proporciona comandos incorporados para cargar clases arbitrarias en la memoria de JVM e invocar bytecode ya existente y/o recién cargado. La siguiente sección cubrirá los pasos para crear código de explotación en Python, que se comporta como una implementación parcial de un front-end de JDI para ser lo más confiable posible. La razón principal de este script de explotación independiente es que, como pentester, me gustan las explotaciones "de un solo golpe". Es decir, cuando sé con certeza que un entorno/aplicación/protocolo es vulnerable, quiero tener mi herramienta lista para explotarlo de inmediato (es decir, sin PoC, que básicamente es lo único que existía hasta ahora). Ahora que hemos cubierto la teoría, vamos a la implementación práctica. Cuando nos enfrentamos a un servicio JDWP abierto, la ejecución de comandos arbitrarios está a solo cinco pasos de distancia (o con esta explotación, a solo una línea de comando de distancia). Así es como se desarrollaría: 1. Obtener referencia de tiempo de ejecución de JavaLa JVM manipula objetos a través de sus referencias. Por esta razón, nuestra explotación debe obtener primero la referencia a la clase java.lang.Runtime. De esta clase, necesitamos la referencia al método getRuntime(). Esto se realiza obteniendo todas las clases (paquete AllClasses) y todos los métodos en la clase que estamos buscando (paquete ReferenceType/Methods). 2. Configurar un punto de interrupción y esperar una notificación (llamadas asíncronas)Este es el punto clave de nuestra explotación. Para invocar código arbitrario, debemos estar en un contexto de hilo en ejecución. Para hacerlo, un truco es configurar un punto de interrupción en un método que se sabe que se llama en tiempo de ejecución. Como se vio anteriormente, un punto de interrupción en JDI es un evento asíncrono cuyo tipo se establece en BREAKPOINT(0x02). Cuando se alcanza, la JVM envía un paquete EventData a nuestro depurador, que contiene nuestro ID de punto de interrupción y, lo que es más importante, la referencia al hilo que lo alcanzó.\
Por lo tanto, es una buena idea configurarlo en un método que se llama con frecuencia, como java.net.ServerSocket.accept(), que es muy probable que se llame cada vez que el servidor recibe una nueva conexión de red. Sin embargo, hay que tener en cuenta que podría ser cualquier método existente en tiempo de ejecución. 3. Asignar un objeto Java String en tiempo de ejecución para llevar a cabo la carga útilEjecutaremos código en tiempo de ejecución de JVM, por lo que todos nuestros datos manipulados (como cadenas) deben existir en tiempo de ejecución de JVM (es decir, poseer una referencia de tiempo de ejecución). Esto se hace bastante fácilmente enviando un comando CreateString.
4\. Obtener objeto Runtime desde el contexto del punto de interrupciónEn este punto, casi tenemos todos los elementos que necesitamos para una explotación exitosa y confiable. Lo que nos falta es una referencia de objeto Runtime. Obtenerlo es fácil, y simplemente podemos ejecutar en tiempo de ejecución de JVM el método estático java.lang.Runtime.getRuntime()\[8] enviando un paquete ClassType/InvokeMethod y proporcionando las referencias de la clase Runtime y el hilo. 5. Buscar e invocar el método exec() en la instancia de RuntimeEl último paso es simplemente buscar el método exec() en el objeto estático Runtime obtenido en el paso anterior e invocarlo (enviando un paquete ObjectReference/InvokeMethod) con el objeto String que creamos en el paso tres. 
El exploit final utiliza esas técnicas, agrega algunas comprobaciones y envía señales de suspensión/reanudación para causar la menor interrupción posible (siempre es mejor no romper la aplicación en la que estás trabajando, ¿verdad?). Actúa en dos modos:
* El modo "Predeterminado" es totalmente no intrusivo y simplemente ejecuta código Java para obtener información del sistema local (perfecto para una prueba de concepto para un cliente).
* Pasar la opción "cmd" ejecuta un comando del sistema en el host remoto y, por lo tanto, es más intrusivo. El comando se ejecuta con los privilegios con los que se está ejecutando la JVM.
Como Java es independiente de la plataforma por diseño, los comandos se pueden ejecutar en cualquier sistema operativo compatible con Java. Bueno, esto en realidad es una buena noticia para nosotros, los pentesters: **un servicio JDWP abierto significa una RCE confiable**. Hasta ahora, todo bien.
De hecho, JDWP se utiliza bastante en el mundo de las aplicaciones Java. Sin embargo, los pentesters pueden no verlo con tanta frecuencia al realizar evaluaciones remotas, ya que los firewalls bloquearían (y deberían bloquear) principalmente el puerto en el que se está ejecutando. Pero esto no significa que no se pueda encontrar JDWP en la naturaleza:
* Al realizar un escaneo masivo en Internet en busca de puertos específicos (tcp/8000, tcp/8080, tcp/8787, tcp/5005), se encontraron muchos hosts (que no se pueden informar aquí) que responden al saludo inicial.
* Se encontraron aplicaciones "empresariales" en la naturaleza que ejecutan un servicio JDWP \*de forma predeterminada\* (encontrar el número de puerto real queda como ejercicio para el lector curioso).
Estas son solo algunas formas de descubrir servicios JDWP abiertos en Internet. Esto es un gran recordatorio de que las aplicaciones deben someterse regularmente a revisiones de seguridad exhaustivas, los entornos de producción deben desactivar cualquier funcionalidad de depuración y los firewalls deben configurarse para restringir el acceso a los servicios necesarios solo para el funcionamiento normal. Permitir que cualquier persona se conecte a un servicio JDWP es exactamente lo mismo que permitir una conexión a un servicio gdbserver (de una manera posiblemente más estable). Espero que hayas disfrutado leyendo este artículo tanto como yo disfruté jugando con JDWP. ¡A todos los poderosos piratas, felices JDWP pwning!
* ¿Trabajas en una **empresa de ciberseguridad**? ¿Quieres ver tu **empresa anunciada en HackTricks**? ¿O quieres tener acceso a la **última versión de PEASS o descargar HackTricks en PDF**? ¡Consulta los [**PLANES DE SUSCRIPCIÓN**](https://github.com/sponsors/carlospolop)!
* Descubre [**The PEASS Family**](https://opensea.io/collection/the-peass-family), nuestra colección de [**NFTs**](https://opensea.io/collection/the-peass-family) exclusivos.
* Obtén el [**swag oficial de PEASS y HackTricks**](https://peass.creator-spring.com).
* **Únete al** [**💬**](https://emojipedia.org/speech-balloon/) [**grupo de Discord**](https://discord.gg/hRep4RUj7f) o al [**grupo de Telegram**](https://t.me/peass) o **sígueme** en **Twitter** [**🐦**](https://github.com/carlospolop/hacktricks/tree/7af18b62b3bdc423e11444677a6a73d4043511e9/\[https:/emojipedia.org/bird/README.md)[**@carlospolopm**](https://twitter.com/hacktricks\_live)**.**
* **Comparte tus trucos de hacking enviando PR al** [**repositorio de hacktricks**](https://github.com/carlospolop/hacktricks) **y al** [**repositorio de hacktricks-cloud**](https://github.com/carlospolop/hacktricks-cloud).