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

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

  •  09-06-2019
  •  | 
  •  

Pregunta

Tengo PHP configurado para que las comillas mágicas estén activadas y los registros globales estén desactivados.

Hago lo mejor que puedo para llamar siempre a htmlentities() para cualquier cosa que genere y que se derive de la entrada del usuario.

De vez en cuando también busco en mi base de datos elementos comunes utilizados en xss adjuntos, como...

<script

¿Qué más debería hacer y cómo puedo asegurarme de que las cosas que intento hacer sean correctas? siempre hecho.

¿Fue útil?

Solución

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 utiliza el motor de plantillas Smarty, puede utilizar |escape:'htmlall' modificador para convertir todos los caracteres confidenciales a entidades HTML (yo uso propio |e modificador que es un alias del anterior).

Mi enfoque para la seguridad de entrada/salida es:

  • almacenar la entrada del usuario no modificada (no se escapa HTML en la entrada, solo el escape compatible con DB se realiza a través de declaraciones preparadas por PDO)
  • escape en la salida, dependiendo del formato de salida que utilice (p. ej.HTML y JSON necesitan reglas de escape diferentes)

Otros consejos

Soy de la opinión de que no se debe escapar nada durante la entrada, solo en la salida.Ya que (la mayoría de las veces) no puedes asumir que sabes hacia 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 un escape diferente (de lo contrario, un usuario malintencionado podría reescribir los encabezados de su correo electrónico).

En otras palabras, sólo puedes escapar en el último momento en que los datos "abandonan" tu aplicación:

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

Para abreviar:

  1. No sabes a dónde van tus datos
  2. En realidad, los datos podrían terminar en más de un lugar, necesitando diferentes mecanismos de escape, PERO NO AMBOS.
  3. Los datos que se escaparon para el objetivo equivocado realmente no son agradables.(P.ej.recibirá un correo electrónico con el asunto "Ir al bar de Tommy".)

° 3 ocurrirá si escapa de los datos en la capa de entrada (o necesita eliminarlos nuevamente, etc.).

PD:Apoyaré el consejo de no usar citas mágicas, ¡esas son pura maldad!

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, podría captar más de lo que logran mis rutinas hechas a mano.

Esta es una gran pregunta.

En primer lugar, no escape el texto en la entrada, excepto para que sea seguro para el almacenamiento (por ejemplo, si se coloca en una base de datos).La razón de esto es que desea conservar lo que se ingresó para poder presentarlo contextualmente en diferentes formas y lugares.Hacer cambios aquí puede comprometer su presentación posterior.

Cuando vayas a presentar tus datos, filtra lo que no debería estar allí.Por ejemplo, si no hay ningún motivo para que JavaScript esté allí, búsquelo y elimínelo.Una forma sencilla de hacerlo es utilizar el etiquetas_desnudas funcione y solo presente las etiquetas html que esté permitiendo.

A continuación, toma lo que tienes y pásalo por htmlentities o htmlspecialchars para cambiar lo que hay allí a caracteres ascii.Haga esto según el contexto y lo que desea transmitir.

También sugeriría desactivar las Cotizaciones mágicas.Se eliminó de PHP 6 y se considera una mala práctica usarlo.Detalles en http://us3.php.net/magic_quotes

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

Esta no es una respuesta completa, pero con suerte será suficiente para ayudarte a comenzar.

rik escribe:

Hago lo mejor que puedo para llamar siempre a htmlentities() para cualquier cosa que genere y que se derive de la entrada del usuario.

Véase el ensayo de Joel sobre Hacer que el código parezca incorrecto para ayudar con esto

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 ventaja para la seguridad, porque su sitio no se volverá vulnerable si olvida htmlspecialchars() o |escape en algún lugar.

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

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

Si agrega htmlentities() a lo largo de su código, el diseño general es incorrecto.Y como sugieres, es posible que te pierdas uno o dos puntos.Por eso la única solución es una codificación HTML rigurosa. -> cuando Las variables 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, ni la localización, ni la validación de html, ni nada importante.¿Quizás alguien más conozca una biblioteca de plantillas adecuada para PHP?

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 Referer enlace a otro sitio.Además, si permite que sus usuarios envíen enlaces, asegúrese de que no javascript: se permiten enlaces de protocolo;estos ejecutarían un script tan pronto como el usuario haga clic en el enlace.

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

Leer más:Desinfección de datos de usuario:Como y donde hacerlo

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

A continuación, dependiendo del tipo de datos de usuario que esté filtrando, se determinará qué hacer a continuación, p.si es solo texto, p.e.un nombre, entonces strip_tags(trim(stripslashes())); o para verificar 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 convertirlos a un tipo específico, eso debería evitar que las personas intenten enviar cadenas en su lugar.

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

Si tienes que manejar HTML entonces deberías considerar algo como Filtro de entrada PHP o Purificador HTML.HTML Purifier también validará la conformidad de HTML.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 utilizar y qué atributos están permitidos.

Independientemente de lo que decida, recuerde siempre: nunca confíe en nada de lo que un usuario ingresa en su script PHP (¡incluido usted mismo!).

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

Filtrar la entrada siempre es una buena idea para cualquier aplicación.

Escapar de 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 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, quizás usando una interfaz estándar como DOM, y luego usen una biblioteca (como libxml) para manejar la serialización a XHTML/HTML/etc.Por supuesto, estamos muy lejos de que eso sea lo suficientemente popular y rápido, pero mientras tanto tenemos que construir nuestros documentos HTML mediante operaciones de cadenas, y eso es inherentemente más riesgoso.

Creo que usar esta función ayuda a eliminar muchos posibles ataques xss:http://www.codebelay.com/killxss.phps

Las “comillas mágicas” son un remedio paliativo para algunas de las peores fallas de XSS que funciona escapando de todo en la entrada, algo que está mal por diseño.El único caso en el que uno querría usarlo es cuando es absolutamente necesario usar una aplicación PHP existente que se sabe que está escrita descuidadamente con respecto a XSS.(En este caso, estás en serios problemas incluso con las “comillas mágicas”.) Cuando desarrolles tu propia aplicación, debes desactivar las “comillas mágicas” y, en su lugar, seguir prácticas seguras para XSS.

XSS, una vulnerabilidad de secuencias de comandos entre sitios, ocurre cuando una aplicación incluye cadenas de fuentes externas (entradas del usuario, obtenidas de otros sitios web, etc.) en su [X]HTML, CSS, ECMAscript u otra salida analizada por el navegador sin el escape adecuado, con la esperanza de que los caracteres especiales como menos 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:usando entidades en [X]HTML, barras invertidas en ECMAscript, etc.

Debido a que puede ser difícil realizar un seguimiento de lo que no es de confianza y de lo que hay que escapar, es una buena idea escapar siempre 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 facilitan al introducir varios tipos de cadenas incompatibles:“cadena” (texto normal), “cadena HTML” (marcado HTML), etc.De esa manera, 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 formato HTML es pasándola a través de una función de escape.

"Registrar globales", aunque deshabilitarlo es definitivamente una buena idea, soluciona un problema completamente diferente al de XSS.

Realice cualquier cookie de sesión (o todas las cookies) que utilice HttpOnly.En ese caso, la mayoría de los navegadores ocultarán el valor de la cookie de JavaScript.El usuario aún puede copiar las cookies manualmente, pero esto ayuda a evitar el acceso directo al script.StackOverflow tuvo este problema durante la versión beta.

Esto no es una solución, sólo otro ladrillo en la pared.

  • No confíes en la entrada del usuario
  • Escapar de toda la salida de texto libre
  • No utilices comillas mágicas;ver si hay una variante específica de DBMS o usar PDO
  • Considere utilizar cookies solo HTTP cuando sea posible para evitar que cualquier script malicioso pueda secuestrar una sesión.

Al menos debería 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.¡Debes preg_match, stip_tags o htmlentities siempre que sea posible!

El mejor método actual para prevenir XSS en una aplicación PHP es HTML Purifier (http://htmlpurifier.org/).Un pequeño inconveniente es que es una biblioteca bastante grande y se utiliza mejor con un caché de código de operación como APC.Usarías esto en cualquier lugar donde se muestre en la pantalla contenido que no sea de confianza.Es mucho más completo que htmlentities, htmlspecialchars, filter_input, filter_var, strip_tags, etc.

Utilice una biblioteca de desinfección existente ingresada por el usuario para limpiar todo entrada del usuario.A menos que pongas un lote Si le dedicas mucho esfuerzo, implementarlo tú mismo nunca funcionará tan bien.

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.

Es difícil implementar una prevención exhaustiva de inyección SQL/inyección XSS en un sitio que no cause falsas alarmas.En un CMS, el usuario final podría querer utilizar <script> o <object> que enlaza con elementos de otro sitio.

Recomiendo que todos los usuarios instalen Firefox con NoScript ;-)

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