Los ataques con inyección SQL son unos de los más habituales en el mundo web. En este artículo trataremos algunas de las maneras en que se pueden evitar estas peligrosas fallas en la seguridad.
Lo primero es seguir una serie de consejos a nivel de administración, como limitar los permisos del usuario a nivel de base de datos. Por ejemplo, en la mayoría de aplicaciones web lo habitual es que no tenga que utilizarse DROP, por lo que por seguridad sería mejor impedir que el usuario lo haga.
También es recomendable no dar información extra al atacante evitando sacar en pantalla los errores de la base de datos. En ese caso lo ideal es capturar el error haciendo uso de exceptiones.
Importante y recomendable es hacer las validaciones en el lado del servidor pues un atacante puede saltarse fácilmente las validaciones que se hacen con javascript en el lado del cliente sencillamente desactivando javascript en el navegador.
Por último escapar las comillas con msqli_real_scape_string (en caso de que usemos MySQL), pg_scape_string (en caso de PostgreSQL) o addslashes (por si utilizamos otro SGBD). También podemos utilizar htmlentities para convertir los textos en entidades html, como un plus a la seguridad. Abajo un simple ejemplo:
try{ $query = sprintf("SELECT * FROM users WHERE id=%d", mysqli_real_escape_string($id)); $query = htmlentities($query); mysqli_query($query); }catch(Exception $e){ echo('Lo sentimos, ha habido un error en la conexión'); } ?>
Como medida extra se podrían utilizar expresiones regulares para evitar la inserción de ciertas palabras (SELECT, DROP, UNION…).
Pero si todo esto te parece lioso, hay una alternativa: la clase PDO. Dicha clase nos facilitará mucho la vida a la hora de trabajar con bases de datos, ya que nos permite abstraernos del SGDB que estemos utilizando.
Si por ejemplo, en una página donde no utilices PDO o algo similar sino el mysql_connect simple, decides migrar tu web de MySQL a PostgreSQL tendrías que cambiar todos los métodos del conector de MySQL por los métodos de PostgreSQL.
Con PDO bastaría con que cambiaras una sola línea de código, concretamente la de la creación del objeto PDO, y el resto de la aplicación seguiría funcionando.
PDO además te permitirá usar consultas parametrizadas (como los Prepared Statements de java) o realizar transacciones.
En fin, en el enlace de arriba tenéis todo el manual de PDO para estudiarlo si queréis. Ahora vamos con un simple ejemplo de Prepared Statement, para que veáis lo sencillo que es (dando por sentado para el ejemplo que ya hemos creado el objeto PDO, tal cual está explicado en el manual del enlace).
/*preparamos la consulta*/ $prepared_statement >= $pdo->prepare("SELECT name FROM usuarios WHERE id = :id"); /*Le pasamos el parámetro, asociado al parámetro de la consulta y definiendo su tipo (si no, por defecto lo trata como string)*/ $prepared_statement->bindParam(':id', $_GET['id'], PDO::PARAM_INT); /*ejecutamos*/ $prepared_statement->execute(); /*recogemos los resultados, como un array. Se pueden utilizar parámetros para especificar otro tipo de respuesta, como por ejemplo PDO::FETCH_ASSOC para obtener un array asociativo*/ $prepared_statement = $statement->fetch(); ?>
Y con estos breves consejos lograrás que tu página sea más segura. Si utilizas PDO, tendrás menos complicaciones en la seguridad y tu código será más portable.