Controlar tu servidor mediante un ataque de shell inversa
10 de agosto de 2022
0 minutos de lecturaNota del editor: 9 de mayo de 2023
Esta publicación, publicada originalmente el 10 de agosto de 2022, se actualizó para mostrar cómo Snyk puede ayudarte a prevenir ataques de shell inverso.
Crear y ejecutar una aplicación en tu lenguaje favorito suele ser bastante sencillo. Después de crearla, implementarla y mostrarla al mundo también es bastante fácil. Lo último que necesitas es que alguien se apodere de tu sistema y tome el control total de tu nueva aplicación. En este artículo, explicaré cómo puede ocurrir esto mediante un ataque de shell inversa.
Ten en cuenta que los ejemplos de código de este artículo son solo para fines educativos. Mi objetivo principal es explicar qué es un ataque de shell remota y cómo puede ocurrir en tus aplicaciones. No se recomienda usar este ni ningún otro ejemplo para hackear a alguien. En la mayoría de los países, hackear sin el consentimiento del objetivo es ilegal, incluso si tienes las mejores intenciones.
¿Qué es una shell inversa?
Una shell inversa (o shell de conexión inversa) es una sesión de shell que inicia la máquina objetivo hacia un host remoto. La máquina objetivo abre la sesión hacia un host y puerto específicos. Se puede crear una conexión de shell si el host remoto escucha en ese puerto con el software adecuado. Es importante tener en cuenta que quien inicia la conexión es la máquina objetivo, no el host remoto.
En un ataque de shell remota, un atacante intenta hacer que la máquina de la víctima inicie esa conexión. El ataque puede establecer acceso interactivo a la shell (básicamente, una terminal) y tomar el control de la máquina de la víctima.
¿Cómo ocurre un ataque de shell inversa?
En la mayoría de los casos, un ataque de shell inversa ocurre cuando una aplicación es vulnerable a una vulnerabilidad de ejecución remota de código. Un atacante aprovecha una vulnerabilidad de la aplicación para ejecutar código en la máquina de la víctima e iniciar la sesión de shell. Sin saberlo, la víctima crea una conexión, y el atacante solo tiene que escuchar las conexiones entrantes en el puerto correcto. Una vez establecida la conexión, el atacante obtiene acceso a la shell de la víctima y puede hacer todo tipo de cosas interesantes.
Piensa en una pelota de tenis. Si la lanzas contra algo duro, rebotará hacia ti. Solo tienes que atraparla en el lugar y momento adecuados.
Cómo establecer una conexión de shell inversa
Para crear una shell inversa, tienes varias opciones, según el lenguaje que uses. Sin embargo, antes de ejecutar este código de shell inversa, debemos asegurarnos de escuchar en el puerto correcto las conexiones entrantes.
Escuchar conexiones entrantes con netcat
Una excelente herramienta para hacerlo es netcat. Netcat (a menudo abreviado como nc) es una utilidad de redes informáticas que permite leer y escribir en conexiones de red mediante TCP o UDP. En la máquina a la que quieres que se conecte la shell inversa, puedes usar netcat para escuchar las conexiones entrantes en un puerto específico. El siguiente ejemplo muestra cómo hacer que netcat escuche en el puerto 9001. Ten en cuenta que el parámetro v no es estrictamente necesario, pero proporciona una salida detallada útil.
Ejecutar una shell inversa en Python, Java o Node.js
Veamos dos métodos para configurar una shell inversa. Ambos ejemplos son adecuados para sistemas que tienen instalada la shell bash.
Carga útil de shell inversa:
El primer método consiste en realizar una acción mediante programación para iniciar una shell. Luego, creamos una conexión de socket con la computadora remota usando la dirección IP y el puerto adecuados.
Por último, conectamos los descriptores de archivo (entrada, salida y error) de la shell con la conexión de socket recién creada.
Java
En este ejemplo de Java, redirigimos el InputStream y el ErrorStream del proceso al OutputStream de la conexión de socket remota. También debemos hacer lo contrario y escribir el Socket OutputStream en el Inputstream del proceso bash.
Shell inversa en Python
En este script de Python, conectamos stdin, stdout y stderr a la conexión de socket. En los sistemas tipo Unix, estos son los tres primeros descriptores de archivo. Luego usamos pty para ejecutar bash.
Node.js
Este ejemplo de Node.js es muy similar al de Python. Ejecutamos bash y conectamos adecuadamente los descriptores de archivo estándar a la conexión de socket.
Ejecutar un comando de shell inversa:
El segundo método es un poco más corto. La mayoría de los lenguajes tienen alguna forma de ejecutar comandos de shell, como:
Runtime.getRuntime()en Javaos.system()en Pythonrequire(‘child_process’).exec()en Node.js
Podemos aprovechar estas funciones para ejecutar un comando de shell de una sola línea que inicie la shell inversa.
Java
Python
Node.js
Si primero ejecutas el comando netcat para escuchar en el puerto 9001 y luego ejecutas este fragmento de código, verás que se establece la conexión y podrás ejecutar comandos de shell como el siguiente.

Con todos los ejemplos anteriores, estableces una conexión de shell inversa contigo mismo. Si quieres hacerlo con una máquina remota, obviamente tendrás que cambiar la dirección IP según corresponda. Luego, recuerda que, aunque tengas acceso, los privilegios dependen del usuario que ejecute este código en la máquina de la víctima. Para obtener privilegios elevados, quizá tengas que hacer algo más.
Cómo crear un ataque de shell inversa mediante una vulnerabilidad de ejecución remota de código
Para llevar a cabo un ataque real con ejemplos de código como estos, debemos aprovechar una vulnerabilidad de ejecución de código e insertar el código en un sistema existente. Un gran ejemplo es la vulnerabilidad Log4Shell, descubierta en diciembre de 2021. Era posible insertar una clase gadget que ejecutara código al instanciarse. Muchos ejemplos mostraban cómo iniciar la calculadora o hacer algo inofensivo. Sin embargo, el código siguiente crearía un gadget para esta infame vulnerabilidad de Log4j. Si aprovechas Log4Shell hoy, ya no iniciarás la calculadora: la convertirás en un mecanismo para habilitar una shell inversa.
Casi cualquier vulnerabilidad de ejecución remota de código puede utilizarse para habilitar un ataque de shell inversa. Otros ejemplos recientes fueron Spring4Shell y la vulnerabilidad RCE de Apache Commons Configuration. Ninguno de los dos fue tan problemático como Log4Shell, pero puedes usar cualquiera para crear un ataque de shell inversa y posiblemente controlar una máquina objetivo. Por eso, es fundamental evitar que se ejecute, aunque sea parcialmente, la entrada del usuario.
Con Snyk Open Source, puedes analizar tu aplicación para detectar vulnerabilidades en bibliotecas de código abierto, incluido este problema de Log4j. Aquí tienes un ejemplo del resultado del complemento de Snyk para IntelliJ IDEA, que menciona este problema y cómo corregirlo.

Cómo prevenir ataques de shell inversa
Si impedimos que un atacante ejecute código en tu máquina, eliminamos casi todas las posibilidades de un ataque de shell inversa. Veamos algunas medidas que puedes tomar como desarrollador para prevenir ataques maliciosos de shell inversa.
Elimina las instrucciones de ejecución. Evita en la medida de lo posible las instrucciones de tu código que puedan ejecutar scripts u otras partes de código, como
exec().Desinfecta y valida las entradas. Debes considerar que todas las entradas pueden ser maliciosas. Esto no se limita a la entrada directa del usuario. Por ejemplo, si un campo de una base de datos se usa como entrada para una ejecución, alguien podría intentar atacar la base de datos.
Ejecuta tu aplicación con privilegios limitados. No ejecutes tu aplicación como root; crea un usuario con los privilegios mínimos necesarios. Lamentablemente, esto ocurre con frecuencia en aplicaciones dentro de contenedores Docker, ya que el usuario predeterminado de un contenedor Docker es root.
Prevén las vulnerabilidades que permiten la ejecución remota de código. Si una biblioteca o un framework está comprometido, reemplázalo por una versión segura.
Casi cualquier vulnerabilidad de ejecución remota de código puede utilizarse para un ataque de shell inversa, aunque el caso de uso parezca poco probable.
¡Snyk puede ayudar!
Snyk es una herramienta útil para prevenir ataques de shell inversa mediante el análisis de código y dependencias. Detecta posibles errores de seguridad en tu código personalizado y revisa las dependencias transitivas para encontrar vulnerabilidades conocidas.
Empieza con los desafíos de Capture the Flag
Aprende a resolver desafíos de captura la bandera con nuestro taller virtual introductorio a pedido.



