TL; DR
- La aplicación acepta la entrada, en este caso 'Nancy', sin intentar - desinfectar la entrada, como escapando de caracteres especiales
school => INSERT INTO estudiantes VALUES ( 'Nancy' ); INSERTAR 0 1
- La inyección de SQL se produce cuando la entrada en un comando de base de datos se manipula para - hacer que el servidor de base de datos ejecute SQL
school arbitrario => INSERTAR EN LOS VALORES de los estudiantes ( 'Robert' ); DROP TABLE estudiantes ; - '); INSERTAR 0 1 TABLA DE GOTA
- Los registros de los estudiantes ya no están, ¡podría haber sido aún peor!
escuela => SELECCIONAR * DE los estudiantes ;
ERROR : relación "estudiantes" no no existir
LÍNEA 1 : SELECCIONAR * DE los estudiantes ; ^
Esto elimina (elimina) la tabla del alumno.
( Todos los ejemplos de código en esta respuesta se ejecutaron en un servidor de base de datos PostgreSQL 9.1.2 ) .
Para dejar en claro lo que está sucediendo, intentemos esto con una tabla simple que contenga solo el campo de nombre y agregue una sola fila:
escuela => CREAR TABLA estudiantes ( nombre TEXTO PRIMARIA CLAVE );
AVISO : CREAR TABLA / PRIMARIA CLAVE va a crear implícita índice "students_pkey" de mesa "estudiantes" CREAR TABLA
escuela => INSERTAR EN estudiantes VALORES ( 'John' ); INSERTAR 0 1
Supongamos que la aplicación usa el siguiente SQL para insertar datos en la tabla:
INSERTAR EN LOS VALORES de los estudiantes ( 'foobar' );
Reemplazar foobar
con el nombre real del alumno. Una operación de inserción normal se vería así:
- Entrada:
escuela Nancy => INSERTAR EN LOS VALORES de los estudiantes ( 'Nancy' ); INSERTAR 0 1
Cuando consultamos la tabla, obtenemos esto:
escuela => SELECCIONAR * DE los estudiantes ;
nombre
-------
Juan
Nancy
( 2 filas )
¿Qué sucede cuando insertamos el nombre de Little Bobby Tables en la tabla?
- Entrada: Robert '); DROP TABLE estudiantes; -
escuela => INSERTAR EN LOS VALORES de los estudiantes ( 'Robert' ); DROP TABLE estudiantes ; - '); INSERTAR 0 1 TABLA DE GOTA
La inyección SQL aquí es el resultado del nombre del estudiante que termina la declaración e incluye un DROP TABLE
comando separado ; los dos guiones al final de la entrada están destinados a comentar cualquier código sobrante que, de lo contrario, causaría un error. La última línea de la salida confirma que el servidor de bases de datos ha descartado la tabla.
Es importante tener en cuenta que durante la INSERT
operación la aplicación no verifica la entrada de caracteres especiales y, por lo tanto, permite la entrada arbitraria en el comando SQL. Esto significa que un usuario malintencionado puede insertar, en un campo normalmente destinado a la entrada del usuario, símbolos especiales como comillas junto con un código SQL arbitrario para hacer que el sistema de base de datos lo ejecute, por lo tanto, la inyección SQL .
¿El resultado?
escuela => SELECCIONAR * DE los estudiantes ;
ERROR : relación "estudiantes" no no existir
LÍNEA 1 : SELECCIONAR * DE los estudiantes ; ^
La inyección SQL es el equivalente de la base de datos de una vulnerabilidad de ejecución remota de código arbitrario en un sistema operativo o aplicación. El impacto potencial de un ataque de inyección SQL exitoso no puede subestimarse; según el sistema de la base de datos y la configuración de la aplicación, un atacante puede usarlo para causar pérdida de datos (como en este caso), obtener acceso no autorizado a los datos o incluso ejecutar código arbitrario en la máquina host misma.
Como señaló el cómic XKCD, una forma de protegerse contra los ataques de inyección SQL es desinfectar las entradas de la base de datos, como escapar caracteres especiales, para que no puedan modificar el comando SQL subyacente y, por lo tanto, no puedan causar la ejecución de código SQL arbitrario. Si usa consultas parametrizadas, como SqlParameter
en ADO.NET, la entrada, como mínimo, se desinfectará automáticamente para evitar la inyección de SQL.
Sin embargo, las entradas de desinfección a nivel de aplicación pueden no detener las técnicas de inyección SQL más avanzadas. Por ejemplo, hay formas de eludir la mysql_real_escape_string
función PHP . Para mayor protección, muchos sistemas de bases de datos admiten declaraciones preparadas . Si se implementa correctamente en el backend, las declaraciones preparadas pueden hacer que la inyección de SQL sea imposible al tratar las entradas de datos como semánticamente separadas del resto del comando.