viernes, 6 de abril de 2012

Inyección SQL persistente

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.