example4.php?id=id=2-1
Encontré la inyección anterior y no puedo entender por qué (cómo) funciona y lo interesante es que devuelve todos los registros de la base de datos.
¿Algo chicos? educame
Gracias
Ejecuta la consulta WHERE id=id
. Como id
es solo otra columna y en SQL solo puede pasar el nombre de la columna al realizar operaciones de comparación.
Esto indica que se obtengan todas las filas DONDE id
de la fila es igual a id
de la misma fila, lo cual es cierto para todas las filas.
Esto es igual que WHERE 1=1
, básicamente altera la declaración WHERE
de tal manera que siempre es verdadera.
El fragmento inyectado probablemente dé como resultado una consulta similar a esta:
… WHERE id=id=2-1
Dado que MySQL se analiza de izquierda a derecha, lo anterior es equivalente a:
… WHERE (id=id)=2-1
Entonces la expresión id=id
se evalúa primero y devuelve 1
( TRUE
value) para cada fila, ya que cualquier valor que no sea NULL
es equivalente a sí mismo cuando se utiliza el =
operation . Por lo tanto, se puede simplificar a:
… WHERE 1=2-1
Que, por supuesto, se puede simplificar para:
… WHERE 1=1
Y esto, nuevamente, es cierto para cada fila con un valor que no sea NULL
id
.
Con respecto al título: es un malentendido común de que pasar un valor de entrada a través de la función mysql_real_escape_string
hace que sea seguro de usar automáticamente en una declaración SQL . Incluso el manual de PHP afirma que es ambiguo:
Esta función debe usarse siempre (con pocas excepciones) para proteger los datos antes de enviar una consulta a MySQL.
Sin embargo, lo que falta en el manual es que los valores pasados a través de mysql_real_escape_string
solo se deben usar en literales de cadena MySQL y en ninguna otra parte. Desafortunadamente, el manual no aclara ese aspecto importante.
El resultado es que mysql_real_escape_string
también se usa para datos que no están diseñados como un literal de cadena. Como un valor literal diferente, a keyword , o incluso como columna o identificador de tabla .
Del mismo modo, en el caso descrito anteriormente, el valor de entrada no se usa en un literal de cadena, por lo que mysql_real_escape_string
no ayudará. Sin embargo, una declaración preparada, en la que la entrada se pasaría como parámetro, habría ayudado.
Lea otras preguntas en las etiquetas web-application sql-injection