web-dev-qa-db-fra.com

Comment empêcher les gens de faire XSS dans Spring MVC?

Que dois-je faire pour empêcher XSS dans Spring MVC? Pour le moment, je mets simplement tous les endroits où je produis du texte utilisateur dans les balises JSTL <c:out> ou les fonctions fn:escapeXml(), mais cela semble sujet aux erreurs car je risque de manquer un endroit.

Existe-t-il un moyen simple et systématique d’empêcher cela? Peut-être comme un filtre ou quelque chose? Je collecte les données en spécifiant les paramètres @RequestParam dans les méthodes de mon contrôleur. 

48
Doug

Au printemps, vous pouvez échapper au HTML des pages JSP générées par les balises <form>. Cela ferme de nombreuses possibilités d'attaques XSS et peut être effectué automatiquement de trois manières:

Pour l'application complète dans le fichier web.xml:

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

Pour tous les formulaires sur une page donnée dans le fichier lui-même:

<spring:htmlEscape defaultHtmlEscape="true" /> 

Pour chaque formulaire:

<form:input path="someFormField" htmlEscape="true" /> 
52
Tendayi Mawushe

Essayez XSSFilter .

8
Bozho

Lorsque vous essayez d'empêcher XSS, il est important de penser au contexte. Par exemple, comment et quoi échapper est très différent si vous exportez des données à l'intérieur d'une variable dans un extrait de code javascript, par opposition à une sortie de données dans une balise HTML ou un attribut HTML.

J'en ai un exemple ici: http://erlend.oftedal.no/blog/?blogid=91

Consultez également le aide-mémoire de prévention OWASP XSS: http://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet

La réponse courte est donc, assurez-vous d'échapper à la sortie comme suggéré par Tendayi Mawushe, mais soyez particulièrement vigilant lorsque vous exportez des données au format HTML ou javascript.

6
Erlend

J'utilise Hibernate Validator via @Valid pour tous les objets d'entrée (binding et @RequestBody json, voir https://dzone.com/articles/spring-31-valid-requestbody ). Donc, @org.hibernate.validator.constraints.SafeHtml est une bonne solution pour moi.

Hibernate SafeHtmlValidator dépend de org.jsoup, il est donc nécessaire d’ajouter une autre dépendance au projet:

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

Pour haricot User avec champ

@NotEmpty
@SafeHtml
protected String name;

pour tentative de mise à jour avec la valeur <script>alert(123)</script> dans le contrôleur

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

ou

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

est levé BindException pour la liaison et MethodArgumentNotValidException pour @RequestBody avec le message par défaut:

name may have unsafe html content

Validator fonctionne aussi bien pour la liaison que pour la persistance précédente . Les applications peuvent être testées sur http://topjava.herokuapp.com/

6
GKislin

Vérifiez toujours manuellement les méthodes et les balises que vous utilisez, et assurez-vous qu’elles s’échappent toujours (une fois) à la fin. Les frameworks ont de nombreux bugs et différences dans cet aspect.

Un aperçu: http://www.gablog.eu/online/node/91

0
sibidiba

Comment collectez-vous les entrées des utilisateurs en premier lieu? Cette question/réponse peut vous aider si vous utilisez une FormController:

Spring: échappement d'entrée lors de la liaison à la commande

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

la solution au problème XSS consiste à filtrer tous les champs de texte du formulaire au moment de le soumettre.

    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 deuxième classe de code nommée RequestWrapper.Java est:

package 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;
    }

Il ne reste que l'entrée XML dans le fichier 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>

Le/* indique que pour chaque requête émise par un navigateur, il appellera la classe CrossScriptingFilter. Ce qui analysera tous les composants/éléments issus de la requête et remplacera tous les tags javascript mis par hacker par une chaîne vide i.e

0
GAURAV KUMAR GUPTA

Au lieu de s’appuyer uniquement sur <c:out />, il convient également d’utiliser une bibliothèque antixss, qui non seulement encodera, mais supprimera également les scripts malveillants en entrée. L'une des meilleures bibliothèques disponibles est OWASP Antisamy . Il est extrêmement flexible et peut être configuré (à l'aide de fichiers de stratégie xml) selon les besoins. 

Par exemple si une application ne prend en charge que la saisie de texte, le fichier générique policy fourni par OWASP peut être utilisé pour nettoyer et supprimer la plupart des balises HTML. De même, si les éditeurs HTML (tels que tinymce) prennent en charge les applications et ont besoin de tout type de balises HTML, vous pouvez utiliser une stratégie plus souple, telle que le fichier de règles ebay .

0
rjha