En este tutorial os contamos cómo evitar uno de los ataques mas frecuentes de los hackers: La inyección SQL.
Os vamos a mostrar 3 scripts de PHP que nos van a permitir conocer la forma en que podemos evitar una inyección SQL por parte de posibles atacantes.
Para ello revisemos primero este primer script y analicemos
<?php $query = "SELECT * FROM users WHERE name = '{$_GET['name']}'"; ?>
Este script puede ser fácilmente vulnerable porque directamente agrega el valor de la variable ‘name’ a la sentencia SQL. Como puede ver permite para que el atacante agregue lo que desee y pueda comprometer nuestros datos.
Otra opción, aunque no muy recomendable sería la que se muestra debajo. En esta opción primero se verifica que los caracteres de la variable ‘name’ sean numéricos, luego se escapan los caracteres especiales haciendo uso de la función de php llamada mysql_real_escape_string. Por último se construye la sentencia SQL haciendo uso de los datos ya tratados previamente.
<?php // Inicializar arreglos para datos filtrados y escapados, respectivamente. $clean = array(); $sql = array(); // Filtra el nombre. Solo caracteres alfabéticos. if (ctype_alpha($_GET['name'])) { $clean['name'] = $_GET['name']; } else { // El nombre es inválido. Se debe tomar una acción aquí. } // Escapar el nombre $sql['name'] = mysql_real_escape_string($clean['name']); // Construir la consulta $query = "SELECT * FROM users WHERE name = '{$sql['name']}'"; ?>
La última opción –la preferida– se muestra debajo. En ella simplemente se transfiere a PHP y MySQL la tarea de verificar la sentencia SQL. Se hace uso del método prepare de la clase PDO para preparar la sentencia y de execute para ejecutarla. Notemos el uso de los dos puntos antes de ‘name’ en la preparación de la sentencia y en la ejecución de la misma. Estos son requisitos que no podemos omitir.
<?php // Creando el formato de la consulta $query = $db->prepare('SELECT * FROM users WHERE name = :name'); // Indicando los datos $query->execute(array(':name' => $clean['name'])); ?>
10 Comments
Me gustaría saber porque la opción numero 2 no es muy recomendada?
Hola German, la segunda opción no es recomendable porque nosotros mismos debemos agregar a mano cada una de los filtros a los datos obtenidos mediante GET. Si olvidamos filtros podríamos hacer vulnerable el script poniendo en riesgo la seguridad de nuestra aplicación. La tercera opción, en cambio, es menos engorrosa y deja todo el trabajo pesado a PHP.
Gracias por escribirnos.
Les ayudo con la que yo utilizo que me va de lujo…
function securitymax($valores) {
$_Cadena = htmlspecialchars(trim(addslashes(stripslashes(strip_tags($valores)))));
$_Cadena = str_replace(chr(160),”,$valores);
return mysql_real_escape_string($valores);
}
$minurl = $_GET[‘id2’];
$minurla = str_replace(“‘”, “”, $minurl);
$minurlb = str_replace(“;”, “”, $minurla);
$minurlokc = str_replace(“\””, “”, $minurlb);
$minurlok = securitymax($minurlokc);
Donde “$newurlok” es la variable completamente saneada
Al final quise decir:
Donde “$minurlok” es la variable completamente saneada
Una consulta
en
$_Cadena = htmlspecialchars(trim(addslashes(stripslashes(strip_tags($valores)))));
$_Cadena = str_replace(chr(160),”,$valores);
no seria
$_Cadena = htmlspecialchars(trim(addslashes(stripslashes(strip_tags($valores)))));
$_Cadena = str_replace(chr(160),”,$_Cadena);
gracias por la información
a mi me queda una duda… Con las consultas preparadas de PDO, se debe utilizar addslashes y mysql_real_escape_string de todas formas? o solo con preparar la consulta, y hacer los bind a la consulta ya esta la seguridad?
Muchísimas gracias.
no seria mejor una consulta preparada para mi es la mejor forma ya que esta preparada para esta ocacion
alguien podria ayudarme a cambiar este codigo mysqli a PDO
escape_string($_POST[‘datepicker’]);
$new_date = date(‘Y-m-d’,strtotime($date));
$equipo = $mysqli->escape_string( trim($_POST[‘bien’]));
$marca = $mysqli->escape_string( trim($_POST[‘marca’]));
$modelo = $mysqli->escape_string( trim($_POST[‘modelo’]));
$serie = $mysqli->escape_string( trim($_POST[‘serie’]));
$sql = “INSERT INTO equipo_inf(fecha_registro, nomb_equipo, marca_equi, modelo_equi, serie_equi)
VALUES (‘$new_date’,’$equipo’, ‘$marca’, ‘$modelo’, ‘$serie’)”;
if($mysqli->query($sql)){
header(‘Location: registronuevo.php’);
}else die($mysqli->error);
?>
yo lo unico que utiliz es esto jajaaj
$id=intval($_GET[‘id’]);
y listo