Comment puis-je empêcher les gens de faire XSS dans Spring MVC?
-
23-09-2019 - |
Question
Que dois-je faire pour éviter XSS dans Spring MVC? En ce moment je suis en train de mettre tous les lieux où le texte de l'utilisateur de sortie I en balises JSTL de <c:out>
ou des fonctions de fn:escapeXml()
, mais cela semble sujette aux erreurs que je pourrais manquer un endroit.
Y at-il un moyen facile systématique pour empêcher cela? Peut-être comme un filtre ou quelque chose? Je collectionne l'entrée en spécifiant des paramètres de @RequestParam
sur mes méthodes de contrôleur.
La solution
Au printemps vous pouvez échapper à la html des pages JSP générées par les balises <form>
. Cette ferme a des pistes de lot pour les attaques XSS, et peut être fait automatiquement de trois façons:
Pour l'ensemble de l'application dans le fichier web.xml
:
<context-param>
<param-name>defaultHtmlEscape</param-name>
<param-value>true</param-value>
</context-param>
Pour toutes les formes sur une page donnée dans le fichier lui-même:
<spring:htmlEscape defaultHtmlEscape="true" />
Pour chaque forme:
<form:input path="someFormField" htmlEscape="true" />
Autres conseils
J'utilise Hibernate Validator via @Valid
pour tous les objets d'entrée (liaison et @RequestBody
json, voir https : //dzone.com/articles/spring-31-valid-requestbody). Alors @org.hibernate.validator.constraints.SafeHtml
est une bonne solution pour moi.
Mise en veille prolongée SafeHtmlValidator
dépend org.jsoup
, il est donc nécessaire d'ajouter une plus dépendances du projet:
<dependency>
<groupId>org.jsoup</groupId>
<artifactId>jsoup</artifactId>
<version>1.10.1</version>
</dependency>
Pour User
de haricot avec le champ
@NotEmpty
@SafeHtml
protected String name;
pour la mise à jour avec la valeur tentative <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 jeté 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, comme avant persistant. Apps pourraient être testés à http://topjava.herokuapp.com/
Lorsque vous essayez d'éviter XSS, il est important de penser au contexte. À titre d'exemple comment et quoi échapper est très différent si vous les données ouputting à l'intérieur d'une variable dans un extrait de code JavaScript par opposition à la sortie de données dans une balise HTML ou un attribut HTML.
J'ai un exemple ici: http://erlend.oftedal.no/blog /? blogid = 91
Voir aussi la fiche OWASP XSS Prévention Cheat: http: //www.owasp .org / index.php / XSS_% 28Cross_Site_Scripting% 29_Prevention_Cheat_Sheet
Donc, la réponse courte est, assurez-vous échapper à la sortie comme suggéré par Tendayi Mawushe, mais prendre des précautions particulières lorsque vous produisez des données dans les attributs HTML ou javascript.
Comment vous percevez l'entrée d'utilisateur en premier lieu? Cette question / réponse peut aider si vous utilisez un FormController
:
Toujours vérifier manuellement les méthodes, les balises que vous utilisez, et assurez-vous qu'ils échappent toujours (une fois) à la fin. Les cadres ont de nombreux bugs et les différences dans cet aspect.
Une vue d'ensemble: http://www.gablog.eu/online/node/91
Au lieu de compter uniquement sur <c:out />
, une bibliothèque AntiXSS doit également être utilisé, ce qui codera non seulement, mais aussi désinfectez script malveillant en entrée. L'une des meilleures bibliothèque disponible est OWASP Antisamy , il est très flexible et peut être configuré (à l'aide des fichiers de stratégie xml) selon l'exigence.
Par exemple, si une application ne supporte que la saisie de texte alors plus générique fichier de stratégie fournie par OWASP peut être utilisé qui assainit et élimine la plupart des balises HTML. De même, si le support des applications éditeurs HTML (comme tinymce) qui ont besoin de toutes sortes de balises HTML, une politique plus souple peut être utilisé comme fichier de stratégie eBay
**To avoid XSS security threat in spring application**
solution au problème XSS est de filtrer tous les champs de texte sous la forme 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 ...............");
}
}
Le code deuxième classe nommée RequestWrapper.java est:
paquetcom.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;
}
La seule chose est restée 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>
/ * indique que pour chaque demande faite à partir du navigateur, il appellera CrossScriptingFilter classe. Ce qui analysera tous les composants / éléments venus de la demande et remplacera toutes les balises javascript posées par pirate avec chaîne vide i.e.