Hacer htmlspecialchars y mysql_real_escape_string mantener mi código PHP seguro de inyección?

StackOverflow https://stackoverflow.com/questions/110575

Pregunta

Temprano el día de hoy una pregunta con respecto a la entrada estrategias de validación en las aplicaciones web.

La respuesta, en el momento de la escritura, sugiere en PHP sólo el uso de htmlspecialchars y mysql_real_escape_string.

Mi pregunta es:Es esto suficiente?Es más, deberíamos saber?Donde se hacen estas funciones se descomponen?

¿Fue útil?

Solución

Cuando se trata de consultas de base de datos, siempre y preparado parametrizar las consultas.El mysqli y PDO las bibliotecas de soporte de este.Esto es infinitamente más seguro que el uso de escapar de funciones tales como mysql_real_escape_string.

Sí, mysql_real_escape_string efectivamente es sólo una cadena de escapar de la función.No es una bala mágica.Todo lo que va a hacer es escapar de la peligrosa caracteres con el fin de que puedan ser seguros para su uso en una sola cadena de consulta.Sin embargo, si no se desinfectan las entradas de antemano, entonces usted va a ser vulnerables a ciertos vectores de ataque.

Imagine el siguiente SQL:

$result = "SELECT fields FROM table WHERE id = ".mysql_real_escape_string($_POST['id']);

Usted debe ser capaz de ver que este es vulnerable a explotar.
Imaginar el id parámetro contenía el común de ataque:

1 OR 1=1

No hay arriesgado caracteres para la codificación, por lo que se pasa directamente a través de la escape filtro.Lo que nos deja:

SELECT fields FROM table WHERE id= 1 OR 1=1

Es un hermoso inyección de SQL vector y permitiría al atacante para devolver todas las filas.O

1 or is_admin=1 order by id limit 1

que produce

SELECT fields FROM table WHERE id=1 or is_admin=1 order by id limit 1

Que permite al atacante para devolver el primer administrador de detalles, en este ejemplo ficticio.

Aunque estas funciones son útiles, deben ser utilizados con cuidado.Usted necesita asegurarse de que todas las entradas son validados en algún grado.En este caso, vemos que puede ser explotado porque ya no podemos comprobar que una variable que se utiliza como un número, era en realidad numérica.En PHP se debe utilizar ampliamente un conjunto de funciones para comprobar que las entradas son números enteros, flotantes, alfanuméricos, etc.Pero cuando se trata de SQL, prestar atención a más el valor de la declaración preparada.El código anterior habría sido segura si era una declaración preparada como las funciones de base de datos habría sabido que 1 OR 1=1 no es válido literal.

Como para htmlspecialchars().Ese es un campo minado de su propio.

Hay un problema real en PHP, que tiene toda una selección de diferentes relacionados con html escapar de funciones, y no hay una orientación clara sobre exactamente qué funciones a hacer qué.

En primer lugar, si está dentro de una etiqueta HTML, usted está en serios problemas.Mira

echo '<img src= "' . htmlspecialchars($_GET['imagesrc']) . '" />';

Ya estamos dentro de una etiqueta HTML, por lo que no necesitamos < o > para hacer algo peligroso.Nuestro vector de ataque podría ser javascript:alert(document.cookie)

Ahora HTML resultante se parece a

<img src= "javascript:alert(document.cookie)" />

El ataque va directamente a través de.

Se pone peor.Por qué?porque htmlspecialchars (cuando se llama de esta manera) sólo codifica comillas y no de una sola.Así que si hemos tenido

echo "<img src= '" . htmlspecialchars($_GET['imagesrc']) . ". />";

Nuestro mal atacante puede ahora inyectar toda la nueva parámetros

pic.png' onclick='location.href=xxx' onmouseover='...

nos da

<img src='pic.png' onclick='location.href=xxx' onmouseover='...' />

En estos casos, no hay una varita mágica, sólo tienes que santise la entrada a ti mismo.Si usted intenta y filtrar los malos caracteres seguramente va a fallar.Tome una lista blanca de enfoque y dejar sólo a través de los caracteres que son buenas.Mira el XSS hoja de trucos para ejemplos sobre cómo diversos vectores pueden ser

Incluso si usted lo usa htmlspecialchars($string) fuera de las etiquetas HTML, siguen siendo vulnerables a la multi-byte charset vectores de ataque.

Lo más efectivo que se puede es utilizar la combinación de mb_convert_encoding y htmlentities de la siguiente manera.

$str = mb_convert_encoding($str, 'UTF-8', 'UTF-8');
$str = htmlentities($str, ENT_QUOTES, 'UTF-8');

Incluso esto deja IE6 vulnerables, debido a la forma en que maneja la UTF.Sin embargo, podría recurrir a una forma más limitada de codificación, tales como ISO-8859-1, hasta el uso de IE6 se cae.

Para un estudio más profundo a la multibyte problemas, ver https://stackoverflow.com/a/12118602/1820

Otros consejos

Además Cheekysoft excelente respuesta:

  • Sí, que te mantendrá a salvo, pero sólo si se utilizan absolutamente correcto.Utiliza correctamente y usted seguirá siendo vulnerable, y pueden tener otros problemas (por ejemplo la corrupción de datos)
  • Por favor utilice parametrizar las consultas en lugar de (como se declaró anteriormente).Usted las puede utilizar por ejemplo, a través dePDO o a través de un contenedor como PEAR DB
  • Asegúrese de que magic_quotes_gpc y magic_quotes_runtime están apagados en todo momento, y nunca se enciende accidentalmente, ni siquiera brevemente.Estos son uno de los primeros y profundamente errado intento por parte de los desarrolladores de PHP para evitar problemas de seguridad (que destruye los datos)

Realmente no hay una bala de plata para prevenir la inyección de código HTML (por ejemplo,cross site scripting), pero usted puede ser capaz de lograr más fácilmente si usted está utilizando una biblioteca o un sistema de plantillas para la salida de HTML.Lea la documentación para que, por la manera de escapar de las cosas adecuadamente.

En HTML, las cosas necesitan ser escapado de forma diferente dependiendo del contexto.Esto es especialmente cierto de las cadenas de caracteres que se coloca en Javascript.

Definitivamente, me gustaría estar de acuerdo con los anteriores posts, pero tengo una pequeña cosa para agregar en respuesta a Cheekysoft la respuesta, específicamente:

Cuando se trata de consultas de base de datos, siempre trate y el uso de preparados parametrizar las consultas.El mysqli y PDO bibliotecas de soporte de este.Este es infinitamente más seguro que el uso de escapar funciones tales como mysql_real_escape_string.

Sí, es mysql_real_escape_string efectivamente sólo una cadena de escapar la función.No es una bala mágica.Todo lo que va a hacer es escapar de la peligrosa los caracteres con el fin de que puedan ser caja fuerte a utilizar en una sola cadena de consulta.Sin embargo, si no se desinfectan su entradas de antemano, entonces usted va a ser vulnerables a ciertos vectores de ataque.

Imagine el siguiente SQL:

$resultado = "SELECCIONE los campos DE la tabla DONDE id = ".mysql_real_escape_string($_POST['id']);

Usted debe ser capaz de ver que este es vulnerable a explotar.Imaginar el id parámetro contenía el ataque común vector:

1 O 1=1

No hay arriesgado caracteres en la que codificar, por lo que va a pasar a través de la escape filtro.Dejando nosotros:

SELECCIONE los campos FROM tabla where id = 1 O 1=1

Lo programé una rápida función poco que lo he puesto en mi clase de base de datos que se tira todo lo que no es un número.Utiliza preg_replace, así que no hay problema un poco más optimizado la función, pero funciona en un apuro...

function Numbers($input) {
  $input = preg_replace("/[^0-9]/","", $input);
  if($input == '') $input = 0;
  return $input;
}

Así que en lugar de utilizar

$resultado = "SELECT campos FROM tabla where id = ".mysqlrealescapestring("1 or 1=1");

Me gustaría utilizar

$resultado = "SELECT campos FROM tabla where id = ".Los números("1 or 1=1");

y lo haría de forma segura ejecutar la consulta

SELECCIONE los campos FROM tabla where id = 111

Seguro, que sólo dejó de mostrar la fila correcta, pero no creo que es un gran problema para quien está tratando de inyectar código sql en su sitio ;)

Una pieza importante de este rompecabezas es de contextos.Alguien enviar un "1 or 1=1" como el ID no es un problema si usted cita cada argumento en su consulta:

SELECT fields FROM table WHERE id='".mysql_real_escape_string($_GET['id'])."'"

Que se traduce en:

SELECT fields FROM table WHERE id='1 OR 1=1'

que es ineficaz.Ya que estás escapando de la cadena, la entrada no puede romper la cadena de contexto.He probado esto en cuanto a la versión de MySQL 5.0.45, y el uso de un contexto de cadena para una columna de enteros no causa ningún problema.

$result = "SELECT fields FROM table WHERE id = ".(INT) $_GET['id'];

Funciona bien, incluso mejor en sistemas de 64 bits.Cuidado con los sistemas de limitaciones en el direccionamiento de los grandes números, pero para la base de datos de identificadores de esto funciona muy bien en el 99% del tiempo.

Usted debe utilizar una sola función/método para la limpieza de sus valores.Incluso si esta función es simplemente un contenedor para mysql_real_escape_string().Por qué?Porque un día, cuando una explotar a su método preferido de la limpieza de datos se encuentra usted sólo tiene que actualizar una posición, en lugar de un sistema amplio de buscar y reemplazar.

¿por qué, oh por QUÉ, le no incluir comillas alrededor de la entrada del usuario en la instrucción sql?parece bastante tonto no!incluyendo citas en la instrucción sql haría "1 or 1=1" un infructuoso intento, ¿no?

así que ahora, que voy a decir, "¿y si el usuario incluye una cita (o entre comillas) en la entrada?"

así, una solución fácil para que:acaba de quitar la entrada del usuario había comillas.por ejemplo: input =~ s/'//g;.ahora, a mí me parece de todos modos, que la entrada del usuario estaría asegurado...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top