SSH tiene un montón de opciones (os recomiendo echar un vistazo a su página de man) y una de las más interesantes es que un cliente SSH también permite "tunelizar" un puerto o una conexión entre el sistema local del atacante y el servidor SSH remoto. Hay tres tipos diferentes de túneles SSH: reenvío de puertos local, remoto o dinámico.
Local port forwarding
El "reenvío de puertos local permite acceder a los recursos de la red local que no están expuestos desde el exterior (ya sea Internet, otra red externa o incluso para el acceso a servicios que están restringidos y accesibles solo desde el host local).
Por ejemplo, imaginad que queremos acceder al servicio RDP del servidor de la víctima. Para ello levantaremos un puerto local en la máquina del atacante que tunelizará directamente con el del servidor:
ssh -L local_port:remote_address:remote_port username@server.com
ssh -L 3389:192.168.2.3:3389 user@192.168.2.3
De esta manera, podremos establecer una sesión de escritorio remoto simplemente lanzando nuestro cliente así:
rdesktop 127.0.0.1
Aunque bueno... si estamos hablando de RDP se trata de Windows y sería bastante "exótico" que corriera un servidor SSH... así que si hemos comprometido previamente el servidor mediante cualquier otra vulnerabilidad podemos subir el binario plink.exe (la versión de consola de putty) y ejecutar:
plink.exe -i clave.ppk -L *:3389:localhost:3389 user@192.168.2.3
Otras opciones interesantes a tener en cuenta son:
-g : permite que otros clientes de la LAN puedan conectarse al puerto de la máquina del atacante. Por defecto, solo se permite en local.
-f : pone en background el proceso una vez que se haya establecido con éxito la sesión SSH. Muy util para que el puerto permanezca activo aún cuando se cierre la sesión interactiva.
Dynamic port forwarding
El "reenvío de puertos dinámico" funciona de manera similar a un proxy, de hecho, el cliente SSH creará un proxy SOCKS que se puede configurar en las aplicaciones para usarse. Es similar al reenvío local, pero
en lugar de a un sólo puerto, TODO el tráfico enviado a través del proxy será enviado a su vez a través del servidor SSH.
Para usar el reenvío dinámico tendremos que usar el argumento -D:
ssh -D local_port username@server.com
ssh -D 127.0.0.1:9050 root@192.168.2.2
A partir de ese momento tendremos escuchando en la máquina del atacante un proxy SOCKS en el puerto 9050 y podemos usar cualquier programa (un navegador por ejemplo) para que lo utilice. Sin embargo, si el programa no soporta configurar proxy podremos aún forzarlo mediante proxychains. Para ello bastará configurar el fichero /etc/proxychains.conf añadiendo la línea: "socks4 127.0.0.1 9050" y luego poniendo delante "proxychains" cuando usemos la herramienta que necesitemos:
proxychains rdesktop 192.168.2.3
Remote port forwarding
El "reenvío de puertos remoto" también llamado reverso o inverso, es lo contrario al local. Es decir, se utiliza para hacer accesible un puerto del servidor del atacante desde el servidor comprometido.
Veamos también su sintaxis y uso:
ssh -R remote_port:local_address:local_port username@server.com
ssh -R 8888:192.168.2.33:1234 bob@ssh.youroffice.com
Con el comando anterior, cuando alguien acceda al puerto 8888 del servidor remoto estará siendo redirigido realmente al puerto 1234 de la máquina del atacante.
Sin embargo, para que esto funcione tendremos que añadir la línea "GatewayPorts yes" en el fichero de configuración /etc/ssh/sshd_config.
Bonus: VPN sobre SSH
Desde la versión 4.3 de openssh, es posible tunelizar el tráfico de red de la capa 3 a través de un canal ssh establecido. Esto tiene una ventaja sobre un túnel típico de tcp porque tenemos el control del tráfico IP. De esta manera por ejemplo podemos realizar un SYN-scan con nmap y usar sus herramientas directamente sin recurrir a proxychains u otras herramientas de proxificación.
Esta VPN se realiza a través de la creación de dispositivos tun en el lado del cliente y del servidor y la transferencia de datos entre ellos a través de la conexión ssh. Esto es bastante simple, pero se necesita root en ambas máquinas ya que la creación de dispositivos tun es una operación privilegiada.
Estas líneas deben estar presentes en su archivo /etc/ssh/sshd_config (en el lado del servidor):
PermitRootLogin yes
PermitTunnel yes
El siguiente comando en el cliente creará un par de dispositivos tun en el cliente y el servidor:
ssh username@server -w any:any
Con el parámetro -w establecemos el túnel entre los dispositivos especificados. Si ponemos "any" como en el ejemplo el sistema cogerá el primer interfaz tun disponible.
Un vez creado el túnel procederemos a configurar los interfaces tun.
En el cliente:
ip addr add 1.1.1.2/32 peer 1.1.1.1 dev tun0
En el servidor:
ip addr add 1.1.1.1/32 peer 1.1.1.2 dev tun0
Y tendremos que configurar el reenvío IP y el NAT en el servidor:
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -s 1.1.1.2 -o eth0 -j MASQUERADE
Ahora podemos hacer que el peer 1.1.1.1 sea la puerta de enlace predeterminada o enrutar un host o una red específicas a través de él:
route add -net 10.0.0.0/16 gw 1.1.1.1
En el ejemplo, la interfaz de red externa del servidor es eth0 y los dispositivos tun creados recientemente en ambos lados son tun0.
Truco del día
Seguramente os habréis dado cuenta que cada vez que creamos un túnel con SSH también obtenemos una shell. Esto no suele ser necesario cuando solo intentamos crear un túnel. Para evitar esto, podemos ejecutar SSH con los parámetros -nNT, como el siguiente ejemplo, lo que hará que SSH no asigne un tty y solo reenvíe los puertos.
$ ssh -nNT -L 9000: imgur.com: 80 user@example.com
-N : esta opción es la que indica que no se abra la shell, solo reenvío de puertos.
-n : se utiliza cuando ssh se ejecuta en background y previene que se lea de stdin.
-t : desactiva pseudo-tty
Fuentes:
- A Red Teamer's guide to pivoting
- SSH Tunnel - Local and Remote Port Forwarding Explained With Examples
- The Black Magic Of SSH / SSH Can Do That?
- How to Use SSH Tunneling to Access Restricted Servers and Browse Securely
Local port forwarding
El "reenvío de puertos local permite acceder a los recursos de la red local que no están expuestos desde el exterior (ya sea Internet, otra red externa o incluso para el acceso a servicios que están restringidos y accesibles solo desde el host local).
Por ejemplo, imaginad que queremos acceder al servicio RDP del servidor de la víctima. Para ello levantaremos un puerto local en la máquina del atacante que tunelizará directamente con el del servidor:
ssh -L local_port:remote_address:remote_port username@server.com
ssh -L 3389:192.168.2.3:3389 user@192.168.2.3
De esta manera, podremos establecer una sesión de escritorio remoto simplemente lanzando nuestro cliente así:
rdesktop 127.0.0.1
Aunque bueno... si estamos hablando de RDP se trata de Windows y sería bastante "exótico" que corriera un servidor SSH... así que si hemos comprometido previamente el servidor mediante cualquier otra vulnerabilidad podemos subir el binario plink.exe (la versión de consola de putty) y ejecutar:
plink.exe -i clave.ppk -L *:3389:localhost:3389 user@192.168.2.3
Otras opciones interesantes a tener en cuenta son:
-g : permite que otros clientes de la LAN puedan conectarse al puerto de la máquina del atacante. Por defecto, solo se permite en local.
-f : pone en background el proceso una vez que se haya establecido con éxito la sesión SSH. Muy util para que el puerto permanezca activo aún cuando se cierre la sesión interactiva.
Dynamic port forwarding
El "reenvío de puertos dinámico" funciona de manera similar a un proxy, de hecho, el cliente SSH creará un proxy SOCKS que se puede configurar en las aplicaciones para usarse. Es similar al reenvío local, pero
en lugar de a un sólo puerto, TODO el tráfico enviado a través del proxy será enviado a su vez a través del servidor SSH.
Para usar el reenvío dinámico tendremos que usar el argumento -D:
ssh -D local_port username@server.com
ssh -D 127.0.0.1:9050 root@192.168.2.2
A partir de ese momento tendremos escuchando en la máquina del atacante un proxy SOCKS en el puerto 9050 y podemos usar cualquier programa (un navegador por ejemplo) para que lo utilice. Sin embargo, si el programa no soporta configurar proxy podremos aún forzarlo mediante proxychains. Para ello bastará configurar el fichero /etc/proxychains.conf añadiendo la línea: "socks4 127.0.0.1 9050" y luego poniendo delante "proxychains" cuando usemos la herramienta que necesitemos:
proxychains rdesktop 192.168.2.3
Remote port forwarding
El "reenvío de puertos remoto" también llamado reverso o inverso, es lo contrario al local. Es decir, se utiliza para hacer accesible un puerto del servidor del atacante desde el servidor comprometido.
Veamos también su sintaxis y uso:
ssh -R remote_port:local_address:local_port username@server.com
ssh -R 8888:192.168.2.33:1234 bob@ssh.youroffice.com
Con el comando anterior, cuando alguien acceda al puerto 8888 del servidor remoto estará siendo redirigido realmente al puerto 1234 de la máquina del atacante.
Sin embargo, para que esto funcione tendremos que añadir la línea "GatewayPorts yes" en el fichero de configuración /etc/ssh/sshd_config.
Bonus: VPN sobre SSH
Desde la versión 4.3 de openssh, es posible tunelizar el tráfico de red de la capa 3 a través de un canal ssh establecido. Esto tiene una ventaja sobre un túnel típico de tcp porque tenemos el control del tráfico IP. De esta manera por ejemplo podemos realizar un SYN-scan con nmap y usar sus herramientas directamente sin recurrir a proxychains u otras herramientas de proxificación.
Esta VPN se realiza a través de la creación de dispositivos tun en el lado del cliente y del servidor y la transferencia de datos entre ellos a través de la conexión ssh. Esto es bastante simple, pero se necesita root en ambas máquinas ya que la creación de dispositivos tun es una operación privilegiada.
Estas líneas deben estar presentes en su archivo /etc/ssh/sshd_config (en el lado del servidor):
PermitRootLogin yes
PermitTunnel yes
El siguiente comando en el cliente creará un par de dispositivos tun en el cliente y el servidor:
ssh username@server -w any:any
Con el parámetro -w establecemos el túnel entre los dispositivos especificados. Si ponemos "any" como en el ejemplo el sistema cogerá el primer interfaz tun disponible.
Un vez creado el túnel procederemos a configurar los interfaces tun.
En el cliente:
ip addr add 1.1.1.2/32 peer 1.1.1.1 dev tun0
En el servidor:
ip addr add 1.1.1.1/32 peer 1.1.1.2 dev tun0
Y tendremos que configurar el reenvío IP y el NAT en el servidor:
echo 1 > /proc/sys/net/ipv4/ip_forward
iptables -t nat -A POSTROUTING -s 1.1.1.2 -o eth0 -j MASQUERADE
Ahora podemos hacer que el peer 1.1.1.1 sea la puerta de enlace predeterminada o enrutar un host o una red específicas a través de él:
route add -net 10.0.0.0/16 gw 1.1.1.1
En el ejemplo, la interfaz de red externa del servidor es eth0 y los dispositivos tun creados recientemente en ambos lados son tun0.
Truco del día
Seguramente os habréis dado cuenta que cada vez que creamos un túnel con SSH también obtenemos una shell. Esto no suele ser necesario cuando solo intentamos crear un túnel. Para evitar esto, podemos ejecutar SSH con los parámetros -nNT, como el siguiente ejemplo, lo que hará que SSH no asigne un tty y solo reenvíe los puertos.
$ ssh -nNT -L 9000: imgur.com: 80 user@example.com
-N : esta opción es la que indica que no se abra la shell, solo reenvío de puertos.
-n : se utiliza cuando ssh se ejecuta en background y previene que se lea de stdin.
-t : desactiva pseudo-tty
Fuentes:
- A Red Teamer's guide to pivoting
- SSH Tunnel - Local and Remote Port Forwarding Explained With Examples
- The Black Magic Of SSH / SSH Can Do That?
- How to Use SSH Tunneling to Access Restricted Servers and Browse Securely
Muy buen post y aclaratorio.
ResponderEliminar