Aunque hace apenas unos días me llegó el libro de SQL Injection de Informática64, apenas lo he podido empezar. Es posible que esto que empecé a escribir hace 3 semanas más o menos esté reflejado ahí dentro, pero, de ser así, no he llegado a ese punto.
****
Desde hace muchos, muchos años, se conoce la problemática del manejo de datos en las aplicaciones cuando se trata de bases de datos. Todos, espero, sabemos que si no controlamos la entrada de esos datos, puede tener consecuencias insospechadas.
Por ejemplo, si queremos utilizar un campo en nuestra aplicación para buscar... digamos, descripciones de casas, podríamos tener algo así
SELECT * FROM CASAS WHERE desc=$miEntradaDeBusquedaDeCasas;
Si no controlásemos esa búsqueda, y nos pusieran algún carácter inesperado, nos podríamos encontrar con esto
$miEntradaDeBusquedaDeCasas=$_POST['textDescCasas'];
Donde
$_POST['textDescCasas'] es %piscina';--
con el siguiente resultado
SELECT * FROM CASAS WHERE desc='%piscina';-- ';
También conocemos los distintos tipos de XSS: los persistentes y los no persistentes.
Si nos quedamos con los persistentes, sabremos que estos se ejecutarán a perpetuidad. Vamos, hasta que se elimine ese registro de la base de datos.
Ahora, lanzo la pregunta: ¿Qué sucedería si controlases las inyecciones sólo a la hora de recoger los datos del teclado y recibirlos, pero se guardasen en la base de datos? Lo que podría pasar es que si no se controlan esos datos, y los usas en otras consultas, los resultados no serían los esperados. Se podría hacer que la aplicación rompa cada vez que se acceda a ese registro.
Un ejemplo podría ser algo parecido a lo que voy a mostrar a continuación.
$miEntradaDeBusquedaDeCasas = "IT'S A DESCRIPTION";
INSERT INTO CASAS (DESC) VALUES(?);
bind(1,miEntradaDeBusquedaDeCasas);//sí, me lo he inventado un poco, pero para el caso de ejemplo...
$descripciones = getRows("SELECT desc FROM CASAS");
foreach($descripciones as$ descripcion){
SELECT * FROM CASAS2 WHERE desc='.$descripcion['DESC'].';
}
La última consulta se acabaría obteniendo:
SELECT * FROM CASAS2 WHERE desc='IT'S A DESCRIPTION';
Para el que le cueste verlo:
SELECT * FROM CASAS2 WHERE desc='IT'S A DESCRIPTION';
Por lo tanto, al ejecutar esa consulta, el motor de bases de dato no sería capaz de tratarlo. Esa cadena "S A DESCRIPTION'" sobraría. Lo peor de todo es que se encuentra insertada en una tabla. Cada vez que se encuentre ese registro y lo usemos de esta manera, nos saltará el error.
Algo parecido a esto es lo que me he encontrado recientemente en un programa. Y ha sido muy, muy curioso. Además, me he echado unas buenas risas. No creo que este concepto sea nuevo, pero, como digo, sí muy curioso, al menos para mí. Lo que nos enseña que también tenemos que tener cuidado con lo que tenemos guardado, y no sólo con lo que nos acaban de introducir por teclado.
Mostrando entradas con la etiqueta sql_inyection. Mostrar todas las entradas
Mostrando entradas con la etiqueta sql_inyection. Mostrar todas las entradas
viernes, 6 de abril de 2012
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.
Suscribirse a:
Entradas (Atom)
