¿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

Cuando el texto escrito se ejecuta (inyección, XSS)

Después de esta lección: Puedo explicar cómo funcionan la inyección y el cross-site scripting.

Lección de 50 minSin comandos

Un buscador que dice demasiado

Una tienda online de Sevilla tiene un buscador de pedidos. Escribes tu nombre y ves tus pedidos.

Un día alguien escribe un texto raro con comillas. De repente ve los pedidos de todos los clientes.

El fallo no está en la base de datos. Está en cómo el programa mezcla lo que escribe el usuario con su propio código.

Al final de esta lección

Nota

Puedo explicar cómo funcionan la inyección y el cross-site scripting.

Palabras clave

PalabraQué significaEjemplo
Entradalo que escribe o envía el usuario
Inyección SQLentrada que se cuela como parte de una consulta
Consulta con parámetrosconsulta que lleva la entrada aparte, nunca pegadaWHERE customer = ?
Cross-site scriptingentrada que el navegador ejecuta como códigoXSS
Escaparcambiar caracteres especiales para que se lean como texto

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

En una inyección, la entrada se vuelve código

Muchos programas construyen una consulta SQL pegando lo que escribe el usuario. Si alguien escribe comillas y un trozo de SQL, la base de datos lo ejecuta como parte de la consulta.

Con OR '1'='1', la condición es verdadera para todas las filas. Así salen datos de otros clientes.

La defensa es una consulta con parámetros. La entrada viaja aparte y nunca se mezcla con el código.

Prueba: pegar frente a usar un parámetro

Código: python
import sqlite3

db = sqlite3.connect(":memory:")
db.execute("CREATE TABLE orders (customer TEXT, total REAL)")
db.execute("INSERT INTO orders VALUES ('ana', 35.5), ('luis', 120.0)")

# Lo que escribe alguien en el buscador de pedidos
typed = "ana' OR '1'='1"

# MAL: el texto se pega dentro de la consulta
query = "SELECT * FROM orders WHERE customer = '" + typed + "'"
print(query)
print("Pegando el texto:", db.execute(query).fetchall())

# BIEN: el texto va aparte, como un parámetro
safe = "SELECT * FROM orders WHERE customer = ?"
print("Con parámetro:", db.execute(safe, (typed,)).fetchall())

# Cambia typed por "ana" y vuelve a ejecutar.

En un XSS, el navegador ejecuta la entrada

El cross-site scripting, o XSS, pasa en la página web y no en la base de datos.

Alguien deja una reseña con una etiqueta <script>. Si la web la muestra tal cual, el navegador de cada visitante ejecuta ese código. Puede robar su sesión.

La defensa es escapar la entrada antes de mostrarla. Así < se convierte en &lt; y se ve como texto.

Prueba: escapar una reseña

Código: python
import html

# Una reseña que alguien deja en la web de un restaurante
review = "Muy rico <script>alert('hola')</script>"

# MAL: la reseña se mete tal cual en la página
print("<p>" + review + "</p>")

# BIEN: los caracteres especiales se escapan antes
print("<p>" + html.escape(review) + "</p>")

# Escribe una reseña con <b>negrita</b> y mira qué sale.

Ejemplo: los dos ataques lado a lado

AspectoInyección SQLCross-site scripting
Dónde ocurreEn la base de datosEn el navegador
Qué entraUn trozo de SQLUna etiqueta script
Qué se pierdeDatos de otros clientesSesiones de visitantes
DefensaConsulta con parámetrosEscapar al mostrar

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

Un error frecuente

Advertencia

Mucha gente cree que basta con revisar la entrada en el navegador. Cualquiera puede saltarse el navegador y enviar la petición directamente. Usa parámetros y escapa siempre en el servidor, porque es la única parte que controlas tú.

¿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.