Skip to main content

Inyección de comandos: cómo funciona, cuáles son los riesgos y cómo prevenirla

Escrito por

25 de noviembre de 2020

0 minutos de lectura

Los ataques de inyección de comandos, también conocidos como ataques de inyección de comandos del sistema operativo, aprovechan una falla de programación para ejecutar comandos del sistema sin validar, escapar ni sanitizar correctamente las entradas. Esto puede permitir que un atacante malicioso ejecute comandos arbitrarios.

¿Cuáles son los riesgos de la inyección de comandos?

Según la configuración de la aplicación y del proceso que la ejecuta, una vulnerabilidad de inyección de comandos podría permitir escalar los privilegios del proceso o iniciar un shell inverso remoto que le dé a una parte maliciosa control total.

¿Cómo funcionan los ataques de inyección de comandos?

Para entender las fallas de programación relacionadas con los ataques de inyección de comandos del sistema operativo, exploremos varias vulnerabilidades de este tipo que se descubrieron en aplicaciones basadas en Node.js.

systeminformation es una biblioteca de información del sistema operativo (SO) con más de 500,000 descargas semanales, mantenimiento regular (commits) y una comunidad a su alrededor, como podemos ver en la página de Snyk Advisor sobre el estado de las dependencias:

Página del paquete npm systeminformation que muestra una puntuación de estado de 75/100, la tendencia semanal de descargas y un gráfico de la frecuencia de commits de mantenimiento

Sin embargo, todas las versiones de system information anteriores a la versión 4.27.11 son vulnerables a la inyección de comandos del SO debido a varios métodos vulnerables que la biblioteca pone a disposición de sus usuarios.

Veamos el código de la función vulnerable inetChecksite(). ¿Puedes detectar la vulnerabilidad de seguridad en este código que muestra un ejemplo de inyección de comandos?

      let urlSanitized = util.sanitizeShellString(url).toLowerCase();
      if (urlSanitized) {
        let t = Date.now();
        if (_linux || _freebsd || _openbsd || _netbsd || _darwin || _sunos) {
          let args = ' -I --connect-timeout 5 -m 5 ' + urlSanitized + ' 2>/dev/null | head -n 1 | cut -d " " -f2';
          let cmd = 'curl';
          exec(cmd + args, function (error, stdout) {
          …

Puedo sacar varias conclusiones de este fragmento de código:

  • Se está sanitizando un parámetro url. ¿Quizás pueda evadir las funciones de sanitización con algo que el autor no tuvo en cuenta?

  • Se usa una API insegura para iniciar procesos del sistema operativo: exec(), que concatena los comandos y sus argumentos en un único comando de shell que se ejecuta. Por eso el autor tuvo que recurrir a su propio método para sanitizar los argumentos de la línea de comandos.

La variable urlSanitized se concatena como parte de los argumentos que se pasan a la CLI.

Ese último punto sobre urlSanitized es donde se encuentra esta vulnerabilidad de seguridad. El comando en sí, indicado por la variable cmd, es la utilidad de red curl. ¿Y si simplemente pudiéramos pasar un argumento de comando a curl como URL?

Se podría intentar una inyección de comandos con la siguiente prueba de concepto, usando la URL proporcionada a la función vulnerable, como se muestra en el primer argumento que se pasa a la función inetChecksite(). Este es un ejemplo de inyección de comandos:

 const si = require('systeminformation');
si.inetChecksite("https://snyk.io; touch /tmp/abc", (result) => console.log(result));

Sin embargo, en este caso no funciona porque este paquete de npm sanitiza las entradas peligrosas del usuario, como el punto y coma (;).

Sin embargo, los argumentos de línea de comandos no suelen requerir caracteres especiales. Podríamos proporcionar como entrada del usuario una URL como https://snyk.io -o hihi, que incluye un espacio y concatena el argumento posicional -o de curl, el cual guarda el resultado del sitio web en un archivo que controlamos.

Aquí tienes otro ejemplo de inyección de comandos que muestra cómo podría llevarse a cabo la explotación y que funciona según lo esperado con una versión vulnerable de systeminformation@4.27.10:

const si = require('systeminformation');
si.inetChecksite("https://snyk.io -o hihi", (result) => console.log(result));

Este commit mejoró la sanitización para reducir aún más este tipo de vulnerabilidades de inyección de comandos:

Comparación de código en lib/internet.js que muestra una sanitización ampliada de URL con reemplazos de caracteres adicionales.

Guía rápida de inyección de comandos

Podemos aprender mucho de otros ejemplos de inyección de comandos en los que identificamos vulnerabilidades de seguridad en paquetes de código abierto y cómo se mitigaron, como las siguientes vulnerabilidades aquí y aquí.

Para prevenir los ataques de inyección de comandos, considera estas prácticas:

  1. No permitas que ninguna entrada del usuario llegue a los comandos que ejecuta tu aplicación.

  2. Usa únicamente API seguras para ejecutar comandos, como execFile(). A diferencia de otras API, esta acepta un comando como primer parámetro y un arreglo de argumentos de línea de comandos como segundo parámetro de la función. De este modo, el comando debe ser un programa válido y no puede estar relacionado con entradas peligrosas.

  3. Cuando uses execFile(), asegúrate de que el usuario no tenga control sobre el nombre del programa. Además, asigna las entradas del usuario a los argumentos del comando para evitar que se pasen tal cual a la ejecución del programa.

  4. Como precaución adicional, valida que las entradas del usuario cumplan con el formato esperado. Por ejemplo, si un parámetro de función espera una URL, valida que la entrada recibida sea una URL válida. Esto habría evitado la vulnerabilidad de inyección de comandos mencionada anteriormente en el paquete de npm systeminformation.

Ataques de inyección de comandos y OWASP Top 10

Para mostrar lo comunes que son los ataques de inyección de comandos del SO, busqué todas las vulnerabilidades de seguridad conocidas públicamente que el equipo de seguridad de Snyk publicó en octubre de 2020 y filtré los resultados por el ecosistema JavaScript en npm. Como puedes ver, solo en la última semana de octubre se identificaron bastantes vulnerabilidades de seguridad de Command injection en paquetes de npm.

Página de Snyk Vulnerability Database que muestra una búsqueda de vulnerabilidades, filtros de paquetes y una lista de vulnerabilidades de npm con su gravedad y fecha de publicación.

En conclusión, las vulnerabilidades de inyección de comandos son más comunes de lo que crees, y por una buena razón los ataques de inyección aparecen desde hace tiempo en la lista de los 10 principales riesgos de seguridad web de OWASP: son frecuentes y adoptan muchas formas, como los ataques de inyección SQL. Te recomiendo conectar tus repositorios de Git con Snyk para probarlos y corregir las vulnerabilidades de inyección de comandos. ¿Quizás Snyk encuentre otras también? Snyk es gratis y configurar la supervisión de tus proyectos es rápido.

Empieza con Capture the Flag

Aprende a resolver desafíos de Capture the Flag viendo nuestro taller virtual introductorio a pedido.

Leer más

Blog

Los modelos de frontera encontraron las vulnerabilidades. Solo el atacante encontró las cadenas.

El análisis estático encontró las fallas, pero solo las pruebas de ataque en vivo demostraron cómo podían encadenarse para provocar brechas. Una comparación de Evo COS, Claude Security y Claude Code Security.

feature insights context
Blog

Los ataques autónomos ya están aquí. La defensa debe estar a su altura.

Los atacantes autónomos están reduciendo el tiempo disponible para defenderse. Descubre cómo el descubrimiento, la corrección, la validación y la prevención continuos pueden ayudar a los equipos de seguridad a seguirles el ritmo.

Blog

Por qué los agentes de programación con IA siguen generando fallas de control de acceso

Los agentes de programación con IA pueden generar lógica de autorización que compila y supera la revisión, pero expone los datos de un inquilino a otro. Descubre por qué es difícil detectar el control de acceso roto y cómo prevenirlo.