120 votes

Modifier les paramètres de la requête avec filtre de servlet

Une application web existante est en cours d'exécution sur Tomcat 4.1. Il y a un XSS problème avec une page, mais je ne peux pas modifier le code source. J'ai décidé d'écrire un filtre de servlet pour assainir le paramètre avant qu'il est perçu par la page.

Je voudrais écrire une classe de Filtre comme ceci:

import java.io.*;
import javax.servlet.*;

public final class XssFilter implements Filter {

  public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
      throws IOException, ServletException
  {
    String badValue = request.getParameter("dangerousParamName");
    String goodValue = sanitize(badValue);
    request.setParameter("dangerousParamName", goodValue);
    chain.doFilter(request, response);
  }

  public void destroy() {
  }

  public void init(FilterConfig filterConfig) {
  }
}

Mais ServletRequest.setParameter n'existe pas.

Comment puis-je changer la valeur du paramètre de la requête avant de transmettre la demande de la chaîne?

139voto

skaffman Points 197885

Comme vous l'avez remarqué HttpServletRequest n'ont pas de méthode setParameter. C'est délibéré, car la classe représente la demande comme il est venu de la part du client, et en modifiant le paramètre ne représentent pas que.

Une solution consiste à utiliser l' HttpServletRequestWrapper classe, ce qui vous permet de vous envelopper l'un demande à l'autre. Vous pouvez sous-classe, et de remplacer l' getParameter méthode pour retourner votre aseptisé de la valeur. Vous pouvez ensuite passer qui a enveloppé la demande d' chain.doFilter , au lieu de l'original de la demande.

C'est un peu moche, mais qu'est ce que la servlet API dit que vous devriez faire. Si vous essayez de passer quelque chose d'autre pour doFilter, certains conteneurs de servlet va se plaindre que vous avez violé les spec, et refuse de le gérer.

Une solution plus élégante est plus de travail, - modifier l'original de servlet/JSP qui traite le paramètre, de sorte qu'il s'attend à une demande de l'attribut au lieu d'un paramètre. Le filtre examine le paramètre, désinfecte, et définit l'attribut (à l'aide d' request.setAttribute) avec la aseptisé de la valeur. Pas de sous-classement, pas d'usurpation d'identité, mais ne vous oblige à modifier d'autres parties de votre application.

79voto

Jeremy Stein Points 8343

Pour l'enregistrement, ici, c'est la classe j'ai fini par écrire:

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 javax.servlet.http.HttpServletRequestWrapper;

public final class XssFilter implements Filter {

    static class FilteredRequest extends HttpServletRequestWrapper {

    	/* These are the characters allowed by the Javascript validation */
    	static String allowedChars = "+-0123456789#*";

    	public FilteredRequest(ServletRequest request) {
    		super((HttpServletRequest)request);
    	}

    	public String sanitize(String input) {
    		String result = "";
    		for (int i = 0; i < input.length(); i++) {
    			if (allowedChars.indexOf(input.charAt(i)) >= 0) {
    				result += input.charAt(i);
    			}
    		}
    		return result;
    	}

    	public String getParameter(String paramName) {
    		String value = super.getParameter(paramName);
    		if ("dangerousParamName".equals(paramName)) {
    			value = sanitize(value);
    		}
    		return value;
    	}

    	public String[] getParameterValues(String paramName) {
    		String values[] = super.getParameterValues(paramName);
    		if ("dangerousParamName".equals(paramName)) {
    			for (int index = 0; index < values.length; index++) {
    				values[index] = sanitize(values[index]);
    			}
    		}
    		return values;
    	}
    }

    public void doFilter(ServletRequest request, ServletResponse response,
    		FilterChain chain) throws IOException, ServletException {
    	chain.doFilter(new FilteredRequest(request), response);
    }

    public void destroy() {
    }

    public void init(FilterConfig filterConfig) {
    }
}

11voto

Asaph Points 56989

Écrire une classe simple qui subcalsses HttpServletRequestWrapper avec une méthode getParameter() qui retourne la version aseptisée de l'entrée. Puis de passer une instance de votre HttpServletRequestWrapper de Filter.doChain() à la place de l'objet de la requête directement.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X