¿Qué es una inyección SQL?
Una inyección SQL es un ataque. Alguien escribe órdenes de SQL en un cuadro de texto, y la base de datos las ejecuta. SQL es el lenguaje de las bases de datos. Pasa cuando una web pega lo que escribe el usuario dentro de su consulta.
Es uno de los fallos web más viejos y sigue existiendo. En esta lección verás por qué ocurre y cómo se arregla con una consulta parametrizada.
Al terminar esta lección
Nota
Puedo explicar cómo funciona una inyección SQL y arreglarla con una consulta parametrizada.
Palabras clave
| Palabra | Qué significa |
|---|---|
| Consulta | una orden de SQL que pide datos a una base de datos |
| Entrada del usuario | lo que escribe una persona en un formulario |
| Concatenar | pegar textos uno detrás de otro |
| Inyección SQL | colar órdenes de SQL dentro de una entrada |
| Consulta parametrizada | una consulta con huecos que se rellenan aparte |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
La regla de este laboratorio
Advertencia
Practica solo con la tienda de tu copia privada, que no tiene salida a internet. Nunca pruebes una inyección en una web real: es un delito. Aprendemos cómo se rompe una consulta para escribir consultas que no se rompan.
La web arma la consulta pegando textos
Una tienda tiene un cuadro de búsqueda. El programa de la web toma lo que escribes y lo pega dentro de una orden de SQL.
Mientras escribas un nombre normal, funciona. El problema llega cuando lo escrito trae comillas o palabras de SQL. La base de datos no sabe qué parte puso el programador y cuál el usuario.
Una consulta armada pegando textos
term = "Pen"
query = "SELECT name, price FROM products WHERE name LIKE '%" + term + "%'"
print(query)
# SELECT name, price FROM products WHERE name LIKE '%Pen%'Antes de empezar
Nota
Pulsa Iniciar el laboratorio en la barra superior y espera a que diga que está en marcha. Cada botón Ejecutar escribe su comando en el terminal de la máquina. La tienda se llama app.
Busca un producto normal en la tienda
curl -G --data-urlencode "q=Pen" http://app:8000/searchSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Busca otro producto
curl -G --data-urlencode "q=Mug" http://app:8000/searchSe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Lee la línea que arma la consulta
docker exec app grep LIKE /tmp/app/app.pySe muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.
Un texto puede cambiar la orden
Mira un ejemplo distinto, un formulario de acceso inventado. La web pega el usuario y la clave en la consulta.
Si el usuario escribe unas comillas y dos guiones, los guiones empiezan un comentario en SQL. Todo lo que sigue se ignora, y la comprobación de la clave desaparece.
Ejemplo resuelto: un acceso que se rompe
| Lo que escribe el usuario | Consulta que se arma | Qué pasa |
|---|---|---|
| ana y su clave | WHERE name = 'ana' AND pass = 'x1' | Se comprueba la clave |
| ana' -- | WHERE name = 'ana' --' AND pass = '' | Se ignora la clave |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Parametrizar separa la orden de los datos
En una consulta parametrizada, la orden lleva un hueco, escrito con ?. El dato se envía aparte y la base de datos lo trata siempre como un valor, nunca como una orden.
Aunque el dato traiga comillas o guiones, es solo texto. Por eso es el arreglo que recomiendan todos.
La misma búsqueda, parametrizada
cursor = db.execute(
"SELECT name, price FROM products WHERE name LIKE ?",
("%" + term + "%",),
)
# El ? es el hueco: term viaja aparte, como un dato.Ejemplo resuelto: antes y después
| Forma | Cómo se escribe | Seguridad |
|---|---|---|
| Pegando textos | "... LIKE '%" + term + "%'" | Insegura |
| Parametrizada | "... LIKE ?" y el dato aparte | Segura |
Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.
Un error frecuente
Advertencia
Mucha gente cree que basta con prohibir las comillas. Es un parche frágil: siempre hay otra forma de colar texto. El arreglo de verdad es no mezclar nunca la orden con los datos, y para eso están las consultas parametrizadas.
Para ir más lejos: qué más se protege
Además de parametrizar, una web puede dar a su base de datos una cuenta con pocos permisos. Así, aunque algo falle, esa cuenta no puede leer la tabla de usuarios.
Piensa: ¿qué dos permisos le quitarías a la cuenta de una tienda que solo busca productos?