2010-01-27 33 views
45

¿Qué debo hacer para evitar XSS en Spring MVC? En este momento, solo estoy colocando todos los lugares donde publico el texto del usuario en las etiquetas JSTL <c:out> o en las funciones fn:escapeXml(), pero esto parece ser propenso a errores ya que podría perder un lugar.¿Cómo evito que las personas hagan XSS en Spring MVC?

¿Existe una manera sistemática fácil de evitar esto? Tal vez como un filtro o algo? Estoy recopilando entradas especificando los parámetros @RequestParam en mis métodos de controlador.

+2

Ver Joel Spolsky de Mira incorrecto * - http: //www.joelonsoftware. com/articles/Wrong.html - que trata sobre cómo lidiar con este problema exacto. – mob

+0

El título podría ser malinterpretado y respondido cómicamente "primero, instale una JVM en el cerebro de la persona". ;) – Svante

+0

Una pregunta muy similar se puede encontrar aquí: http://stackoverflow.com/questions/2658922/xss-prevention-in-java –

Respuesta

50

En primavera se puede escapar el código HTML de las páginas JSP generadas por <form> etiquetas. Esto cierra un bajo número de vías de ataques XSS, y se puede hacer de forma automática de tres maneras:

para toda la aplicación en el archivo web.xml:

<context-param> 
    <param-name>defaultHtmlEscape</param-name> 
    <param-value>true</param-value> 
</context-param> 

Para todas las formas en una página determinada en el propio archivo :

<spring:htmlEscape defaultHtmlEscape="true" /> 

Para cada formulario:

<form:input path="someFormField" htmlEscape="true" /> 
+2

Puse en un archivo de inclusión que incluyo en todas mis páginas, pero no parece marcar la diferencia. ¿Esa etiqueta hará que se escape $ {param.q}? – Doug

+2

Si usa las cadenas resultantes dentro de un atributo HTML o Javascript, 'defaultHTMLEscape' no es suficiente, entonces use la etiqueta' '. Parece que defaultHtmlEscape no escapa a todos los caracteres html. Se escapa, p. '<' '>' o '&' pero las comillas dobles '" 'no se escaparon para mí Esto puede ocasionar problemas si la cadena resultante se utiliza, por ejemplo, en un atributo html o javascript. (Consulte también la respuesta de Erlend) – Andreas

+3

Agregué el parámetro de contexto a mi web.xml pero no funciona. – Jack

8

Probar XSSFilter.

+0

La página no existe. – opyate

+0

@opyate - parece que lo movieron. Lo actualicé – Bozho

+0

Gracias. Eliminé la barra al final, de lo contrario 404. (esperando la revisión por pares) – opyate

0

compruebe siempre Manua Elija los métodos, las etiquetas que usa y asegúrese de que siempre escapen (una vez) al final. Los marcos tienen muchos errores y diferencias en este aspecto.

Una visión general: http://www.gablog.eu/online/node/91

6

Cuando usted está tratando de evitar XSS, es importante pensar en el contexto. Como ejemplo, cómo y qué escaparse es muy diferente si está superando los datos dentro de una variable en un fragmento de JavaScript en lugar de generar datos en una etiqueta HTML o un atributo HTML.

que tienen un ejemplo de esto aquí: http://erlend.oftedal.no/blog/?blogid=91

también comprobación la Hoja de OWASP XSS Prevención de trucos: http://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet

Así que la respuesta corta es, asegúrese de escapar de salida, como lo sugiere Tendayi Mawushe, pero toma cuidado especial cuando está produciendo datos en atributos HTML o javascript.

+0

"tenga especial cuidado" = use la etiqueta '' cuando imprima datos en atributos HTML o javascript . (vea mi comentario en la respuesta de Tendayi Mawushe) – Andreas

+1

Bueno, es más que solo usar . Javascript tiene otros caracteres de control que HTML, y puede ser atacado de diferentes maneras, y por lo tanto debe manejarse usando otros tipos de escape. ejemplo: var a = ''; var b = ''; Si La entrada e en a es una sola barra invertida, se ejecutará la secuencia de comandos en b. Escapar depende del contexto. – Erlend

+0

La mejor respuesta de todas. – droope

0

En lugar de confiar solamente en <c:out />, también se debe usar una biblioteca antixss, que no solo codificará sino que también desinfectará las secuencias de comandos maliciosas en la entrada. Una de las mejores bibliotecas disponibles es OWASP Antisamy, es altamente flexible y se puede configurar (utilizando archivos de política xml) según los requisitos.

Por ej. si una aplicación solo admite el ingreso de texto, se puede usar la mayoría de los genéricos policy file proporcionados por OWASP, que desinfecta y elimina la mayoría de las etiquetas html.Del mismo modo, si los editores de soporte de aplicaciones HTML (como tinymce) y que requieren todo tipo de etiquetas HTML, una política más flexible puede ser el uso como ebay policy file

4

uso de Hibernate Validator través @Valid para todos los objetos de entrada (de unión y @RequestBody JSON, véase https://dzone.com/articles/spring-31-valid-requestbody). Entonces @org.hibernate.validator.constraints.SafeHtml es una buena solución para mí.

Hibernate SafeHtmlValidator depende de org.jsoup, por lo que se necesita para agregar uno más dependencias del proyecto:

<dependency> 
    <groupId>org.jsoup</groupId> 
    <artifactId>jsoup</artifactId> 
    <version>1.10.1</version> 
</dependency> 

Para frijol User con el campo

@NotEmpty 
@SafeHtml 
protected String name; 

de intento de actualización con valor <script>alert(123)</script> en el controlador

@PutMapping(value = "/{id}", consumes = MediaType.APPLICATION_JSON_VALUE) 
public void update(@Valid @RequestBody User user, @PathVariable("id") int id) 

o

@PostMapping 
public void createOrUpdate(@Valid User user) { 

se lanza BindException por la unión y para MethodArgumentNotValidException@RequestBody con el mensaje por defecto:

name may have unsafe html content 

Validador funciona tan bien para la unión, como antes persistente. Aplicaciones podrían ser probados en http://topjava.herokuapp.com/

0
**To avoid XSS security threat in spring application** 

solución a la cuestión XSS es filtrar todos los campos de texto en forma en el momento de enviar el formulario.

It needs XML entry in the web.xml file & two simple classes. 

     java code :- 
     The code for the first class named CrossScriptingFilter.java is : 

     package com.filter; 

     import java.io.IOException; 
     import javax.servlet.Filter; 
     import javax.servlet.FilterChain; 
     import javax.servlet.FilterConfig; 
     import javax.servlet.ServletException; 
     import javax.servlet.ServletRequest; 
     import javax.servlet.ServletResponse; 
     import javax.servlet.http.HttpServletRequest; 
     import org.apache.log4j.Logger; 

     public class CrossScriptingFilter implements Filter { 
      private static Logger logger = Logger.getLogger(CrossScriptingFilter.class); 
      private FilterConfig filterConfig; 

      public void init(FilterConfig filterConfig) throws ServletException { 
       this.filterConfig = filterConfig; 
      } 

      public void destroy() { 
       this.filterConfig = null; 
      } 

      public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 
       throws IOException, ServletException { 
       logger.info("Inlter CrossScriptingFilter ..............."); 
       chain.doFilter(new RequestWrapper((HttpServletRequest) request), response); 
       logger.info("Outlter CrossScriptingFilter ..............."); 
      } 

     } 

La segunda clase cuyo nombre en código es RequestWrapper.java:

paquete com.filter;

import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletRequestWrapper; 

import org.apache.log4j.Logger; 

public final class RequestWrapper extends HttpServletRequestWrapper { 
    private static Logger logger = Logger.getLogger(RequestWrapper.class); 
    public RequestWrapper(HttpServletRequest servletRequest) { 
     super(servletRequest); 
    } 

    public String[] getParameterValues(String parameter) { 
     logger.info("InarameterValues .. parameter ......."); 
     String[] values = super.getParameterValues(parameter); 
     if (values == null) { 
      return null; 
     } 
     int count = values.length; 
     String[] encodedValues = new String[count]; 
     for (int i = 0; i < count; i++) { 
      encodedValues[i] = cleanXSS(values[i]); 
     } 
     return encodedValues; 
    } 

    public String getParameter(String parameter) { 
     logger.info("Inarameter .. parameter ......."); 
     String value = super.getParameter(parameter); 
     if (value == null) { 
      return null; 
     } 
     logger.info("Inarameter RequestWrapper ........ value ......."); 
     return cleanXSS(value); 
    } 

    public String getHeader(String name) { 
     logger.info("Ineader .. parameter ......."); 
     String value = super.getHeader(name); 
     if (value == null) 
      return null; 
     logger.info("Ineader RequestWrapper ........... value ...."); 
     return cleanXSS(value); 
    } 

    private String cleanXSS(String value) { 
     // You'll need to remove the spaces from the html entities below 
     logger.info("InnXSS RequestWrapper ..............." + value); 
     //value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;"); 
     //value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;"); 
     //value = value.replaceAll("'", "& #39;"); 
     value = value.replaceAll("eval\\((.*)\\)", ""); 
     value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\""); 

     value = value.replaceAll("(?i)<script.*?>.*?<script.*?>", ""); 
     value = value.replaceAll("(?i)<script.*?>.*?</script.*?>", ""); 
     value = value.replaceAll("(?i)<.*?javascript:.*?>.*?</.*?>", ""); 
     value = value.replaceAll("(?i)<.*?\\s+on.*?>.*?</.*?>", ""); 
     //value = value.replaceAll("<script>", ""); 
     //value = value.replaceAll("</script>", ""); 
     logger.info("OutnXSS RequestWrapper ........ value ......." + value); 
     return value; 
    } 

Lo único que permanece es la entrada XML en el archivo web.xml:

 <filter> 
     <filter-name>XSS</filter-name> 
     <display-name>XSS</display-name> 
     <description></description> 
     <filter-class>com.filter.CrossScriptingFilter</filter-class> 
    </filter> 

    <filter-mapping> 
     <filter-name>XSS</filter-name> 
     <url-pattern>/*</url-pattern> 
    </filter-mapping> 

El/* indica que por cada petición realizada desde el navegador, se llamará Clase CrossScriptingFilter. Que analizar todos los componentes/elementos provienen de la solicitud & reemplazará todas las etiquetas JavaScript formuladas por hackers con cadena vacía es decir Código * Hacer

Cuestiones relacionadas