2009-08-21 35 views
27

¿Cómo desinfecta los datos en $ _GET -variables por PHP?Desinfección de los datos del usuario en GET por PHP

Sano solo una variable en GET por strip_tags. No estoy seguro de si debo desinfectar todo o no, porque la última vez que le puse datos a Postgres, el problema se solucionó más fácilmente mediante el uso de pg_prepare.

+1

Desinfección para evitar inyecciones de SQL o ataques XSS? –

Respuesta

74

¿Cómo se desinfecte datos en $ _GET variables- por PHP?

Usted no desinfectar datos en $ _GET. Este es un enfoque común en los scripts de PHP, pero está completamente mal *.

Todas sus variables deben permanecer en forma de texto sin formato hasta el momento en que las incruste en otro tipo de cadena. No hay ninguna forma de escape o "desinfección" que pueda abarcar todos los tipos de cadenas posibles en las que pueda incrustar sus valores.

Así que si estás incrustación de una cadena en una consulta SQL, tiene que escapar de ella a la salida:

$sql= "SELECT * FROM accounts WHERE username='".pg_escape_string($_GET['username'])."'"; 

Y si estás escupiendo la cadena a cabo en HTML, tiene que escapar entonces:

Cannot log in as <?php echo(htmlspecialchars($_GET['username'], ENT_QUOTES)) ?>. 

Si no ambos pasos se escapan de la matriz $ _GET al principio, según lo recomendado por personas que no saben lo que están haciendo:

$_GET['username']= htmlspecialchars(pg_escape_string($_GET['username'])); 

Luego, cuando tenía un '&' en su nombre de usuario, misteriosamente se convertiría en '& amp;' en su base de datos, y si tenía un apóstrofo en su nombre de usuario, se convertiría en dos apóstrofes en la página. Luego, cuando tienes un formulario con estos personajes, es fácil terminar escapando cosas cuando se editan, razón por la cual muchos CMS PHP malos terminan con títulos de artículos rotos como "Libros nuevos de O \\\\". \\\\\\\\\\\\ '' Reilly ''.

Naturalmente, recordar pg_escape_string o mysql_real_escape_string y htmlspecialchars cada vez que envía una variable es un poco tedioso, por lo que todos quieren hacerlo (incorrectamente) en un lugar al comienzo del script. Para la salida HTML, al menos puede guardar algunos tipeos definiendo una función con un nombre corto que haga eco (htmlspecialchars (...)).

Para SQL, es mejor utilizar consultas con parámetros. Para Postgres, hay pg_query_params. O, de hecho, declaraciones preparadas como usted mencionó (aunque personalmente las encuentro menos manejables). De cualquier manera, puede olvidarse de "desinfectar" o escaparse para SQL, pero igualmente debe escapar si incorpora otros tipos de cadena, incluido HTML.

strip_tags() no es una buena forma de tratar la entrada para la visualización de HTML. En el pasado, ha tenido problemas de seguridad, ya que los analizadores del navegador son en realidad mucho más complicados en su interpretación de lo que puede ser una etiqueta de lo que podría pensar. htmlspecialchars() es casi siempre lo correcto para usar, de modo que si alguien escribe un signo menos de lo que realmente obtendrán un signo literal de menos de no encontrar la mitad de su texto desapareciendo misteriosamente.

(*: como un enfoque general para resolver problemas de inyección, naturalmente. Hay controles específicos de dominio que vale la pena hacer en campos particulares, y hay tareas de limpieza útiles que puede hacer como eliminar todos los caracteres de control de los valores enviados . Pero esto no es lo que la mayoría de los codificadores de PHP significan por sanitización.)

+0

Podría explicarme más qué quiere decir con esto * aún debe escapar si inserta en otros tipos de cadena, incluyendo HTML *. ** ¿Quiere decir que no necesito escapar de los nombres de usuario y correos electrónicos que puse en mi base de datos cuando uso declaraciones preparadas? ** - Solo muestro el nombre de usuario para el usuario dentro de HTMLL tomado de la base de datos. Su respuesta me sugiere que necesito 'pg_espace_string' para los nombres de usuario –

+5

No: para dar salida a una cadena SQL usa SQL escaping (o deja que las declaraciones parametrizadas/preparadas lo hagan automáticamente, pero no ambos). Para la salida a HTML, utiliza HTML escaping (con htmlspecialchars). Nunca coloque texto escapado en HTML en una cadena SQL, o texto escapado en SQL en una página HTML. – bobince

5

Si está hablando de desinfectar resultados, recomendaría almacenar contenido en su base de datos en su forma completa, sin guardar, y luego escapar (htmlspecialchars o algo similar) cuando haga eco de los datos, de esa manera tendrá más opciones para la salida. Consulte la pregunta this para obtener una explicación sobre el contenido de la base de datos de desinfección/escape.

En términos de almacenamiento en postgres, use pg_escape_string en cada variable en la consulta, para escapar de las comillas, y generalmente protege contra la inyección de SQL.

Editar:

Mis pasos habituales para almacenar datos en una base de datos y recuperación de la misma, son:

  1. de llamadas de los datos de base de datos la función que escapan (pg_escape_string, mysql_escape_string, etc), para escapar cada variable entrante $ _GET utilizada en su consulta. Tenga en cuenta que el uso de estas funciones en lugar de addslashes da como resultado que no haya barras adicionales en el texto cuando se almacenan en la base de datos.

  2. Cuando recupera los datos de la base de datos, puede usar htmlspecialchars en cualquier dato generado, no es necesario utilizar stripslashes, ya que no debe haber barras adicionales.

+0

Si le da los datos escapados para el usuario, entonces ve las barras inclinadas. ** ¿Qué función usas para hacer que los datos sean legibles nuevamente para el usuario? ** –

+0

Puedes usar tiras (http://uk2.php.net/stripslashes) para quitar barras de la cadena. – Kazar

+0

** ¿Hay alguna opción para todo el sistema que haga que mis datos se desinfecten en las variables '$ _GET' y' $ _POST' sin necesidad de poner las declaraciones 'htmlspecialvars' y' stripslashes' en cada estado? ** –

3

Debe desinfectar todas las solicitudes, no solo POST como GET.

Puede utilizar la función htmlentities(), la función preg_replace() con expresiones regulares, o filtrar por reparto:

<? 
$id = (int)$_GET['id']; 
?> 

[ 's]

+0

Estoy de acuerdo con usted en que todas las solicitudes deben estar espaced. Sin embargo, si usa 'pg_prepare', entonces no necesita la función' htmlentitiies' en mi opinión, ya que 'pg_prepare' desinfecta los datos. –

+0

No use un regex para desinfectar la salida; debe perderse algo y exponer accidentalmente una vulnerabilidad XSS; existen buenas bibliotecas para realizar una desinfección de salida personalizada (http://htmlpurifier.org/) – Kazar

+2

Masi: eso está mal y peligroso. pg_prepare trata de escaparse de SQL. No tiene nada que ver con el escapado de HTML, y no lo protegerá de ningún modo de los ataques XSS causados ​​por un personaje callejero. – bobince

2

higienizar sus entradas de acuerdo a dónde va.

  • Si muestra que (en una página o como el valor de un campo de entrada), utilice htmlspecialchars y/o str_replace.
  • Si lo usa como otro tipo, ejecútelo.
  • Si lo incluye en la consulta SQL, escúpelo con la función adecuada, tal vez pegue las etiquetas html si desea eliminarlas por completo (lo que no es lo mismo que escapó).

Lo mismo para la POST o incluso los datos de su base de datos, ya que los datos dentro de su base de datos en general no se deben escapar.

dos cosas que usted debe comprobar:

  1. codificación de su entrada vs.sus scripts PHP/salida/tabla de DB
  2. Si tiene habilitado el [magic_quotes_gpc][1], debe deshabilitarlo (cuando sea posible) o valores stripslashes() GET, POST y COOKIE. magic_quotes_gpc está en desuso, debe desinfectar los datos que manipula, según el use de esos datos.
Cuestiones relacionadas