[php] ¿Las declaraciones preparadas por PDO son suficientes para evitar la inyección de SQL?



Answers

Las declaraciones preparadas / consultas parametrizadas son generalmente suficientes para evitar la inyección de primer orden en esa declaración * . Si usa sql dinámico sin marcar en cualquier otro lugar de su aplicación, aún es vulnerable a la inyección de segundo orden .

La inyección de segundo orden significa que los datos se han ciclado a través de la base de datos una vez antes de ser incluidos en una consulta, y es mucho más difícil de lograr. AFAIK, casi nunca se ven verdaderos ataques de segundo orden diseñados, ya que generalmente es más fácil para los atacantes hacer ingeniería social, pero a veces surgen errores de segundo orden debido a caracteres extra benignos o similares.

Puede realizar un ataque de inyección de segundo orden cuando puede hacer que un valor se almacene en una base de datos que luego se utiliza como un literal en una consulta. Como ejemplo, digamos que ingrese la siguiente información como su nuevo nombre de usuario al crear una cuenta en un sitio web (asumiendo MySQL DB para esta pregunta):

' + (SELECT UserName + '_' + Password FROM Users LIMIT 1) + '

Si no hay otras restricciones en el nombre de usuario, una declaración preparada aún se aseguraría de que la consulta incrustada anterior no se ejecute en el momento de la inserción y almacene el valor correctamente en la base de datos. Sin embargo, imagine que más tarde la aplicación recupera su nombre de usuario de la base de datos y utiliza la concatenación de cadenas para incluir ese valor en una nueva consulta. Es posible que vea la contraseña de otra persona. Dado que los primeros nombres en la tabla de usuarios tienden a ser administradores, es posible que también haya regalado la granja. (También tenga en cuenta: ¡esta es una razón más para no almacenar contraseñas en texto plano!)

Vemos, entonces, que las declaraciones preparadas son suficientes para una sola consulta, pero por sí mismas no son suficientes para proteger contra ataques de inyección SQL en toda una aplicación, ya que carecen de un mecanismo para exigir que todo acceso a una base de datos dentro de la aplicación código seguro Sin embargo, se usa como parte del buen diseño de la aplicación, que puede incluir prácticas como la revisión del código o el análisis estático, o el uso de un ORM, capa de datos o capa de servicio que limite las sentencias preparadas en sql dinámico, son la herramienta principal para resolver la inyección Sql problema. Si sigue los buenos principios de diseño de la aplicación, de forma que su acceso a los datos esté separado del resto de su programa, será fácil imponer o auditar que cada consulta utilice correctamente la parametrización. En este caso, la inyección sql (tanto de primer como de segundo orden) se evita por completo.

* Resulta que MySql / PHP son (está bien, fueron) simplemente tontos sobre el manejo de parámetros cuando se trata de caracteres anchos, y todavía hay un caso raro descrito en la otra respuesta altamente votada aquí que puede permitir que la inyección se deslice a través de un parámetro consulta.

Question

Digamos que tengo un código como este:

$dbh = new PDO("blahblah");

$stmt = $dbh->prepare('SELECT * FROM users where username = :username');
$stmt->execute( array(':username' => $_REQUEST['username']) );

La documentación de PDO dice:

Los parámetros para las declaraciones preparadas no necesitan ser citados; el conductor lo maneja por ti.

¿Es eso realmente todo lo que debo hacer para evitar las inyecciones de SQL? ¿Es realmente así de fácil?

Puede asumir MySQL si hace una diferencia. Además, realmente siento curiosidad sobre el uso de declaraciones preparadas contra la inyección de SQL. En este contexto, no me preocupan las XSS u otras posibles vulnerabilidades.




Sí, es suficiente. La forma en que funcionan los ataques tipo inyección, es de alguna manera obtener un intérprete (La base de datos) para evaluar algo, que debería haber sido datos, como si fuera un código. Esto solo es posible si combina el código y los datos en el mismo medio (por ejemplo, cuando construye una consulta como una cadena).

Las consultas parametrizadas funcionan enviando el código y los datos por separado, por lo que nunca será posible encontrar un agujero en eso.

Sin embargo, aún puedes ser vulnerable a otros ataques tipo inyección. Por ejemplo, si usa los datos en una página HTML, podría estar sujeto a ataques de tipo XSS.




Personalmente siempre ejecutaría alguna forma de desinfección de los datos, ya que nunca se puede confiar en los datos del usuario; sin embargo, cuando se usan marcadores de posición / enlace de parámetros, los datos ingresados ​​se envían al servidor por separado a la declaración sql y luego se combinan. La clave aquí es que esto vincula los datos proporcionados a un tipo específico y un uso específico y elimina cualquier oportunidad de cambiar la lógica de la declaración SQL.






Links