2010-08-14 26 views
5

PHP:SQL-injection: ¿es seguro (oneliner)?

 
$SQL = "SELECT goodies FROM stash WHERE secret='" . 
    str_replace("'",'',$_POST['secret']) . 
"'"; 

Podría un hacker mal genio inyectar SQL en mi SELECT - ¿Cómo?

+4

Aún puede obtener una declaración inválida cuando el valor contiene un '\' al final que escapará del '' 'de cierre. – Gumbo

+3

+1: pregunta interesante. Pero independientemente de si se ha demostrado que es seguro o no, aún así no lo recomendaría. :) –

+0

Un error está bien, siempre y cuando no afecte a los usuarios honestos. – T4NK3R

Respuesta

6

que he tenido un pensar en esto por un tiempo y no puedo ver ninguna manera de inyectar SQL en esta declaración.

Una cadena de SQL que comienza con comillas simples termina en la siguiente comilla simple a menos que se escape con una barra diagonal inversa u otra cita (\' o ''). Como está eliminando todas las comillas simples, no puede haber una comilla doble. Si escapa de la cita de cierre obtendrá un error, pero no inyección de SQL.

Sin embargo, este método tiene una serie de inconvenientes:

  • Las comillas simples en la entrada se ignoran.
  • Las barras diagonales inversas en la entrada no se manejan correctamente; se tratarán como códigos de escape.
  • Obtiene un error si el último carácter es una barra diagonal inversa.
  • Si luego amplía la consulta para agregar un segundo parámetro, sería permitir un ataque de inyección SQL.

Por ejemplo:

$SQL = "SELECT goodies FROM stash WHERE secret='" . 
    str_replace("'",'',$_POST['secret']) . 
"' AND secret2 = '" . 
    str_replace("'",'',$_POST['secret2']) . 
"'"; 

Cuando se llama con parámetros \ y OR 1 = 1 -- resultaría en:

SELECT goodies FROM stash WHERE secret='\' AND secret2=' OR 1 = 1 -- ' 

Qué MySQL vería como algo parecido a esto:

SELECT goodies FROM stash WHERE secret='...' OR 1 = 1 

Incluso si es imposible Es posible causar una inyección, en este caso los inconvenientes hacen que esto no sea adecuado para una forma general de evitar la inyección de SQL.

La solución, como ya se señaló, es usar una declaración preparada. Esta es la forma más confiable de prevenir ataques de inyección SQL.

+0

Vaya, hago eso (¡mucho!). Pero cambiar el str_replace por mysql_real_escape_string ($ _ POST ['secret']) lo curaría (Y la posibilidad de causar un error)? – T4NK3R

+0

@ T4NK3R: Haz mucho, hay un caso muy raro donde mysql_real_escape_string no funciona correctamente: http://ilia.ws/archives/103-mysql_real_escape_string-versus-Prepared- Statements.html. Estado preparado es la mejor manera, pero mysql_real_escape_string debería funcionar también si se hace correctamente. –

+0

Hacer: agregar pares adicionales de clave = valor (en su mayoría enteros aunque "endurecidos" por moldes simples (int)). Por cierto: mi fuente php está en UTF-8 y también en dbConnection (mysql_set_charset ('utf8', $ dbCon);) - Apagado para leer su enlace ahora! – T4NK3R

14

¿Por qué no usará mysql_real_escape_string() o incluso mejor - declaraciones preparadas? Tu solución parece tonta.

+9

+1 para la declaración preparada. –

+0

secundado ... especialmente para declaraciones preparadas – prodigitalson

+0

Estoy tratando de mantenerlo lo más "lo más" posible ... – T4NK3R

-1

¿Por qué simplemente no usa mysql_escape_string? Y sí, podría, agregando " en lugar de ' y además, esta consulta le dará un error, supongo.

+0

Un error está bien, siempre y cuando no afecte a los usuarios honestos. – T4NK3R

+0

Creo que la consulta 'SELECT goodies FROM stash WHERE secret = '"' 'no es un problema. La comilla doble no terminará la cadena. ¿A qué tipo de error hace referencia? –

0

Puede ser. La mejor manera es:

$query = sprintf("SELECT goodies FROM stash WHERE secret='%s'", 
addcslashes(mysql_real_escape_string($_POST['secret']),'%_')); 
+0

No necesita para escapar '%' y '_' ya que no está usando' LIKE'. – Gumbo

+0

Sí, la función addcslashes es opcional – barroco

+0

Estoy construyendo el enunciado dinámicamente (para una búsqueda con muchas opciones), así que preferiría mantener cada par clave-valor juntos, construyendo la declaración en una cadena a medida que avanzo. – T4NK3R