Protection contre les XSS (Cross-site scripting) avec Java Spring

Avant de pouvoir utiliser Spring Security vous devez ajouter les dépendances suivantes :

<dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
          <groupId>org.springframework.security</groupId>
          <artifactId>spring-security-test</artifactId>
          <scope>test</scope>
</dependency>

Configuration HTTP pour Spring Security

Spring Security se charge d'insérer les en-têtes de sécurité HTTP.

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 * 
 * Configuration pour HTTP Spring Security
 *
 */

@EnableWebSecurity
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		/* Active la protection contre XSS : ajoute les en-têtes X-XSS-Protection */
		http.headers().xssProtection();
	}
}

Convertisseur de caractères spéciaux en entités HTML

Chaque caractère spécial jugé dangereux sera converti en entité HTML.

Il est possible d'ajouter plus de caractères à la liste.

import org.springframework.stereotype.Component;

import com.fasterxml.jackson.core.JsonpCharacterEscapes;
import com.fasterxml.jackson.core.SerializableString;
import com.fasterxml.jackson.core.io.CharacterEscapes;
import com.fasterxml.jackson.core.io.SerializedString;

/**
 * 
 * Échappe tous les caractères HTML en entités
 *
 */

/* Component pour l'annotation @Autowired */
@Component
public class HTMLCharacterEscapes extends JsonpCharacterEscapes {

	private static final long serialVersionUID = 8087596655104568289L;

	@Override
	public int[] getEscapeCodesForAscii() {
		/* Tous les caractères ASCII échappés pour le JSON */
		int[] escapeDefinitions = CharacterEscapes.standardAsciiEscapesForJSON();

		/* Personnalisation de l'échappement pour les caractères suivants */
		escapeDefinitions['<'] = CharacterEscapes.ESCAPE_CUSTOM;
		escapeDefinitions['>'] = CharacterEscapes.ESCAPE_CUSTOM;
		escapeDefinitions['&'] = CharacterEscapes.ESCAPE_CUSTOM;
		escapeDefinitions['"'] = CharacterEscapes.ESCAPE_CUSTOM;
		escapeDefinitions['\''] = CharacterEscapes.ESCAPE_CUSTOM;

		/*
		 * Retourne le tableau avec les nouvelles règles d'échappement pour les
		 * caracètres au dessus
		 */
		return escapeDefinitions;
	}

	@Override
	public SerializableString getEscapeSequence(int ch) {
		/* Conversion des caractères dangereux en entité HTML */
		switch (ch) {

		case '&':
			return new SerializedString("&amp;");
		case '<':
			return new SerializedString("&lt;");
		case '>':
			return new SerializedString("&gt;");
		case '\"':
			return new SerializedString("&#34;");
		case '\'':
			return new SerializedString("&#39;");

		default:
			/* Retourne le caractère sans modification */
			return super.getEscapeSequence(ch);
		}
	}

}

Configuration Anti XSS de Jackson

Une fois notre implémentation de classe CharacterEscapes, nous pouvons l'injecter dans la configuration de Jackson.

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;

import com.fasterxml.jackson.core.io.CharacterEscapes;
import com.fasterxml.jackson.databind.ObjectMapper;

/**
 * 
 * Configuration Anti XSS (échappement du HTML) pour Jackson
 *
 */

@Configuration
public class AntiXSSJacksonConfiguration {

	/* injecte une implémentation de CharacterEscapes */
	@Autowired
	CharacterEscapes characterEscapes;

	/* injecte ObjectMapper de Jackson */
	@Autowired
	public void configure(ObjectMapper mapper) {
		mapper.getFactory().setCharacterEscapes(characterEscapes);
	}

}

Résultat dans une application web :

Commentaires