¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Inyección SQL: texto que cambia una consulta

Después de esta lección: Puedo corregir una consulta para que el texto escrito no pueda cambiarla.

Lección de 55 min3 comandosLaboratorio de inyección SQL: ataca una búsqueda débil, corrige la consulta y demuéstralo

Un buscador que muestra un error

Una tienda pequeña tiene un buscador para su lista de productos. Un visitante escribe una palabra con apóstrofo, como D'Angelo.

La página responde con una línea de palabras raras del servidor. El dueño dice que es un fallo menor. En realidad es una señal: la página deja que el visitante escriba parte de sus preguntas.

La regla única

Advertencia

Este laboratorio es una tienda insegura a propósito. Ataca solo tu copia privada, que no tiene salida a internet. Atacar un sistema que no es tuyo, o que no tienes permiso para probar, es delito en casi todos los países.

Al final de esta lección

Nota

Puedo corregir una consulta para que el texto escrito no pueda cambiarla.

Palabras clave

PalabraQué significaEjemplo
Base de datosalmacén ordenado de registros al que un programa hace preguntas
Consultapregunta que un programa hace a una base de datosSELECT name FROM products
Inyección SQLtexto escrito que cambia la consulta que envía un programa
Parámetrovalor que se envía junto a la consulta y nunca dentro de ella?
Cadenatrozo de texto dentro de un programa"pen"
Entradatodo lo que un visitante escribe o envía a una página

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Una consulta hecha con texto se puede cambiar

Muchos programas montan una consulta pegando un principio fijo y lo que el visitante escribió. La base de datos recibe una sola cadena larga. No sabe qué parte puso quien programó la página y cuál el visitante.

Si el texto del visitante lleva una comilla, puede cerrar antes de tiempo el texto fijo del programa. Lo que viene detrás se lee como parte de la consulta.

La consulta que monta el programa

Código: python
# Cambia term por "Cuaderno" y pulsa Run. Luego prueba "Baker's".
term = "pen"
start = "SELECT name, price FROM products WHERE name LIKE '%"
query = start + term + "%'"
print(query)

Ejemplo resuelto: tres búsquedas

El visitante escribeConsulta que recibe la baseQué ocurre
pen... LIKE '%pen%'Funciona como se pensó
Baker's... LIKE '%Baker's%'La comilla cierra el texto antes de tiempo y la consulta se rompe
x' AND 1=2 --... LIKE '%x' AND 1=2 --%'El visitante añadió una condición propia

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Mira la tienda de tu laboratorio

Tu laboratorio tiene una tienda real con esta debilidad. Arranca el laboratorio y ejecuta estos tres comandos. Solo miran. El primero es una búsqueda normal. El segundo usa un nombre con apóstrofo, que la tienda no sabe manejar. El tercero imprime la línea de código que monta la consulta.

Una búsqueda normal

Comando
curl -s -G --data-urlencode "q=pen" http://app:8000/search

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Un nombre con apóstrofo

Comando
curl -s -G --data-urlencode "q=Baker's" http://app:8000/search

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

La línea que monta la consulta

Comando
docker exec app grep -n "rows = db.execute" /tmp/app/app.py

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Qué te dicen las tres respuestas

El primero imprime Pen 1.2, el nombre y el precio. El segundo imprime una línea que empieza por database error. La tienda metió tu apóstrofo tal cual en su consulta.

El tercero imprime un número de línea y una línea larga de código. Busca los signos +. Cada uno pega texto escrito dentro de la consulta.

Un parámetro deja el texto fuera

Un parámetro lo arregla. El programa envía la consulta con un ? donde va el valor. El texto escrito viaja aparte.

La base de datos lee primero la consulta y fija su forma. El texto llega después y solo puede ser un valor. Ninguna comilla puede cerrar nada.

La misma búsqueda con parámetro

Código: python
import sqlite3
db = sqlite3.connect(":memory:")
db.execute("CREATE TABLE products (name TEXT, price REAL)")
db.execute("INSERT INTO products VALUES (?, ?)", ("Baker's apron", 14.0))
db.execute("INSERT INTO products VALUES (?, ?)", ("Pen", 1.2))
# Cambia term y pulsa Run. Nada de lo que escribas cierra la consulta.
term = "Baker's"
rows = db.execute("SELECT name, price FROM products WHERE name LIKE ?", ("%" + term + "%",)).fetchall()
print(rows)

Un error frecuente

Advertencia

Mucha gente cree que basta con quitar el apóstrofo del texto. No es así. Los filtros se dejan casos, y un caso olvidado es una puerta abierta. El parámetro funciona porque nunca mezcla el texto con la consulta, por ingenioso que sea. Úsalo para cada valor.

Hay partes que no pueden ser parámetros

Un parámetro puede ser un valor. No puede ser el nombre de una columna ni un orden. Una página que deja ordenar por precio o por nombre tiene que escribir esa palabra en la consulta.

La forma segura es una lista corta de palabras permitidas. Si la elección del visitante no está en la lista, se usa una por defecto.

Solo palabras de la lista

Código: python
ALLOWED = ["name", "price"]
# Cambia choice a "price" y luego a "stock; drop", y pulsa Run.
choice = "name"
if choice in ALLOWED:
    column = choice
else:
    column = "name"
print("ORDER BY " + column)

Sobre este laboratorio y su código: Laboratorio de inyección SQL: ataca una búsqueda débil, corrige la consulta y demuéstralo

¿Enseñas a una clase? Asigna este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.