PortForwarining y pivoting
Última actualización
Última actualización
La mayoría de las técnicas de movimiento lateral que hemos presentado requieren que haya puertos específicos disponibles para un atacante. En las redes del mundo real, es posible que los administradores hayan bloqueado algunos de estos puertos por razones de seguridad o hayan implementado una segmentación alrededor de la red, impidiéndole llegar a los puertos SMB , RDP, WinRM o RPC.
Para sortear estas restricciones, podemos utilizar técnicas de reenvío de puertos, que consisten en utilizar cualquier host comprometido como un jumpbox para pasar a otros hosts. Se espera que algunas máquinas tengan más permisos de red que otras, ya que cada rol en una empresa tendrá diferentes necesidades en términos de qué servicios de red se requieren para el trabajo diario.
El primer protocolo que veremos es SSH , ya que ya tiene una funcionalidad incorporada para realizar el reenvío de puertos a través de una función llamada SSH Tunneling . Si bien SSH solía ser un protocolo asociado con los sistemas Linux, Windows ahora viene con el cliente OpenSSH de forma predeterminada, por lo que puede esperar encontrarlo en muchos sistemas hoy en día, independientemente de su sistema operativo.
El túnel SSH se puede utilizar de diferentes maneras para reenviar puertos a través de una conexión SSH, que usaremos según la situación. Para explicar cada caso, supongamos un escenario en el que hemos obtenido control sobre la máquina PC-1 (no necesita tener acceso de administrador) y nos gustaría usarla como pivote para acceder a un puerto en otra máquina a la que No podemos conectarnos directamente. Iniciaremos un túnel desde la máquina PC-1, que actúa como cliente SSH, hasta la PC del atacante, que actuará como servidor SSH. La razón para hacerlo es que a menudo encontrará un cliente SSH en máquinas con Windows, pero la mayor parte del tiempo no habrá ningún servidor SSH disponible.
Dado que vamos a establecer una conexión con la máquina de nuestro atacante, queremos crear un usuario en ella sin acceso a ninguna consola para hacer túneles y establecer una contraseña para usar en la creación de túneles:
Dependiendo de sus necesidades, el túnel SSH se puede utilizar para realizar el reenvío de puertos local o remoto. Echemos un vistazo a cada caso.
En nuestro ejemplo, supongamos que las políticas de firewall impiden que la máquina del atacante acceda directamente al puerto 3389 en el servidor. Si el atacante ha comprometido previamente la PC-1 y, a su vez, la PC-1 tiene acceso al puerto 3389 del servidor, se puede utilizar para pasar al puerto 3389 mediante el reenvío de puerto remoto desde la PC-1. El reenvío de puerto remoto le permite tomar un puerto accesible desde el cliente SSH (en este caso, PC-1) y proyectarlo en un servidor SSH remoto (la máquina del atacante).
Como resultado, se abrirá un puerto en la máquina del atacante que puede usarse para conectarse nuevamente al puerto 3389 en el servidor a través del túnel SSH . La PC-1, a su vez, representará la conexión para que el servidor vea todo el tráfico como si viniera de la PC-1:
Una pregunta válida que podría surgir en este punto es por qué necesitamos el reenvío de puertos si hemos comprometido la PC-1 y podemos ejecutar una sesión RDP directamente desde allí. La respuesta es simple: en una situación en la que solo tenemos acceso de consola a la PC-1, no podremos usar ningún cliente RDP porque no tenemos una GUI. Al hacer que el puerto esté disponible para la máquina de su atacante, puede usar un cliente RDP de Linux para conectarse. Surgen situaciones similares cuando desea ejecutar un exploit en un puerto al que no se puede acceder directamente, ya que su exploit puede requerir un lenguaje de secuencias de comandos específico que no siempre está disponible en las máquinas que compromete en el camino.
Refiriéndose a la imagen anterior, para reenviar el puerto 3389 en el servidor a la máquina de nuestro atacante, podemos usar el siguiente comando en la PC-1:
PC1: símbolo del sistema
Esto establecerá una sesión SSH1.1.1.1
desde la PC-1 a (PC atacante) utilizando el tunneluser
usuario.
Dado que tunneluser
no se permite ejecutar un shell en la PC atacante, debemos ejecutar el ssh
comando con el-N
cambie para evitar que el cliente solicite uno, o la conexión se cerrará inmediatamente. El-R
El conmutador se utiliza para solicitar un reenvío de puerto remoto, y la sintaxis requiere que primero indiquemos el puerto que abriremos en el servidor SSH (3389), seguido de dos puntos y luego la IP y el puerto del socket que reenviaremos. (3.3.3.3:3389). Observe que no es necesario que los números de puerto coincidan, aunque sí lo hacen en este ejemplo.
El comando en sí no generará nada, pero el túnel dependerá del comando que se esté ejecutando. Cuando queramos podemos cerrar el túnel pulsando CTRL+C como con cualquier otro comando.
Una vez que nuestro túnel esté configurado y en ejecución, podemos ir a la máquina del atacante y RDP al puerto reenviado para llegar al servidor:
La máquina del atacante
El reenvío de puerto local nos permite "extraer" un puerto de un servidor SSH al cliente SSH. En nuestro escenario, esto podría usarse para tomar cualquier servicio disponible en la máquina de nuestro atacante y hacerlo disponible a través de un puerto en la PC-1. De esa manera, cualquier host que no pueda conectarse directamente a la PC del atacante pero que pueda conectarse a la PC-1 ahora podrá acceder a los servicios del atacante a través del host pivote.
El uso de este tipo de reenvío de puertos nos permitiría ejecutar shells inversos desde hosts que normalmente no podrían conectarse con nosotros o simplemente hacer que cualquier servicio que queramos esté disponible para máquinas que no tienen conexión directa con nosotros.
Para reenviar el puerto 80 desde la máquina del atacante y hacerlo disponible desde la PC-1, podemos ejecutar el siguiente comando en la PC-1:
PC1: símbolo del sistema
La estructura del comando es similar a la que se usa en el reenvío de puertos remotos, pero usa la -L
opción para el reenvío de puertos locales. Esta opción requiere que indiquemos el socket local utilizado por el PC-1 para recibir conexiones ( *:80
) y el socket remoto al que conectarse desde la perspectiva del PC del atacante ( 127.0.0.1:80
).
Observe que usamos la dirección IP 127.0.0.1 en el segundo socket, ya que desde la perspectiva de la PC del atacante, ese es el host que contiene el puerto 80 que se reenviará.
Dado que estamos abriendo un nuevo puerto en la PC-1, es posible que necesitemos agregar una regla de firewall para permitir conexiones entrantes (con dir=in
). Se necesitan privilegios administrativos para esto:
Una vez configurado el túnel, cualquier usuario que dirija su navegador a la PC-1 http://2.2.2.2:80
verá el sitio web publicado por la máquina del atacante.
En situaciones en las que SSH no está disponible, se puede utilizar socat para realizar una funcionalidad similar. Si bien no es tan flexible como SSH, socat le permite reenviar puertos de una manera mucho más sencilla. Una de las desventajas de usar socat es que necesitamos transferirlo al host pivot (PC-1 en nuestro ejemplo actual), lo que lo hace más detectable que SSH, pero podría valer la pena intentarlo cuando no haya otra opción disponible.
La sintaxis básica para realizar el reenvío de puertos utilizando socat es mucho más sencilla. Si quisiéramos abrir el puerto 1234 en un host y reenviar cualquier conexión que recibamos allí al puerto 4321 en el host 1.1.1.1, tendríamos el siguiente comando:
Elfork
La opción permite a socat bifurcar un nuevo proceso para cada conexión recibida, lo que permite manejar múltiples conexiones sin cerrar. Si no lo incluyes, socat se cerrará cuando finalice la primera conexión realizada.
Volviendo a nuestro ejemplo, si quisiéramos acceder al puerto 3389 en el servidor usando la PC-1 como pivote como lo hicimos con el reenvío de puerto remoto SSH , podríamos usar el siguiente comando:
Tenga en cuenta que socat no puede reenviar la conexión directamente a la máquina del atacante como lo hizo SSH , pero abrirá un puerto en la PC-1 al que la máquina del atacante podrá conectarse:
Como es habitual, dado que se abre un puerto en el host pivote, es posible que necesitemos crear una regla de firewall para permitir cualquier conexión a ese puerto:
Si, por el contrario, queremos exponer el puerto 80 de la máquina del atacante para que sea accesible para el servidor, sólo necesitamos ajustar un poco el comando:
Como resultado, la PC-1 generará el puerto 80 y escuchará las conexiones que se reenviarán al puerto 80 en la máquina del atacante:
Si bien el reenvío de un solo puerto funciona bastante bien para tareas que requieren acceso a sockets específicos, hay ocasiones en las que es posible que necesitemos ejecutar escaneos en muchos puertos de un host, o incluso en muchos puertos en muchas máquinas, todo a través de un host pivote. En esos casos, el reenvío dinámico de puertos nos permite pasar a través de un host y establecer varias conexiones a cualquier dirección IP/puerto que queramos mediante el uso de un proxy SOCKS .
Como no queremos depender de un servidor SSH existente en las máquinas Windows de nuestra red de destino, normalmente usaremos el cliente SSH para establecer un reenvío de puerto dinámico inverso con el siguiente comando:
En este caso, el servidor SSH iniciará un proxy SOCKS en el puerto 9050
y reenviará cualquier solicitud de conexión a través del túnel SSH , donde finalmente el cliente SSH la representará.
La parte más interesante es que podemos utilizar fácilmente cualquiera de nuestras herramientas a través del proxy SOCKS mediante el uso de proxychains . Para hacerlo, primero debemos asegurarnos de que proxychains esté configurado correctamente para apuntar cualquier conexión al mismo puerto utilizado por SSH para el servidor proxy SOCKS. El archivo de configuración de proxychains se puede encontrar en /etc/proxychains.conf
su AttackBox. Si nos desplazamos hacia abajo hasta el final del archivo de configuración, deberíamos ver una línea que indica el puerto en uso para el proxy de calcetines:
El puerto predeterminado es 9050, pero cualquier puerto funcionará siempre que coincida con el que utilizamos al establecer el túnel SSH .
Si ahora queremos ejecutar cualquier comando a través del proxy, podemos usar proxychains:
Tenga en cuenta que es posible que algunos programas como nmap no funcionen bien con SOCKS en algunas circunstancias y que muestren resultados alterados, por lo que su kilometraje puede variar.
El servidor THMDC ejecuta una versión vulnerable de Rejetto HFS. El problema al que nos enfrentamos es que las reglas del firewall restringen el acceso al puerto vulnerable para que sólo pueda verse desde THMJMP2. Además, las conexiones salientes desde THMDC solo están permitidas en máquinas en su red local, lo que hace imposible recibir un shell inverso directamente en la máquina de nuestro atacante. Para empeorar las cosas, el exploit Rejetto HFS requiere que el atacante aloje un servidor HTTP para activar la carga útil final, pero como no se permiten conexiones salientes a la máquina del atacante, necesitaríamos encontrar una manera de alojar un servidor web en uno de las otras máquinas en la misma red, lo cual no es nada conveniente. Podemos utilizar el reenvío de puertos para superar todos estos problemas.
Primero, echemos un vistazo a cómo funciona el exploit. Primero, se conectará al puerto HFS ( RPORT
en Metasploit ) para activar una segunda conexión. Esta segunda conexión se realizará contra la máquina del atacante enSRVPORT
, donde un servidor web entregará la carga útil final. Finalmente, la carga útil del atacante se ejecutará y enviará de vuelta un shell inverso al atacante en LPORT
:
Con esto en mente, podríamos usar SSH para reenviar algunos puertos desde la máquina del atacante a THMJMP2 (SRVPORT para el servidor web y LPORT para recibir el shell inverso) y pasar por THMJMP2 para llegar a RPORT en THMDC. Tendríamos que hacer tres reenvíos de puertos en ambas direcciones para que todas las interacciones del exploit puedan enviarse mediante proxy a través de THMJMP2:
Rejetto HFS escuchará en el puerto 80 de THMDC, por lo que necesitamos hacer un túnel de ese puerto de regreso a la máquina de nuestro atacante a través de THMJMP2 usando el reenvío de puerto remoto. Dado que Attackbox tiene el puerto 80 ocupado con otro servicio, necesitaremos vincular el puerto 80 en THMDC con algún puerto que Attackbox no esté utilizando actualmente. Usemos el puerto 8888. Al ejecutar ssh en THMJMP2 para reenviar este puerto, tendríamos que agregarlo -R 8888:thmdc.za.tryhackme.com:80
a nuestro comando.
Para SRVPORT y LPORT, elijamos dos puertos aleatorios a voluntad. Para fines demostrativos, configuraremos SRVPORT=6666
y LPORT=7878
, pero asegúrese de usar puertos diferentes ya que el laboratorio se comparte con otros estudiantes, por lo que si dos de ustedes eligen los mismos puertos, cuando intenten reenviarlos, obtendrán un error que indica que dicho puerto ya está en uso en THMJMP2.
Para reenviar dichos puertos desde nuestra máquina atacante a THMJMP2, usaremos el reenvío de puertos local agregando -L *:6666:127.0.0.1:6666
y -L *:7878:127.0.0.1:7878
a nuestro comando ssh. Esto unirá ambos puertos en THMJMP2 y canalizará cualquier conexión de regreso a nuestra máquina atacante.
Juntando todo el comando, terminaríamos con lo siguiente:
THMJMP2: símbolo del sistema
Nota: Si está utilizando AttackBox y se ha unido a otras salas de red antes, asegúrese de seleccionar la dirección IP asignada a la interfaz del túnel frente a la lateralmovementandpivoting
red como su ATTACKER_IP, de lo contrario sus shells/conexiones inversas no funcionarán correctamente. Para su comodidad, la interfaz conectada a esta red se llama lateralmovement
, por lo que debería poder obtener la dirección IP correcta ejecutando ip add show lateralmovement
:
Una vez que todos los puertos reenviados estén en su lugar, podemos iniciar Metasploit y configurar el exploit para que los puertos requeridos coincidan con los que hemos reenviado a través de THMJMP2:
Hay mucho que desempacar aquí:
El parámetro LHOST generalmente tiene dos propósitos: se usa como la IP donde un oyente está vinculado en la máquina del atacante para recibir un shell inverso; también está integrado en la carga útil para que la víctima sepa dónde conectarse cuando se activa el exploit. En nuestro escenario específico, dado que THMDC no podrá comunicarse con nosotros, debemos forzar que la carga útil se vuelva a conectar a THMJMP2, pero necesitamos que el oyente se vincule a la máquina del atacante en 127.0.0.1
. Para este fin, Metasploit proporciona un parámetro opcionalReverseListenerBindAddress
, que se puede utilizar para especificar la dirección de enlace del oyente en la máquina del atacante por separado de la dirección donde se conectará la carga útil. En nuestro ejemplo, queremos que el detector de shell inverso esté vinculado a 127.0.0.1 en la máquina del atacante y que la carga útil se conecte nuevamente a THMJMP2 (ya que se reenviará a la máquina del atacante a través del túnel SSH ) .
Nuestro exploit también debe ejecutar un servidor web para alojar y enviar la carga útil final al servidor víctima. Usamos SRVHOST para indicar la dirección de escucha, que en este caso es 127.0.0.1, para que la máquina atacante vincule el servidor web al localhost. Si bien esto puede ser contradictorio, ya que ningún host externo podría apuntar al host local de la máquina del atacante, el túnel SSH se encargará de reenviar cualquier conexión recibida en THMJMP2 en SRVPORT a la máquina del atacante.
El RHOSTS está configurado para apuntar a 127.0.0.1 ya que el túnel SSH reenviará las solicitudes a THMDC a través del túnel SSH establecido con THMJMP2. RPORT está configurado en 8888, ya que cualquier conexión enviada a ese puerto en la máquina atacante se reenviará al puerto 80 en THMDC.
Después de ejecutar el exploit, recibirás un shell en la máquina del atacante. Encontrarás una bandera en C:\hfs\flag.txt
.