it-swarm-es.tech

¿Cuáles son las mejores prácticas para evitar ataques xss en un sitio PHP

Tengo PHP configurado para que las comillas mágicas estén activadas y las globales de registro estén desactivadas.

Hago mi mejor esfuerzo para llamar siempre a htmlentities () para cualquier cosa que estoy generando que se deriva de la entrada del usuario.

También ocasionalmente busco en mi base de datos las cosas comunes utilizadas en xss adjuntas, como ...

<script

¿Qué más debo hacer y cómo puedo asegurarme de que las cosas que estoy tratando de hacer estén siempre hechas.

65
Rik Heywood

Escapar de la entrada no es lo mejor que puede hacer para una prevención exitosa de XSS. También se debe escapar la salida. Si usa el motor de plantillas Smarty, puede usar el modificador |escape:'htmlall' para convertir todos los caracteres confidenciales en entidades HTML (uso el propio modificador |e que es un alias de lo anterior).

Mi enfoque para la seguridad de entrada/salida es:

  • no se modificó la entrada del usuario (no se escapó HTML en la entrada, solo se escapó la base de datos DB mediante declaraciones preparadas para PDO)
  • escapar en la salida, dependiendo del formato de salida que use (por ejemplo, HTML y JSON necesitan diferentes reglas de escape)
58
Michał Rudnicki

Soy de la opinión de que no se debe escapar de nada durante la entrada, solo en la salida. Dado que (la mayoría de las veces) no puede asumir que sabe a dónde van esos datos. Ejemplo, si tiene un formulario que toma datos que luego aparecen en un correo electrónico que envía, necesita un escape diferente (de lo contrario, un usuario malintencionado podría reescribir sus encabezados de correo electrónico).

En otras palabras, solo puede escapar en el último momento en que los datos "abandonan" su aplicación:

  • Elemento de la lista
  • Escribir en un archivo XML, escapar para XML
  • Escriba en DB, escape (para ese DBMS en particular)
  • Escribir correo electrónico, escapar por correos electrónicos
  • etc.

Para ir corto:

  1. No sabes a dónde van tus datos
  2. Los datos podrían terminar en más de un lugar, necesitando diferentes mecanismos de escape, PERO NO AMBOS
  3. Los datos escapados para el objetivo equivocado realmente no son agradables. (Por ejemplo, recibe un correo electrónico con el asunto "Ir a la barra de Tommy").

Esp # 3 ocurrirá si escapa de datos en la capa de entrada (o si necesita volver a escapar de ella, etc.).

PD: Secundaré el consejo para no usar magic_quotes, ¡esos son pura maldad!

18
Jilles

Hay muchas maneras de hacer XSS (Ver http://ha.ckers.org/xss.html ) y es muy difícil de atrapar.

Personalmente delego esto al marco actual que estoy usando (Code Igniter, por ejemplo). Si bien no es perfecto, puede atrapar más de lo que mis rutinas hechas a mano nunca hacen.

12
Christian Studer

Esta es una gran pregunta.

Primero, no escape el texto en la entrada, excepto para que sea seguro para el almacenamiento (como colocarlo en una base de datos). La razón de esto es que desea conservar lo que se ingresó para poder presentarlo contextualmente de diferentes maneras y lugares. Hacer cambios aquí puede comprometer su presentación posterior.

Cuando vayas a presentar tu filtro de datos, lo que no debería estar allí. Por ejemplo, si no hay una razón para que esté JavaScript, búsquelo y elimínelo. Una manera fácil de hacerlo es usar la función strip_tags y solo presentar las etiquetas html que está permitiendo.

A continuación, tome lo que tiene y páselo con htmlentities o htmlspecialchars para cambiar lo que hay a los caracteres ascii. Haga esto en función del contexto y de lo que desea obtener.

También, sugiero desactivar las citas mágicas. Se ha eliminado de PHP 6 y se considera una mala práctica usarlo. Detalles en http://us3.php.net/magic_quotes

Para obtener más información, consulte http://ha.ckers.org/xss.html

Esta no es una respuesta completa pero, con suerte, lo ayudará a comenzar.

10
Matt Farina

hago mi mejor esfuerzo para llamar siempre a htmlentities () para cualquier cosa que estoy generando que se deriva de la entrada del usuario.

.

See Joel's essay on Making Code Look Wrong for help with this

7
Mason

Confío en PHPTAL para eso.

A diferencia de Smarty y PHP simple, escapa a todos los resultados de forma predeterminada. Esta es una gran victoria para la seguridad, porque su sitio no se volverá vulnerable si olvida htmlspecialchars() o |escape en alguna parte.

XSS es un ataque específico de HTML, por lo que la salida HTML es el lugar correcto para evitarlo. No debe intentar filtrar previamente los datos en la base de datos, ya que podría necesitar enviar datos a otro medio que no acepte HTML, pero tiene sus propios riesgos.

4
Kornel

Biblioteca de plantillas O al menos, eso es lo que deberían hacer las bibliotecas de plantillas. Para evitar XSS toda la salida debe estar codificada. Esta no es la tarea de la aplicación principal/lógica de control, solo debe ser manejada por los métodos de salida.

Si rocía htmlentities () a través de su código, el diseño general es incorrecto. Y como sugiere, puede perder uno o dos puntos. Es por eso que la única solución es la rigurosa codificación html -> cuando los vars de salida se escriben en una secuencia html/xml.

Desafortunadamente, la mayoría de las bibliotecas de plantillas php solo agregan su propia sintaxis de plantilla, pero no se preocupan por la codificación de salida, la localización, la validación html ni nada importante. ¿Quizás alguien más conoce una biblioteca de plantillas adecuada para php?

4
user319490

Si le preocupan los ataques XSS, la solución es codificar sus cadenas de salida a HTML. Si recuerda codificar cada carácter de salida en formato HTML, no hay forma de ejecutar un ataque XSS exitoso.

Leer más: Desinfectar los datos del usuario: cómo y dónde hacerlo

2
Niyaz

Personalmente, deshabilitaría magic_quotes. En PHP5 + está deshabilitado de forma predeterminada y es mejor codificar como si no estuviera allí, ya que no escapa de todo y se eliminará de PHP6.

A continuación, según el tipo de datos de usuario que esté filtrando, se determinará qué hacer a continuación, p. si es solo texto, p. un nombre, luego strip_tags(trim(stripslashes())); o para verificar los rangos use expresiones regulares.

Si espera un cierto rango de valores, cree una matriz de valores válidos y solo permita esos valores a través de (in_array($userData, array(...))).

Si está verificando números, use is_numeric para aplicar números enteros o emitir a un tipo específico, eso debería evitar que las personas intenten enviar cadenas en su lugar.

Si tiene PHP5.2 +, considere mirar filter () y usar esa extensión que puede filtrar varios tipos de datos, incluidas las direcciones de correo electrónico. La documentación no es particularmente buena, pero está mejorando.

Si tiene que manejar HTML, entonces debería considerar algo como Filtro de entrada PHP o Purificador HTML . HTML Purifier también validará HTML para la conformidad. No estoy seguro de si todavía se está desarrollando el filtro de entrada. Ambos le permitirán definir un conjunto de etiquetas que se pueden usar y qué atributos están permitidos.

Sea lo que sea que decida, recuerde siempre, nunca confíe en nada que su usuario ingrese en su script [PHP (incluido usted mismo).

2
Dave

Me parece que el uso de esta función ayuda a eliminar muchos posibles ataques xss: http://www.codebelay.com/killxss.phps

2
barce

Las “citas mágicas” son un remedio paliativo para algunos de los peores defectos de XSS que funciona al escapar de todo en la entrada, algo que está mal por diseño. El único caso en el que uno desearía usarlo es cuando absolutamente debe usar una aplicación existente [PHP que se sabe que está escrita descuidadamente con respecto a XSS. (En este caso, está en serios problemas incluso con “comillas mágicas”). Al desarrollar su propia aplicación, debe deshabilitar las “comillas mágicas” y seguir las prácticas seguras de XSS.

XSS, una vulnerabilidad de secuencias de comandos entre sitios, ocurre cuando una aplicación incluye cadenas de fuentes externas (entrada del usuario, obtenidas de otros sitios web, etc.) en su [X] HTML, CSS, ECMAscript u otra salida analizada por el navegador sin escapar, esperar que caracteres especiales como menor que (en [X] HTML), comillas simples o dobles (ECMAscript) nunca aparecerán. La solución adecuada es escapar siempre de las cadenas de acuerdo con las reglas del lenguaje de salida: usar entidades en [X] HTML, barras invertidas en ECMAscript, etc.

Debido a que puede ser difícil hacer un seguimiento de lo que no se confía y se debe escapar, es una buena idea escapar siempre de todo lo que es una "cadena de texto" en lugar de "texto con marcado" en un lenguaje como HTML. Algunos entornos de programación facilitan la introducción de varios tipos de cadenas incompatibles: “cadena” (texto normal), “cadena HTML” (marcado HTML), etc. De esa forma, sería imposible una conversión implícita directa de "cadena" a "cadena HTML", y la única forma en que una cadena podría convertirse en marcado HTML es pasándola a través de una función de escape.

"Registrar globales", aunque desactivarlo definitivamente es una buena idea, trata un problema completamente diferente de XSS.

2
Alexey Feldgendler

Escapar de todas las entradas del usuario es suficiente para la mayoría de los sitios. También asegúrese de que los ID de sesión no terminen en la URL para que no puedan ser robados del enlace Referer a otro sitio. Además, si permite que sus usuarios envíen enlaces, asegúrese de que no se permitan enlaces de protocolo javascript:; estos ejecutarían un script tan pronto como el usuario haga clic en el enlace.

2
Konrad Rudolph

Todas estas respuestas son geniales, pero fundamentalmente, la solución a XSS será dejar de generar documentos HTML mediante la manipulación de cadenas.

El filtrado de entrada siempre es una buena idea para cualquier aplicación.

Escapar de su salida usando htmlentities () y sus amigos debería funcionar siempre que se use correctamente, pero este es el equivalente HTML de crear una consulta SQL concatenando cadenas con mysql_real_escape_string ($ var): debería funcionar, pero menos cosas pueden validar su trabajo , por así decirlo, en comparación con un enfoque como el uso de consultas parametrizadas.

La solución a largo plazo debería ser que las aplicaciones construyan la página internamente, tal vez usando una interfaz estándar como DOM, y luego usar una biblioteca (como libxml) para manejar la serialización a XHTML/HTML/etc. Por supuesto, estamos muy lejos de que sea lo suficientemente popular y rápido, pero mientras tanto tenemos que construir nuestros documentos HTML a través de operaciones de cadena, y eso es inherentemente más riesgoso.

2
Daniel Papasian
  • No confíes en la entrada del usuario
  • Escapar de toda la salida de texto libre
  • No uses magic_quotes; ver si hay una variante específica de DBMS, o usar PDO
  • Considere el uso de cookies solo HTTP cuando sea posible para evitar que cualquier script malicioso pueda secuestrar una sesión
1
Rob

Al menos debe validar todos los datos que ingresan a la base de datos. E intente validar todos los datos que salen de la base de datos también.

mysql_real_escape_string es bueno para evitar la inyección de SQL, pero XSS es más complicado. ¡Debe preg_match, stip_tags o htmlentities cuando sea posible!

1
Abeon

El mejor método actual para prevenir XSS en una aplicación PHP es HTML Purifier (http://htmlpurifier.org/). Un inconveniente menor es que es una biblioteca bastante grande y se usa mejor con un caché de código operativo como APC. Usaría esto en cualquier lugar donde el contenido no confiable se envíe a la pantalla. Es mucho más exhaustivo que htmlentities, htmlspecialchars, filter_input, filter_var, strip_tags, etc.

1
Night Owl

Crea cookies de sesión (o todas las cookies) que utilices HttpOnly. La mayoría de los navegadores ocultarán el valor de la cookie de JavaScript en ese caso. El usuario aún podría copiar manualmente las cookies, pero esto ayuda a evitar el acceso directo a los scripts. StackOverflow tuvo este problema durante la versión beta.

Esto no es una solución, solo otro ladrillo en la pared

1
basszero

Creo que la mejor manera es usar una clase que le permita vincular su código para que nunca tenga que preocuparse por escapar manualmente de sus datos.

0
Darren22

Utilice una biblioteca de desinfección de entrada de usuario existente para limpiar todas entrada de usuario. A menos que ponga un lote de esfuerzo, implementarlo usted mismo nunca funcionará tan bien.

0
dbr