2009-08-21 21 views
34

Empecé a usar declaraciones preparadas por PDO no hace mucho tiempo, y, según tengo entendido, hace todo el escape/seguridad para usted.cuán seguras son las declaraciones preparadas por PDO

por ejemplo, suponiendo que $ _POST ['title'] es un campo de formulario.

$title = $_POST['title']; 
$query = "insert into blog(userID, title) values (?, ?)" 
$st = $sql->prepare($query); 
$st->bindParam(1, $_SESSION['user']['userID'], PDO::PARAM_INT); 
$st->bindParam(2, $title); 
$st->execute(); 

¿Es esto realmente seguro? ¿Tengo que hacer algo más? ¿Qué más tengo que tomar en consideración?

Gracias.

Respuesta

66

Estrictamente hablando, en realidad no se necesita escaparse, porque el valor del parámetro nunca se interpola en la cadena de consulta.

La manera en que funcionan los parámetros de consulta es que la consulta se envía al servidor de la base de datos cuando llamó a prepare(), y los valores de los parámetros se envían más tarde, cuando llamó al execute(). Por lo tanto, se mantienen separados de la forma textual de la consulta. Nunca hay una oportunidad para inyección SQL (siempre que PDO::ATTR_EMULATE_PREPARES sea falso).

Así que sí, los parámetros de consulta lo ayudan a evitar esa forma de vulnerabilidad de seguridad.

¿Son 100% de protección contra cualquier vulnerabilidad de seguridad? No claro que no. Como sabrá, un parámetro de consulta solo ocupa el lugar de un único valor literal en una expresión SQL. No se puede hacer una única sustitución de parámetros para una lista de valores, por ejemplo:

SELECT * FROM blog WHERE userid IN (?); 

No se puede utilizar un parámetro para que los nombres de tabla o nombres de columna dinámicos:

SELECT * FROM blog ORDER BY ?; 

Puede 't utilizar un parámetro para cualquier otro tipo de sintaxis SQL:

SELECT EXTRACT(? FROM datetime_column) AS variable_datetime_element FROM blog; 

por lo que hay un buen número de casos en los que hay que manipular la consulta como una cadena, antes de la llamada prepare(). En estos casos, aún necesita escribir el código cuidadosamente para evitar la inyección de SQL.

+2

esto fue muy buena información. ¡gracias! – sqram

+0

También 'LIKE?' Es válido, pero debe escapar de los caracteres utilizados para la coincidencia. –

+0

Con respecto a "Nunca hay una oportunidad para la inyección SQL (siempre que PDO :: ATTR_EMULATE_PREPARES sea falso).", ¿Significa esto que las preparaciones emuladas con PDO NO son tan seguras como las preparaciones nativas del controlador db? Si es así, ¿por qué? –

2

En cuanto a las inyecciones de SQL, creo que es lo más seguro que puede obtener, especialmente si utiliza constantes como PDO :: PARAM_INT.

+6

Este 'especial' necesita alguna aclaración IMO. Probablemente no quieras decir que es 95% seguro, pero si usas las constantes, es 100% seguro. Si no hay constantes, no es 100% seguro, no es seguro.Si es 100%, entonces no es 'especialmente' seguro con constantes. ¿Cuál es la diferencia de seguridad entre usar las constantes y no usarlas? – koen

9

Es seguro desde la inyección de SQL.

Un par de cosas que no es seguro desde:

  • Denegación de servicio (que causa una cantidad excesiva de filas que se creen)
  • ataques entre sitios mediante secuencias de comandos (si el título está cada vez se hizo eco de nuevo a otro usuario)

La seguridad es más que la prevención de la inyección SQL.

+0

por favor contribuya. ¿A qué te refieres si el título se repite a otro usuario? – sqram

+3

Supongamos que tiene el título de las publicaciones de blog almacenadas en una base de datos, y otros usuarios pueden ver estas publicaciones. Luego hay un posible ataque de secuencias de comandos entre sitios en el que un usuario malintencionado puede crear un título que incluya HTML para insertar un script malicioso en la página tal como se muestra a otros usuarios de su sitio. – Yuliy

Cuestiones relacionadas