¿Qué es la inyección SQL?

11

¿Cuál es el significado de inyección SQL? No soy capaz de entender el término. ¿Y qué problemas pueden ser causados por la inyección de SQL?

    
pregunta Bhavik Ambani 24.01.2012 - 12:16
fuente

2 respuestas

36

La inyección de SQL ocurre con mayor frecuencia cuando un programador construye un comando de SQL agregando (o interpolando) cadenas, utilizando la entrada proporcionada por el usuario.

por ejemplo Imagine este extracto de un pseudocódigo de autenticación de usuario (inicio de sesión) vulnerable de una aplicación web ficticia.

username = getPostData( "username" );
password = getPostData( "password" );

sql = "select id, username from users'
      + ' where username='" + username + "' and password='" + password +"'";
result = executeQuery( sql );

if (result[ 0 ]) {
  loginUser( result[ 0 ][ 'id' ] );
  print "You are logged in as " + encodeAsHtml( result[ 0 ][ 'username' ] );
}

A primera vista, puede parecerle sensato, pero el problema es que no hace distinción entre los datos proporcionados por el usuario y el código SQL; los datos se pueden tratar como código . Esto significa que un usuario malintencionado puede cambiar la lógica de la declaración SQL.

Un usuario malintencionado podría omitir completamente la protección de inicio de sesión si pudiera cambiar la lógica del comando SQL para producir una respuesta que garantice que siempre se devuelva siempre una fila.

Por ejemplo, si ingresó un nombre de usuario real bob , pero coloca la contraseña como:

' or 1=1 --

Entonces esto le permitiría acceder a la cuenta de otra persona. Esto se debe a que el SQL resultante se vería así:

select id, username
from users 
where username='bob' and password='' or 1=1 --'

Tenga en cuenta que la expresión lógica 1=1 siempre se evalúa como verdadera. También tenga en cuenta que el vector de inyección terminó con dos guiones, lo que marca el resto de la línea como un comentario. Por lo tanto, el SQL es lógicamente el mismo que

select id, username
from users 
where (username='bob' and password='') or true

que es lógicamente lo mismo que

select id, username
from users 
where true

que es lógicamente lo mismo que

select id, username 
from users

Por lo tanto, se devolverá a todos los usuarios de la base de datos y se registrará como el primero en la lista, que generalmente es el administrador.

También se puede usar la inyección SQL para leer todos los datos de la base de datos. Al ingresar el nombre de usuario de la siguiente manera (sintaxis de SQL Server) se mostrarán los nombres de las tablas definidas por el usuario

' union select -1, name, from sysobjects where xtype = 'U' order by id --

porque esto produce

select id, username
from users
where username = ''

union

select -1, name
from sysobjects
where xtype = 'U'

order by id asc

debido a que nuestros datos inyectados tienen un id de -1 y estamos clasificando los datos por ID, la primera fila devuelta de la base de datos será nuestra selección en la tabla sysobjects . Por lo tanto, nuestro " username " mostrado ahora será el nombre de la primera tabla creada por el usuario en la base de datos. Se pueden repetir técnicas similares para leer todos los datos de cada columna de cada fila de cada tabla accesible. Tenga en cuenta que esto todavía se puede hacer incluso cuando la función que está siendo atacada no produce ninguna salida.

Algunas combinaciones de bibliotecas de bases de datos en lenguaje de programación y DBMS también permiten apilar consultas . Esta es una técnica en la que se agrega un nuevo comando SQL al final. La base de datos ejecutará ambas consultas. Nombre de usuario:

'; delete from users --

produce

select id, username
from users
where username='';

delete from users 

Ahora su aplicación no tiene usuarios (y requiere una inyección de SQL para iniciar sesión). Consulte cómic XKCD obligatorio .

Vea esta hoja de trucos de SQLi si está interesado en más técnicas comúnmente utilizadas por los atacantes y la vulnerabilidad probadores.

Entonces, ¿cómo puedo evitar esto?

En realidad, en muchos escenarios comunes, es muy fácil. Prepared statements separa los datos del código y no permite que los parámetros se traten como código SQL. Simplemente recodifique su consulta para usar sentencias preparadas y vincular parámetros individuales a los marcadores de posición.

en pseudocódigo:

username = getPostData( "username" );
password = getPostData( "password" );

sql = "select id, username from users where username=? and password=?";
query = prepareStatement( sql );

query.setParameter( 0, username );
query.setParameter( 1, password );
result = executePreparedStatement( query );

Como siempre, esto no es toda la historia ...

No te olvides de defender en profundidad y siempre realiza validación de entrada también, como siempre lo harías (deberías). Las cláusulas WHERE necesitan atención adicional, ya que los caracteres especiales como % pueden no ser deseados. Tenga especial cuidado al pasar datos de usuario como argumentos a las funciones de la base de datos y tenga en cuenta cómo se puede abusar de ellos. Si tiene procedimientos almacenados que generan consultas dinámicas, es posible que necesite más protección dentro de los procedimientos mismos.

    
respondido por el Cheekysoft 24.01.2012 - 14:52
fuente
4

La inyección SQL es una técnica de uso de comandos SQL válidos para manipular, eliminar o inyectar datos en una base de datos back-end directamente a través de puntos débiles en la validación de la entrada de código a una aplicación web que llama a esa base de datos.

Es una de las OWASP Top Ten rutas de ataque más utilizadas, ya que es muy simple explotar.

Se puede usar para comprometer bases de datos completas de datos de clientes, datos de tarjetas de crédito, registros financieros, etc., o para obtener una copia de estos datos. En general, un gran impacto!

Lo bueno es que es muy fácil de mitigar a través de la Validación de entrada: la mayoría de los marcos proporcionan módulos para hacer esto.

    
respondido por el Rory Alsop 24.01.2012 - 13:43
fuente

Lea otras preguntas en las etiquetas