En términos sencillos:
Las aplicaciones web típicas son de tres niveles (navegador + servidor web + bases de datos backend). Cuando un usuario accede a un sitio web, su navegador recibe html y js que son producto de páginas web estáticas y también de dinámicas generadas mediante el código del lado del servidor (por ejemplo, php, asp). Cuando inicia sesión, por ejemplo, envía su contraseña y nombre de usuario al servidor web, que procesa dichos parámetros y aplica la lógica de autenticación preprogramada (en php, asp). Dicha lógica requiere verificaciones utilizando una base de datos que almacena datos de los usuarios y permite La verificación simple: el nombre de usuario coincide con la contraseña. Por lo tanto, la lógica del lado del servidor toma sus argumentos y consulta la base de datos (por ejemplo, MySQL).
SELECT * FROM Users WHERE username='your_supplied_username' AND password='your_supplied_password';
La base de datos procesa esto y devuelve (si la base de datos está diseñada correctamente) solo una (coincidencia de nombre de usuario y contraseña) o cero (contraseña incorrecta) que "lo represente".
¿Qué pasa con SQL Injection Bro?
No soy tu hermano, hermano: P. Un desarrollador descuidado tomaría los parámetros enviados por usted y los pondría directamente en los campos your_supplied_ *. Si el usuario no fuera malicioso, esto no sería ningún problema. Sin embargo, para un atacante malicioso, esto abre una puerta enorme para los ataques. Si está familiarizado con SQL, sabe que AND requiere que las expresiones izquierda y derecha se evalúen como verdaderas. Además, en SQLi, el carácter de comentario "-" es un amigo útil, ¿y si escribo mi nombre de usuario '; -?
SELECT * FROM Users WHERE username='your_supplied_username';--' AND password='your_supplied_password';
El código del lado del servidor tomará mi entrada, la aplicará a la consulta de cadena y la enviará a la base de datos. La base de datos interpretará "-" como un comentario que excluirá:
' AND password='your_supplied_password';
manteniendo:
SELECT * FROM Users WHERE username='your_supplied_username'
Esta es una consulta válida que se evaluará fácilmente como verdadera. Ahora, el comportamiento aquí varía. Si el nombre de usuario es único (normalmente lo es), solo se devolverá un registro. Si no es así, se devolverán varios registros y el código del servidor web (por ejemplo, php) generalmente elegirá el primero. Si está familiarizado con SQL, ahora puede obtener consultas creativas y en cadena, usar comodines y obtener comodines. Ahora la pregunta es:
Como desarrollador, ¿qué puedo hacer?
Ahora, esto depende del lenguaje del lado del servidor que está utilizando, pero las primitivas de codificación suelen tener el mismo nombre. Puede escapar de secuencias especiales usando php ( enlace ) o usar declaraciones preparadas ( enlace ).
¿Cómo puedo saber si el servidor sufre de SQLi?
Puede ejecutar herramientas como SQLMap o SQLNinja. También puedes ir a los formularios y escribir
'gibberish
donde, con suerte, confundirá el analizador de consultas php y filtrará un error que se muestra en su navegador (error de sentencia SQL). Existen otras técnicas, como inyectar una declaración de suspensión en las consultas para verificar si la base de datos se cuelga durante unos segundos antes de regresar. Como mecanismo de defensa, siempre debe procesar sus errores de SQL en el código del lado del servidor antes de enviarlos al usuario para evitar la fuga de información.
Mantente seguro;)