Si estás cansado de oír hablar de los SQL Injection pero nunca te ha quedado muy claro para qué servían… o sirven, voy a intentar dar un pequeño y claro ejemplo. No hay tema mejor para empezar una serie de clasicos de la ciberseguridad, así que estreno la sección en la que se intentara explicar clásicos como: Los SQL Injection, los Styack Overflow, como funcionan los protocolos de seguridad, intercambio de claves, encriptación… los clásicos!
Los SQL Injection han formado parte de la historia de Internet. Han sido uno de los agujeros más usados para reventar la seguridad de diversas hojas WEB, o de Intranets. Cualquier formulario que pidiera datos era una víctima posible del terrible ataque conocido como SQL Injection.
Detrás de este nombre lo único que hay es una técnica muy simple basada en introducir comandos SQL en los campos de los formularios para ver si se podían ejecutar, y de todos estos comandos, uno era el protagonista, y es el que vamos a usar para este ejemplo.
¿De qué va lo del SQL Injection?
Se trata de introducir sentencias SQL en los campos que nos piden que rellenemos. Las instrucciones enviadas pueden tener varias intenciones malévolas, como robar datos, obtener una entrada en nuestro sistema, o simplemente borrar nuestra base de datos.
Está claro que si quien realiza un ataque con SQL Injection tiene conocimientos de nuestra base de datos, tendrá más posibilidades de hacernos daño, ya que sabrá los nombres de nuestras tablas, nuestros campos… como estan organizadas las consultas. Pero un atacante que no tenga ni idea de cómo es nuestra base de datos también tiene muchas oportunidades para conseguir lo que busca.
Vamos a ver cómo se crea una orden SQL, para que nos sea más sencillo entender cómo funcionan los SQL Injection.
[code language=»javascript»]
var tuCiudad;
tuCiudad = Request.form("tuCiudadForm");
var ordenSQL = "select * from socios where tuCiudadField =’" + tuCiudad +"’"
[/code]
Pongamos que queremos ejecutar una consulta que nos devuelva todos los socios de nuestro club que viven en la ciudad que el usuario indique. La orden SQL seria mas o menos así:
[code language=»SQL»]
SELECT * FROM socios WHERE tuCiudadField = ‘BARCELONA’;
[/code]
Pero como no vamos a crear una orden para cada ciudad lo que hacemos es crear la orden mediante la concatenación del valor que introduce el usuario. Entonces nos fiamos de que el usuario ponga una ciudad. Porque ponga lo que ponga nosotros lo vamos a concatenar a nuestro SQL y lo vamos a lanzar a la base de datos. Si el usuario tiene un bastante mala leche y un poco de destreza va a poder crearnos unos cuantos problemillas.
Ejemplo tontisimo de SQL Injection
La parte más golosa de atacar de cualquier WEB es su login. Así que vamos a basar el ejemplo en un formulario que nos pide el usuario y el password, que podría ser el de login, recuperación, o lo que sea que necesite estos datos. Cómo aprovechar el formulario de login de una página WEB con un sistema de seguridad tirando a nulo. Es decir, que nadie se piense que con esto conseguiremos entrar en Facebook, gmail, ni siquiera hotmail… tal como están los tiempos no tendría que funcionar ni en la WEB de la panadería de nuestro barrio, pero… seguro que funciona en mas de una.
Partamos de un formulario en el que tengas que introducir el usuario y el password y se seleccionarán todos los datos del usuario. En un principio si no sabemos el usuario y el password no tendríamos que recibir ninguna respuesta. Veamos como seria el codigo:
[code language=»javascript»]
var usuario;
var password;
usuario = Request.form("usuarioForm");
password = Request.form("passwordForm");
var ordenSQL = "SELECT * FROM usuarios WHERE usuario =’" + usuario +"’ AND password =’" + password + "’;"
[/code]
Si el usuario introduce MANOLO y PASSWORDILLO la orden quedaría como:
[code language=»SQL»]
SELECT * FROM usuarios WHERE usuario = ‘MANOLO’ AND password = ‘PASSWORDILLO’;
[/code]
¿Pero qué pasa si el usuario tiene mala leche y introduce ‘or 1 = 1 — en el nombre y cualquier cosa tanto da en el password? Pues muy sencillo, que nuestra orden SQL queda como:
[code language=»SQL»]
SELECT * FROM usuarios WHERE usuario = » OR 1 = 1 –cualquiercosa
[/code]
Lo primero es saber que para SQL cualquier cosa después del doble guión «–» es un comentario, por lo que no tiene ninguna importancia. Al ejecutar la orden primero se buscaría el nombre del usuario, y no se encontraría, pero como hemos introducido una cláusula OR la sentencia se volvería correcta para todo el contenido de la base de datos y nos devolverá todo su contenido. Está claro que no es la respuesta que espera la pagina y que no entraremos, pero la orden se ejecutará y podríamos llegar a obtener todos los datos de los usuarios del sistema.
Va, otro ejemplo, esta vez con un poco de mala leche, y conocimiento de nuestra base de datos. Imaginad que lo introducido en el campo usuario es: Usuario’ DROP TABLE usuarios;–
Nos eliminan la base de datos de usuarios, así tranquilamente.
Para estos ejemplos estamos asumiendo unos sistemas muy pero que muy desprotegidos, en el mundo real se controlaría la entrada en el lado cliente y el usuario que ejecuta las SQL de la aplicación no tendrá permisos para borrar tablas. ¿Verdad? o no… hay veces que nos olvidamos de estas cosas. Que dejamos las entradas desprotegidas, o que usamos el usuario administrador para acceder a nuestra base de datos. No tenemos que hacerlo, porque si lo hacemos, cualquier persona con un poco de conocimientos y tiempo podría liarnos una buena.
Aunque, para mí, la mejor solución es dejar estos temas a los expertos, es decir, no crees un sistema de usuarios por ti mismo. Utiliza Firebase, o oAuth2, o integra login de Facebook, o Google. Ellos se ocupan de que nadie pueda robar los datos de sus usuarios, ellos se ocupan de que el proceso de login sea seguro. No vas a diseñar nunca un sistema tan seguro como el suyo.
Por cierto, ya os habréis dado cuenta que el texto ‘ or 1=1 — es un clásico, y que no hace falta introducirlo en un formulario de login.