miércoles, 26 de mayo de 2010

Inyección SQL - Un caso raro


Estaba haciendo una serie de pruebas sobre inyección SQL (o SQL injection) y mientras las estaba haciendo me estaba dando una serie de problemas.

Lo primero resumir mucho (así podré contarlo más detallamente en otro momento) qué es la inyección SQL o SQL inyection.

SQL injection es la técnica por la cual se introducen expresiones propias de SQL en alguna(s) de las variables involucradas en las proposiciones de la misma.

Vamos a crear una base de datos llamada pruebasInyeccion en la que creo la tabla tablaInyeccion.

Acceso a la BB.DD pruebasInyeccion y creación de la tabla tablaInyeccion.

Una vez he creado la BB.DD con la que vamos a trabajar insertaré una serie de datos. Por ejemplo:

Inserción de 5 filas y su select.

Voy a poner un ejemplo que se suele poner mucho:

SELECT * FROM usuarios WHERE nomUsr = '$nombreIntroducido' AND password = '$passwordIntroducida';


Pongamos que a esta consulta le introducimos un $nombreIntoducido como "elQueSea' OR '1'='1" (sin comillas) y una $passwordIntroducida como "unaPassCualquiera' OR '1'='1" (la parte negrita de ambas opciones). Luego, a la hora de evaluar la consulta, tendríamos algo así:

SELECT * FROM usuarios WHERE nomUsr = 'elQueSea' OR '1'='1' AND password = 'unaPassCualquiera' OR '1'='1';


Total, para resumir, hemos "aumentado" proposiciones de esta consulta de 2 a 4, haciendo estas dos últimas que siempre se cumpla la condición. Así, de encontrarnos en un sistema de autenticación vulnerable a esta técnica, nos daría paso.

¿Qué tiene que ver toda esta parafernalia con el caso extraño que quería comentar? Vamos a la tabla de la captura. En esa tabla genérica se han introducido datos que podrían ser los de una tabla de usuarios y contraseñas.

Una select normal sería algo así:

SELECT * FROM tablaInyeccion WHERE cab2 = 'usr01' AND cab3 = 'password01';


Dando como resultado:

Resultado de la select

Pongamos que queremos obviar la necesidad de utilizar la password. ¿Qué harías? Yo intentaría hacer que el usuario "comentara" el resto de la consulta. ¿Cómo se comenta en SQL? Se comenta usando dos guiones seguidos ("--"; sin las comillas). Luego, podríamos introducir un cab2 con un valor igual a "usr02' OR '1'='1';--" y un cab3 con un valor igual a "LALALAAAAAA".

SELECT * FROM tablaInyeccion WHERE cab2 = 'usr02' OR '1'='1';--' AND cab3 = 'LALALAAAAAA';


Así, nos devuelve:

Inyección con error (¿?)

¿Cómo es posible que esto de un error? Vamos a probar otra la consulta...

SELECT * FROM tablaInyeccion WHERE cab2 = 'usr02' OR '1'='1';-- ' AND cab3 = 'LALALAAAAAA';


Inyección sin error

Luego. ¿Por qué unas veces sí y otras no? ¿Dónde está la diferencia entre una y otra consulta para que la primera de un error después de realizar la operación y la otra ni se inmuta? Vamos a comparar las dos consultas bien pegaditas:

SELECT * FROM tablaInyeccion WHERE cab2 = 'usr02' OR '1'='1';--' AND cab3 = 'LALALAAAAAA';
SELECT * FROM tablaInyeccion WHERE cab2 = 'usr02' OR '1'='1';-- ' AND cab3 = 'LALALAAAAAA';

¿Ya? El problema está en que en los últimos tres caracteres de la primera consulta son ";--" y en la segunda los 3 últimos son "-- ". (mirar que después de los guiones hay un espacio). Y, eso es lo que quería mostrar que me había llamado la atención. Algo más que he descubierto buscando la razón por la que es necesario un espacio en blanco (o, qué es lo que hace realmente si no se introduce), es que hay otras formas de comentar. Resumiendo:

- #Esto está comentado al poner el símbolo # antes de la línea.
- /*Lo que se encuentra entre estos asteriscos con las barras estará comentado. */

Según he podido averiguar, se necesita el espacio en blanco para que se diferencie entre un comentario y una operación matemática. Dado:

UPDATE account SET credit=credit-!payment!
Donde !payment! es -1 obtendríamos:
UPDATE account SET credit=credit--1
Dando lugar a:
UPDATE account SET credit=credit--1
que no es lo esperado. Al menos esa es la razón por la que he entendido que hacer falta poner el espacio. A sí que... Mucho cuidadín. 

No hay comentarios:

Publicar un comentario