La inyección SQL consiste en insertar código SQL para alterar la base de datos de la página web. Se suele hacer en los formularios de login o en los formularios de alta de usuario o cuando se sabe que se va a interactuar con una base de datos.
Ejemplo:
Supongamos que tenemos un formulario de login donde se pide el nombre de usuario y damos al botón de enviar (o submit) y tenemos la siguiente query en php:
$query = "SELECT * FROM usuarios WHERE nombre = '" .$nombreusuario."';"
Se supone que la variable nombre de usuario contiene el nombre del usuario que se va a logear en nuestra aplicación. Pero alguien malintencionado podría introducir en el formulario otra cosa como por ejemplo juan';DROP TABLE usuarios; SELECT * FROM datos WHERE nombre LIKE '%'; y después de hacer la consulta select borra la tabla de usuarios.
Una solución sencilla sería usar la función mysql_real_escape_string y nos podría evitar muchos problemas. Aquí os pongo un ejemplo:
$prueba1 = mysql_real_escape_string('torrevieja');
$prueba2 = mysql_real_escape_string( "1;DROP TABLE nombre_alojamiento;");
$query = 'SELECT * from alojamiento where nombre_alojamiento = "'.$prueba1.'" and id_owner = '.$prueba2;
echo $query;
$res = mysql_query($query,$con);
var_dump($res);
Se puede observar que la segunda variable contiene un drop table. Al hacer var_dump del resultado de la consulta el resultado es false y si quitamos el drop table el resultado es true.
Pero a partir de PHP 7, hay que evitar la inyeccion de sql de dos maneras:
Evitar inyección de mysql con MYSQLI
//Conexióna la base de datos
$mysqli = new mysqli('127.0.0.1', 'tu_usuario', 'tu_contraseña', 'pruebas');
...
//Con el siguiente codigo se 'prepara' la query para evitar la inyeccion de sql
$stmt = $conn->prepare("INSERT INTO alumnos (nombre, apellid, email) VALUES
(?, ?, ?)");
$stmt->bind_param("sss", $name, $apellido, $email);
$firstname = 'Juan';
$lastname = 'Pérez';
$email = 'juan@examplo.com';
$stmt->execute();
$firstname = 'Ana';
$lastname = 'López';
$email = 'Ana@examplo.com';
$stmt->execute();
$firstname = 'Pedro';
$lastname = 'Sandoval';
$email = 'Pedro@examplo.com';
$stmt->execute();
echo 'Los datos se han guardado correctamente';
$stmt->close();
$conn->close();
En la sentencia "insert" hay tres "s" que coincide con el número de valores que se van a insertar: nombre, apellido y email y la "s" quiere decir que se va a introducir un string, en este caso 3.
Lista de caracteres a poner según el tipo de valor
- i - integer
- d - double
- s - string
- b - BLOB
Evitar inyección de mysql con PDO
$conn = new PDO("mysql:host=127.0.0.1;dbname=pruebas", 'tu_usuario', 'tu_contraseña');
$stmt = $conn->prepare("INSERT INTO alumnos(nombre, apellido, email)
VALUES (:nombre, :apellido, :email)");
$stmt->bindParam(':nombre', $nombre);
$stmt->bindParam(':apellido', $apellido);
$stmt->bindParam(':email', $email);
$firstname = 'Ana';
$lastname = 'López';
$email = 'Ana@examplo.com';
$stmt->execute();
$firstname = 'Pedro';
$lastname = 'Sandoval';
$email = 'Pedro@examplo.com';
echo 'Los datos se han guardado correctamente';
$conn = null;
Como se peude ver evitar la inyecciónd e sql es sencillo y fácil y puede ahorrar varios disgustos.