Um aplicativo da web existente está sendo executado no Tomcat 4.1. Há um problema de XSS com uma página, mas não consigo modificar a fonte. Decidi escrever um filtro de servlet para limpar o parâmetro antes de ser visto pela página.
Eu gostaria de escrever uma classe Filter como esta:
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) {
}
}
Mas ServletRequest.setParameter
não existe.
Como posso alterar o valor do parâmetro do pedido antes de passar o pedido pela cadeia?
java
servlet-filters
Jeremy Stein
fonte
fonte
Respostas:
Como você observou
HttpServletRequest
, não tem um método setParameter. Isso é proposital, já que a classe representa a solicitação como ela veio do cliente, e modificar o parâmetro não representaria isso.Uma solução é usar a
HttpServletRequestWrapper
classe, que permite agrupar uma solicitação com outra. Você podegetParameter
criar uma subclasse disso e substituir o método para retornar seu valor higienizado. Você pode então passar essa solicitação encapsulada para, emchain.doFilter
vez da solicitação original.É um pouco feio, mas é o que a API do servlet diz que você deve fazer. Se você tentar passar qualquer outra coisa para
doFilter
, alguns contêineres de servlet reclamarão que você violou a especificação e se recusarão a lidar com isso.Uma solução mais elegante é mais trabalhosa - modifique o servlet / JSP original que processa o parâmetro, de forma que ele espere um atributo de solicitação em vez de um parâmetro. O filtro examina o parâmetro, limpa-o e define o atributo (usando
request.setAttribute
) com o valor limpo. Sem subclasses, sem spoofing, mas exige que você modifique outras partes de seu aplicativo.fonte
<property name="username" value="[email protected]" /> //Change email on logging in <property name="password" value="*********" />//Change Password on logging in
Para registro, aqui está a aula que acabei escrevendo:
fonte
Escreva uma classe simples
HttpServletRequestWrapper
com subcálculo com um método getParameter () que retorna a versão sanitizada da entrada. Em seguida, passe uma instância de seuHttpServletRequestWrapper
para emFilter.doChain()
vez do objeto de solicitação diretamente.fonte
Tive o mesmo problema (alterando um parâmetro da solicitação HTTP no Filtro). Acabei usando um
ThreadLocal<String>
. NoFilter
tenho:No meu processador de solicitação (
HttpServlet
controlador JSF ou qualquer outro processador de solicitação HTTP), recebo o valor do thread atual de volta:Vantagens:
HttpServletRequestWrapper
clichêrequest.setAttribute(String,Object)
, ou seja, você pode acessar a variável em outros filtros.Desvantagens:
java.util.stream.Stream.parallel
,java.util.concurrent.Future
,java.lang.Thread
.Algumas notas laterais:
O servidor possui um pool de threads para processar as solicitações HTTP. Uma vez que esta é uma piscina:
if (value!=null) { THREAD_VARIABLE.set(value);}
porque você reutilizará o valor da solicitação HTTP anterior quandovalue
é nulo: os efeitos colaterais são garantidos).HttpSession.setAttribute()
@RequestScoped
usa internamente umThreadLocal
, mas usar oThreadLocal
é mais versátil: você pode usá-lo em contêineres não JEE / CDI (por exemplo, em aplicativos JRE multithread)fonte
@RequestScoped
faz o mesmo internamente). A solicitação múltipla verá o mesmo tópico = não (ou pelo menos você não tem garantia). Eu editei a resposta para precisar esses pontos.Isso é o que eu acabei fazendo
fonte
Com base em todos os seus comentários, aqui está minha proposta que funcionou para mim:
observação: queryString () requer o processamento de TODOS os valores para cada KEY e não se esqueça de encodeUrl () ao adicionar seus próprios valores de parâmetros, se necessário
Como limitação, se você chamar request.getParameterMap () ou qualquer método que chame request.getReader () e começar a ler, você evitará outras chamadas para request.setCharacterEncoding (...)
fonte
Você pode usar Regular Expression for Sanitization. Filtro interno antes de chamar o método chain.doFilter (solicitação, resposta) , chame este código. Aqui está o código de amostra:
fonte
Experimente
request.setAttribute("param",value);
. Funcionou bem para mim.Encontre este exemplo de código:
fonte