Protección contra SQL Injection
En esta página
El SQL injection ocurre cuando un valor externo es concatenado en la cadena
de la query antes de llegar a la base de datos. Al usar sql"...", Zolo nunca
concatena: toda interpolación {expr} se convierte en un ? posicional y el
valor se envía por separado a través del driver. La base de datos recibe la
estructura de la query por un canal y los datos por otro — los metacaracteres SQL
en el valor se tratan como texto, no como código.
El payload clásico '; DROP TABLE users; -- se inserta como variable en una
query sql"...". La tabla permanece intacta y no se encuentra ninguna fila.
// Feature: `sql"..."` interpolations are *bound parameters*, not concatenated
// Syntax: `sql"SELECT ... WHERE x = {evil}"` — at compile time the
// `{evil}` becomes `?` and the value is sent as a parameter. SQL
// metacharacters in the value are literal, not parsed.
// When to use: ALWAYS. Never build queries with `+` or interpolation
// outside `sql"..."`. This file demonstrates why.
use std::database::Database
let db = Database.open("sqlite://:memory:")?
defer db.close()
db.execute(sql"CREATE TABLE users (name TEXT)")?
db.execute(sql"INSERT INTO users VALUES ('alice')")?
db.execute(sql"INSERT INTO users VALUES ('bob')")?
// The classic injection payload — in a string-concat builder it
// would terminate the query, drop the table, and comment out the rest.
// Inside `sql"..."` it's just a string parameter that doesn't match.
let evil = "'; DROP TABLE users; --"
let rows = sql"SELECT name FROM users WHERE name = {evil}".query(db)?
var count = 0
for _ in rows { count = count + 1 }
print("matched: {count}")
// expected: matched: 0
// Proof: the table is still there, both rows intact.
let total = sql"SELECT COUNT(*) FROM users".scalar(db)?
print("total: {total}")
// expected: total: 2
db.query("SELECT * FROM users") ?> .each(|u| print(u.name))
Requiere la CLI o el host de Zolo; ábrelo en el playground o ejecútalo localmente.
La regla práctica es simple:
- Usa
sql"..."(o?+ bindings) siempre que un valor provenga de fuera del código fuente. - Nunca construyas queries con
+ni con interpolación fuera del literalsql"...".
Desafío
Intenta construir la misma query sin sql"..." usando concatenación de cadenas
y observa qué ocurre con la tabla. ¿Qué mensaje de error emite Zolo?
Consulta también