2008-09-16 12 views
62

Tengo PHP configurado para que las comillas mágicas estén activadas y las variables globales de registro estén desactivadas.¿Cuáles son las mejores prácticas para evitar ataques xss en un sitio PHP

Hago todo lo posible para llamar siempre a htmlentities() para cualquier cosa que estoy obteniendo que se deriva de la entrada del usuario.

también de vez en cuando da pesquisa mi base de datos de las cosas comunes que se utilizan en XSS conectados, tales como ...

<script 

¿Qué más debo hacer y cómo puedo estar seguro de que las cosas que estoy tratando de hacer son siempre hecho.

Respuesta

58

Escapar no es el mejor que puede hacer para el éxito de la prevención de XSS. También la salida debe ser escapada. Si utiliza el motor de plantillas Smarty, puede usar el modificador |escape:'htmlall' para convertir todos los caracteres sensibles a entidades HTML (yo uso el modificador propio |e, que es un alias del anterior).

Mi enfoque de la seguridad de entrada/salida es: la entrada del usuario

  • tienda no modificado (sin HTML escape en la entrada, solamente DB-consciente de escape que realiza a través de DOP preparado estados)
  • de escape en la salida, dependiendo en qué formato de salida que utiliza (por ejemplo, HTML y JSON necesitan diferentes reglas de escape)
+5

htmlentities() es una exageración y es codifica-sensible. htmlspecialchars() protege igual de bien. – Kornel

+2

htmlspecialchars no puede ser su amigo: http://stackoverflow.com/questions/110575/do-htmlspecialchars-and-mysqlrealescapestring-keep-my-php-code-safe-from-injec – Cheekysoft

+0

@Cheekysoft: Sólo hay que establecer la [apropiada flags] (http://au.php.net/htmlspecialchars#refsect1-function.htmlspecialchars-parameters) – Casebash

2

Escapar de toda la entrada 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 permiten enlaces de protocolo javascript:; estos ejecutarían un script tan pronto como el usuario haga clic en el enlace.

12

Hay muchas formas de hacer XSS (consulte http://ha.ckers.org/xss.html) y es muy difícil de detectar.

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

2

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

Leer más: entrada Sanitizing user data: How and where to do it

2

“comillas mágicas” es un remedio paliativo para algunos de los peores defectos XSS que trabaja por escapar de todo en la entrada, algo que le pasa por diseño . El único caso donde uno querría usarlo es cuando absolutamente debe usar una aplicación PHP existente que se sabe que se escribió descuidadamente con respecto a XSS. (En este caso, usted está en un problema serio incluso con "citas mágicas"). Al desarrollar su propia aplicación, debe desactivar las "comillas mágicas" y seguir las prácticas seguras de XSS.

XSS, una vulnerabilidad de scripting entre sitios, ocurre cuando una aplicación incluye cadenas de fuentes externas (entrada del usuario, obtenida de otros sitios web, etc.) en su [X] HTML, CSS, ECMAscript u otra salida analizada por navegador sin escaparse correctamente, con la esperanza de que nunca aparezcan caracteres especiales como menos que (en [X] HTML), comillas simples o dobles (ECMAscript). La solución adecuada es escaparse siempre de las cadenas de acuerdo con las reglas del lenguaje de salida: usando entidades en [X] HTML, barras invertidas en ECMAscript, etc.

Dado que puede ser difícil hacer un seguimiento de lo que no es de confianza y debe escaparse, es una buena idea escapar de todo lo que sea una "cadena de texto" en lugar de "texto con marcado" en un lenguaje como HTML . Algunos entornos de programación lo hacen más fácil al introducir varios tipos de cadenas incompatibles: "cadena" (texto normal), "cadena HTML" (marcado HTML), etc. De esta forma, una conversión implícita directa de "cadena" a "cadena HTML" sería imposible, y la única forma en que una cadena podría convertirse en una marca HTML es pasarla a través de una función de escape.

"Register globals", aunque deshabilitarlo definitivamente es una buena idea, se trata de un problema completamente diferente de XSS.

+1

No utilice registros globales. Hacen que sea fácil escribir código inseguro y se han depreciado en el tiempo desde que se publicó. – James

+1

Quise decir deshabilitar el registro global, por supuesto, no habilitando. Error de tipografía. –

0

Utilice una biblioteca de higienización de entrada de usuario existente para limpiar todos entrada de usuario. A menos que agregue lote de esfuerzo, implementarlo usted mismo nunca funcionará tan bien.

10

Esta es una gran pregunta.

En primer lugar, no escatime el texto en la entrada excepto para que sea seguro para el almacenamiento (como ser puesto en una base de datos). La razón de esto es que desea mantener lo que se ingresó para que pueda presentarlo de manera diferente en diferentes lugares y lugares. Hacer cambios aquí puede comprometer su presentación posterior.

Cuando vaya a presentar su filtro de datos, lo que no debería estar allí. Por ejemplo, si no hay una razón para que JavaScript esté allí, búscalo y quítalo. Una forma fácil de hacerlo es usar la función strip_tags y solo presentar las etiquetas html que está permitiendo.

A continuación, toma lo que tienes y pásalo, htmlentities o htmlspecialchars para cambiar lo que está ahí para ascii characters. Haga esto en función del contexto y de lo que desea obtener.

Yo también recomendaría apagar Magic Quotes. Se ha eliminado de PHP 6 y se considera una mala práctica para usarlo. Más detalles en http://us3.php.net/magic_quotes

Para más detalles visita http://ha.ckers.org/xss.html

Ésta no es una respuesta completa, pero, con suerte suficiente para ayudarle a empezar.

1

Cree cualquier cookie de sesión (o todas las cookies) que use HttpOnly. La mayoría de los navegadores ocultan el valor de la cookie de JavaScript en ese caso. El usuario aún puede copiar cookies de forma manual, pero esto ayuda a evitar el acceso directo al script. StackOverflow tuvo este problema durante beta.

Esto no es una solución, más que otro ladrillo en la pared

2

Personalmente, me gustaría desactivar magic_quotes. En PHP5 + está deshabilitado por defecto 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 filtre, se le indicará qué hacer a continuación, p. si solo es texto, p. un nombre, luego strip_tags(trim(stripslashes())); o para comprobar si los rangos usan expresiones regulares.

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

Si está revisando números de utilizar para hacer cumplir is_numeric números enteros o fundido a un tipo específico, que debe evitar que las personas que tratan de enviar cadenas en lugar de él.

Si tiene PHP5.2 +, considere buscar en filter() y hacer uso de 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 usted tiene que manejar HTML, entonces debería considerar algo así como PHP Input Filter o HTML Purifier. Purificador HTML también validará HTML para la conformidad. No estoy seguro de si aún está en desarrollo del filtro de entrada. Tanto le permitirá definir un conjunto de etiquetas que se pueden utilizar y qué atributos están permitidos.

Independientemente de lo que decida, recuerde siempre, nunca confíe en nada que ingrese a su script PHP desde un usuario (incluido usted mismo).

7

rikh escribe:

hago todo lo posible para llamar siempre htmlentities() para cualquier cosa que estoy outputing que se deriva de la entrada del usuario. ensayo

Sede de Joel en Making Code Look Wrong para obtener ayuda con este

+0

1 para un enlace a un gran artículo – Josiah

2

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

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

Escapar su salida usando htmlentities() y 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 puede 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 para 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 ser popular y lo suficientemente rápido, pero mientras tanto tenemos que construir nuestros documentos HTML a través de operaciones de cadenas, y eso es inherentemente más arriesgado.

1
  • No confíe en la entrada del usuario
  • Escape de toda la salida de texto libre
  • No utilice magic_quotes; ver si hay una variante DBMS-specfic, o usar DOP
  • Considere el uso de HTTP sólo las cookies que sea posible para evitar cualquier script malicioso que había sido capaz de secuestrar una sesión
18

Soy de la opinión de que uno shouldn' t escapa cualquier cosa durante la entrada, solo en la salida. Como (la mayoría de las veces) no puede suponer que sabe a dónde van esos datos. Por ejemplo, si tiene un formulario que toma datos que luego aparecen en un correo electrónico que envía, necesita diferentes escapes (de lo contrario, un usuario malintencionado podría reescribir sus encabezados de correo electrónico).

En otras palabras, sólo se puede escapar en el último momento los datos se "abandona" su aplicación:

  • elemento de la lista
  • escribir en el archivo XML, escapar para XML
  • Escribir al DB, escape (para ese DBMS particular)
  • escritura de correo electrónico, mensajes de correo electrónico para escapar
  • etc

ir corto:

  1. Usted no sabe dónde están sus datos va
  2. datos en realidad podría terminar en más de un lugar, necesitando diferente del mecanismo de escape PERO NO TANTO
  3. datos escapó de la el objetivo equivocado no es realmente agradable. (Por ejemplo, recibe un correo electrónico con el asunto "Ir a la barra Tommy \ 's".)

Esp # 3 se producirá si escapas de datos en la capa de entrada (o lo que necesita para de-escapar de nuevo, etc.)

PD: Voy a secundar el consejo de no usar magic_quotes, ¡eso es pura maldad!

+0

ronda de bonificación: [WordPress consiguió propiedad de XSS a través de MySQL truncamiento columna en 2015] (https://klikki.fi/adv/wordpress2.html) gracias a la filtración en la entrada, en lugar de salida. –

0

Creo que la mejor forma es utilizar una clase que permita enlazar su código para que nunca tenga que preocuparse escapando manualmente sus datos.

-1

Es difícil implementar una inyección de sql/prevención de inyección xss completa en un sitio que no causa falsas alarmas. En un CMS, el usuario final puede querer usar <script> o <object> que enlaza con elementos de otro sitio.

Es recomendable tener todos los usuarios instalar Firefox con NoScript ;-)

4

me baso en PHPTAL para eso.

A diferencia de Smarty y PHP simple, se escapa de todos los resultados por defecto. Este es un gran triunfo 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 prefiltrar datos en la base de datos, ya que podría necesitar generar datos en otro medio que no acepte HTML, pero que tiene sus propios riesgos.

+0

Solo resuelve el resultado a HTML, no a SQL, Mail, XML, etc ... – Jilles

+3

SQL no ejecuta JavaScript. Transformar datos en un subconjunto seguro común a HTML, SQL, correo, etc. es demasiado limitante y no elimina el riesgo por completo. El escapado correcto de la salida HTML es a prueba de balas para HTML. Para un escapado SQL adecuado, ¡use las herramientas SQL! – Kornel

4

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

Si salpica htmlentities() a través de su código, el diseño general es incorrecto. Y como sugieres, es posible que te pierdas uno o dos lugares. 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.

Por desgracia, la mayoría de las bibliotecas de plantillas php sólo añadir su propia sintaxis de la plantilla, pero no se preocupan de codificación de salida, o la localización, o validación de HTML, o cualquier cosa importante. ¿Tal vez alguien más conoce una biblioteca de plantillas adecuada para php?

+0

Estoy totalmente de acuerdo, y diría que la mejor biblioteca de plantillas es xsl. – Josiah

1

Al menos debe validar todos los datos que entran en la base de datos. Y trate de 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, XSS, pero es más complicado. ¡Debes preg_match, stip_tags o htmlentities donde sea posible!

1

El mejor método actual para la prevención de XSS en una aplicación PHP es Purificador HTML (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. Debería usar esto en cualquier lugar donde el contenido que no es de confianza se emita en la pantalla. Es mucho más a fondo que htmlentities, htmlspecialchars, filter_input, filter_var, strip_tags, etc.

Cuestiones relacionadas