7

Entiendo que las declaraciones preparadas son la mejor manera de buscar protección contra la inyección de SQL. Sin embargo, brindan cobertura de manera limitada; por ejemplo, en los casos en que dejo que el usuario decida cómo será el orden por operación (es decir, ¿es ASC o DESC? etc.), no obtengo cobertura allí con las declaraciones preparadas.PHP: usando declaraciones preparadas y protegiendo contra la inyección de SQL frente a escape

Entiendo que puedo asignar la entrada del usuario a una lista blanca predefinida para eso. Pero esto solo es posible cuando se puede crear o adivinar una lista blanca de antemano.

Por ejemplo, en los casos que mencioné anteriormente (el ASC o DESC), esto se puede mapear y verificar fácilmente contra una lista de valores aceptados. Pero, ¿no hay una situación en la que la parte de la declaración SQL no puede verificarse contra una lista blanca?

Si tal situación existe, ¿cuál es el enfoque recomendado?

Si tuviera que escapar el user_input utilizando la utilidad de escape integrada de la base de datos subyacente (como mysqL_real_escape_string para mysql) en general, ¿dónde fallaría?

que estoy haciendo esta pregunta con la suposición de que siempre construyo mis sentencias SQL con valores citados - incluso para los números enteros ...

Vamos a echar un vistazo al siguiente ejemplo y reflexionar sobre ella ..

select {$fields} from {$table} where Age='{$age}' order by {$orderby_pref} 

Supongamos que todos los vars son proporcionados por el usuario.

Si fuera a mysql_real_escape_string todas las variables en el SQL anterior (en lugar de usar declaraciones preparadas que me cubren solo a mitad de camino forzándome a subir a listas blancas para la otra mitad que no puede ayudar), ¿no sería así? ser igualmente seguro (y más fácil de codificar)? De lo contrario, ¿en qué escenario de entrada fallaría la utilidad de escape?

$fields  = mysql_escape($fields); 
$table  = mysql_escape($table); 
$age   = mysql_escape($age); 
$orderby_pref = mysql_escape($orderby_pref); 

select {$fields} from {$table} where Age='{$age}' order by {$orderby_pref} 
+2

Subida vertida porque ya conoce y se preocupa por las inyecciones sql (en oposición a la mayoría de las personas que formulan preguntas aquí en la etiqueta PHP) – Mahn

+0

Existe una diferencia entre el SQL dinámico y la adición de valores en las consultas. Ambos parámetros vinculados o la concatenación de cadenas (más el escape) podrían usarse para agregar valores. SQL dinámico requiere una lista blanca de sintaxis aceptable. Entonces, use una expresión regular, un mapa o una declaración de cambio para agregar 'DESC' o' ORDER' y otros calificadores. Sin embargo, los procedimientos almacenados serían una alternativa larga. – mario

Respuesta

3

Siempre necesita utilizar listas blancas para cosas como nombres de tabla o columna, ya sea que use declaraciones preparadas o las funciones de escape mysql. El problema es que los nombres de tabla y columna no se entre comillas simples o dobles, por lo que si utiliza una función que cita específicamente estos caracteres (y algunos más, por supuesto, ...), no hará nada por su nombre de la tabla.

Considere el nombre de la tabla my_table; DELETE * FROM mysql; SELECT * FROM my_table. No se escapará nada en esta cadena de las funciones de escape de mysql, pero definitivamente es una cadena que le gustaría verificar en una lista blanca.

Aparte de eso, las funciones de escape mysql tienen un problema con los juegos de caracteres que pueden inutilizarlos, por lo que siempre estará mejor con las declaraciones preparadas.

+2

SU EJEMPLO DE 'my_table; ELIMINAR * FROM mysql; SELECT * FROM my_table' LO CLAVE MUY BIEN POR QUÉ EL ENFOQUE MYSQL_ESCAPE FALLARÍA ... Por lo tanto, en términos simples y simples, la única alternativa para la protección de inyección SQL (para las partes donde las declaraciones preparadas o los db's la utilidad de escape no ayuda), es usar el enfoque de lista blanca. ¿Es esta conclusión correcta? –

+0

@ Average Joe Eso es correcto. – jeroen

+0

+1 por sugerir un enfoque de lista blanca – Mahn

3

Usted podría utilizar DOP y su vida será más fácil ...:

# Order 
    switch(strtoupper($Order)){ 
     default: 
     case 'ASC': 
      $Order = 'ASC'; 
      break; 

     case 'DESC': 
      $Order = 'DESC'; 
      break; 
    } 

    # ID 
    $ID = 39; 
    $Username = 'David'; 

    # Query 
    $Query = $this->DB->Main->prepare('SELECT * FROM Table WHERE ID = :ID AND Username = :Username ORDER BY HellBob '.$Order); 
    $Query->bindValue(':ID', $ID, PDO::PARAM_INT); 
    $Query->bindValue(':Username', $Username, PDO::PARAM_STR); 

    # All good ? 
    if(!$Query->execute()){ 
     exit('Error'); 
    } 

    // Results 
    $Row = $Query->fetch(PDO::FETCH_ASSOC); 

Usted no tiene que preocuparse acerca de citas o las inyecciones SQL. Puedes usar una simple "lista blanca" como mencionas para obtener variables en tu consulta.

+1

ha olvidado el campo de pedido ;-) – Waygood

+0

@Waygood Oups. Gracias. ¿La actualización? –

+1

Esto realmente no responde la pregunta ya que ha codificado el nombre de la tabla, los nombres de columna y la columna de orden de clasificación en la consulta. – jeroen

Cuestiones relacionadas