SQL injection [1. Ataques]

Antes de empezar… conociendo el ataque

 

¿Que es una inyección SQL?

La vulnerabilidad a inyecciones SQL es un bug de seguridad que suele darse en sitios web aunque también puede darse en un programa normal. Se basa en un fallo en la comunicación entre el usuario final y la base de datos. Esta comunicación se hace a través de un lenguaje llamado SQL (Structured Query Language, Lenguaje Estructurado de Consultas), de ahí el nombre.

La forma más común de ese error es confiar en la entrada y permitir al usuario modificar la consulta a la base de datos para que haga algo diferente a su propósito original.

 

¿Que es SQL?

SQL es un lenguaje diseñado para consultar y modificar bases de datos, es simple inglés, lo que permite aprenderlo rápidamente, por ejemplo, si queremos ver la información de una tabla usuarios, la consulta sería:

select * from bd_tuto;
Después veremos como funciona básicamente este lenguaje para poder usarlo en nuestro favor.

 

¿Se puede evitar una inyección SQL?

Por supuesto, “simplemente” comprobando que los datos de entrada son seguros (normalmente los que provee el usuario), conseguiremos una página web/programa/script que no sea vulnerable a una inyección SQL.

 

 

Este post esta diseñado para aquellos q saben manejar un select, delete y update en sql transact de lo contrario let me google that for you esta presente: https://encrypted.google.com/search?q=sql+transact

 

Técnicas básicas de inyección SQL

1. Inyecciones de salto de variable
Supongamos una consulta que comprueba que un par usuario / contraseña es correcto, haciendo
select *
from bd_tuto
where usuario = ‘$usuario’ and (password = ‘$password’);
(Para distinguir mejor, los datos variables tienen un $ al principio).
La idea es que si quien programó la parte que se conecta a la base de datos y hace la consulta no tuvo
especial cuidado podemos “salirnos” de la variable y modificar la consulta, por ejemplo, si introducimos
un usuario cualquiera (“ejemplo”), pero como contraseña introducimos una comilla simple (‘), la consulta
quedaría así:
select *
from bd_tuto
where usuario = ‘ejemplo’ and (password = ”’);

Como se puede ver, la consulta es errónea, en la parte de la contraseña hay:
[…]password = ” ‘ ;

 

Se comprueba que “password” es igual a ” (esto no nos importa), pero después está el comienzo de un dato alfanumérico (del que ; forma parte), que nunca acaba, con lo que tampoco acaba la consulta, esto hace que se produzca un error, y la comunicación con la base de datos no continúe, pero ya sabemos que la aplicación es vulnerable a este tipo de ataques.
Si añadimos dos ‘, este error no se produciría, sino que simplemente quedaría un dato alfanumérico por el medio, normalmente las bases de datos simplemente ignoran ese dato . La situación entonces queda así:

select *
from bd_tuto
where usuario = ‘ejemplo’ and (password = ” ”);

Por último, podemos apoyarnos en el operador or (si cualquiera de los dos componentes es “verdadero”, el resultado lo es) así que poniendo como contraseña:
‘ or ‘1’=’1 , la consulta resultante sería:

 

select *
from bd_tuto
where usuario = ‘ejemplo’ and (password = ” or ‘1’=’1′);

 

Lo que resultaría son todos los usuarios que se llamen “yoquese” y para los que la contraseña sea “” (vacía) o que “1” sea igual a “1”, así que algún usuario saldrá (a menos que no haya ninguno con ese nombre). En este ejemplo, el fallo permitiría (por ejemplo) loguearse como otro usuario.

 

2. Inyecciones con datos numéricos
Es lo mismo que el ejemplo anterior, pero aplicado a datos numéricos, supongamos que se comprueba
que usuario es a través de un ID (numérico)

select *
from bd_tuto
where id = $id;

 

(Estos ID se suelen ver en las URL’s)
Lo interesante de estos casos es que (a menos que estén bien protegidos) dejan la consulta totalmente expuesta, supongamos que nuestra ID es 65535, si después de nuestra ID añadimos un ‘;’ y una consulta adicional (sin el ‘;’ , ya que está el de la consulta original), podemos hacer lo que queramos, por ejemplo, si usamos como una id 65535; insert into bd_tuto values
(‘nuevoUsuario’,’nuevaContraseña’,0) , el resultado será:

 

select *
from bd_tuto
where id = 65535; insert into bd_tuto values (‘nuevoUsuario’,’nuevaContraseña’,0) ;

 

Seguramente todo parezca que va bien en esta consulta, pero la tabla bd_tuto ahora tiene un usuario más, el que hemos inyectado.
Esto mismo se puede hacer con el otro tipo de datos, simplemente añadiendo las ‘ cuando sea necesario, además se puede hacer lo mismo que en el caso anterior (si hubiera una comprobación de ID), poniendo una id de 65535 or 1=1 :

 

select * from bd_tuto

where id = 65535 or 1=1 ;

 

Más inyecciones SQL

Aunque ya se conozcan las técnicas básicas de inyección SQL, no todo lo que se puede inyectar es ‘ or ‘1’ = ‘1

 

3. Comentarios

Supongamos que por un motivo cualquiera queramos eliminar una porción completa de la consulta a la base de datos, esto es posible porque SQL permite comentarios dentro de las propias consultas, los dos tipos más frecuentes (y que se encuentran en los servidores mas usados) son:

Comentario en una sola linea ( — ), a partir de esto el resto de la linea se ignorará, aunque parece que puede dar problemas según que bases de datos, por ejemplo MySQL requiere que después haya un espacio en blanco y un carácter (por eso aquí usaré — a para estos
comentarios, la a no tiene ningún significado especial ).

Volviendo a la consulta de usuario/contraseña…

select *
from bd_tuto
where usuario = ‘$usuario’ and password = ‘$password';

 

Si al final del nombre del usuario se añade un ‘ (para “escaparse” de la cadena alfanumérica), se marca que se acabó la consulta con un ; y después se añade un — a , la consulta quedaría así:

select *
from bd_tuto
where usuario = ‘ejemplo’ ; – a ‘ andpassword = ‘$password';

 

(En rojo lo que queda comentado, lo que no “lee” el SQL) Como se puede ver, no se hace ninguna comprobación sobre la contraseña, ya que queda comentada, esto puede ser especialmente útil cuando, por ejemplo, solo se comprueba que la parte de la contraseña no tiene caracteres maliciosos.

Comentarios multilínea ( /* y */ ), a partir del comienzo del comentario ( /* ), y hasta su final ( */ ), todo se ignorará, por ejemplo :

select *
from bd_tuto
where usuario = ‘$usuario’

and password = ‘$password’

and ID=$ID;

 

Si al nombre del usuario se añade un ‘ (de nuevo para “escapar” de la cadena alfanumérica) y un /* para iniciar el comentario, y a la ID (que, recordemos que es numérica ) un */ para finalizar el comentario, el resultado sería:

 

select *
from bd_tuto
where usuario = ‘ejemplo’ /* ‘
andpassword = ‘blablabla’
and ID=65535 */;

(Lo rojo, es lo comentado) Como se puede ver, es muy útil cuando las comprobaciones se realizan en distintas líneas.

 

A veces, con un solo tipo de comentarios, no es suficiente, si en el caso anterior, la ID fuera alfanumérica:

 

select *
from bd_tuto
where usuario = ‘ejemplo’ /* ‘
andpassword = ‘blablabla’
and ID=’65535 */ ‘ ;

 

La consulta es errónea, así que no nos sirve, pero si la ID se cambia por un */ , para acabar el comentario anterior, un ; para acabar la consulta y un — a para comentar el resto de la línea:

select *
from bd_tuto
where usuario = ‘ejemplo’ /* ‘
andpassword = ‘blablabla’
and ID=’65535 */ ; — a’ ;

 

Aunque el ; no sería necesario si en la consulta estuviera en una línea independiente, porque:

select * from bd_tuto

where usuario = ‘ejemplo’ /* ‘
andpassword = ‘blablabla’
and ID=’65535 */ — a’
;

 

Además comentar que el /**/ se puede utilizar como sustituto de un espacio, esto lo hace especialmente útil cuando se filtran los espacios de lo que introduce el usuario, haciendo que se puedan seguir construyendo consultas que los requieran.

 

4. Concatenar consultas y nombres de tablas.

 

Continuará…