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

Que dois-je faire pour empêcher XSS dans Spring MVC? En ce moment, je ne fais que placer tous les endroits où je fn:escapeXml() texte utilisateur dans les balises JSTL ou les fonctions fn:escapeXml() , mais cela semble sujet aux erreurs car je risque de rater une place.

Existe-t-il un moyen simple et systématique d’éviter cela? Peut-être comme un filtre ou quelque chose? Je collecte des données en spécifiant les parameters @RequestParam sur mes méthodes de contrôleur.

Au spring, vous pouvez échapper au HTML à partir des pages JSP générées par les balises

. Cela ferme de nombreuses voies pour les attaques XSS et peut se faire automatiquement de trois manières:

Pour toute l’application du fichier web.xml :

  defaultHtmlEscape true  

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

  

Pour chaque formulaire:

  

Essayez XSSFilter .

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 envoyez des données dans une variable dans un extrait de code JavaScript, par opposition à la sortie de données dans une balise HTML ou un atsortingbut HTML.

J’ai un exemple de ceci ici: http://erlend.oftedal.no/blog/?blogid=91

Consultez également la feuille de sortingche de prévention OWASP XSS: http://www.owasp.org/index.php/XSS_%28Cross_Site_Scripting%29_Prevention_Cheat_Sheet

Donc, la réponse courte est, assurez-vous d’échapper à la sortie comme suggéré par Tendayi Mawushe, mais prenez des précautions particulières lorsque vous produisez des données en atsortingbuts HTML ou javascript.

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

Hibernate SafeHtmlValidator dépend d’ org.jsoup , il est donc nécessaire d’append une dépendance de projet supplémentaire:

  org.jsoup jsoup 1.10.1  

Pour bean User avec champ

 @NotEmpty @SafeHtml protected Ssortingng name; 

pour la tentative de mise à jour avec la valeur 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ée BindException pour la liaison et MethodArgumentNotValidException pour @RequestBody avec le message par défaut:

 name may have unsafe html content 

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

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

Spring: échapper l’entrée lors de la liaison à la commande

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

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

Au lieu de compter uniquement sur , une bibliothèque antixss devrait également être utilisée, qui non seulement encodera, mais aussi purifiera les scripts malveillants en entrée. L’une des meilleures bibliothèques disponibles est OWASP Antisamy , très flexible et configurable (à l’aide de fichiers de règles xml) selon les besoins.

Par exemple, si une application ne prend en charge que la saisie de texte, la plupart des fichiers de politique génériques fournis par OWASP peuvent être utilisés, ce qui désinfecte et supprime la plupart des balises HTML. De même, si l’application prend en charge les éditeurs HTML (tels que tinymce) qui nécessitent toutes sortes de balises html, une politique plus flexible peut être utilisée, telle que le fichier de stratégie ebay.

 **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 la soumission du formulaire.

  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 seconde 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 Ssortingng[] getParameterValues(Ssortingng parameter) { logger.info("InarameterValues .. parameter ......."); Ssortingng[] values = super.getParameterValues(parameter); if (values == null) { return null; } int count = values.length; Ssortingng[] encodedValues = new Ssortingng[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).*?", ""); value = value.replaceAll("(?i).*?", ""); value = value.replaceAll("(?i)<.*?javascript:.*?>.*?", ""); value = value.replaceAll("(?i)<.*?\\s+on.*?>.*?", ""); //value = value.replaceAll("", ""); logger.info("OutnXSS RequestWrapper ........ value ......." + value); return value; } 

La seule chose qui rest est l’entrée XML dans le fichier web.xml:

   XSS XSS  com.filter.CrossScriptingFilter   XSS /*  

Le / * indique que pour chaque requête faite depuis le navigateur, il appellera la classe CrossScriptingFilter. Qui va parsingr tous les composants / éléments provenant de la requête & va remplacer tous les tags javascript mis par le pirate avec une chaîne vide, c’est-à-dire