Фильтр XSS для форм enctype = "multipart / form-data" - PullRequest
3 голосов
/ 31 января 2012

Я нашел следующий код, предотвращающий xss-атаки.Но у него есть проблема.Он отлично работает с формами, которые имеют enctype="application/x-www-form-urlencoded", но не с формами, которые имеют enctype="multipart/form-data".Я заметил, что getParameterValues() и остальные методы не вызываются.

// --- XSS 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;

/**
 * Servlet Filter implementation class XSSFilter
 */
public class XSSFilter implements Filter {

@SuppressWarnings("unused")
private FilterConfig filterConfig;

/**
 * Default constructor. 
 */
public XSSFilter() {

}

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 {      
    chain.doFilter(new RequestWrapperXSS((HttpServletRequest) request), response);
}

}

// --- RequestWrapperXSS ---//

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

public final class RequestWrapperXSS extends HttpServletRequestWrapper {
public RequestWrapperXSS(HttpServletRequest servletRequest) {       
    super(servletRequest);
}

public String[] getParameterValues(String parameter) {
    System.out.println("entra parameterValues");
    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) {
    System.out.println("entra getParameter");
    String value = super.getParameter(parameter);
    if (value == null) {
        return null;
    }
    return cleanXSS(value);
}

public String getHeader(String name) {
    System.out.println("entra header");
    String value = super.getHeader(name);
    if (value == null)
        return null;
    return cleanXSS(value);
}

private String cleanXSS(String cadena) {
    System.out.println("entra claean XSS");
     StringBuffer sb = new StringBuffer(cadena.length());
        // true if last char was blank
        boolean lastWasBlankChar = false;
        int len = cadena.length();
        char c;

        for (int i = 0; i < len; i++)
            {
            c = cadena.charAt(i);
            if (c == ' ') {
                // blank gets extra work,
                // this solves the problem you get if you replace all
                // blanks with &nbsp;, if you do that you loss 
                // word breaking
                if (lastWasBlankChar) {
                    lastWasBlankChar = false;
                    sb.append("&nbsp;");
                    }
                else {
                    lastWasBlankChar = true;
                    sb.append(' ');
                    }
                }
            else {
                lastWasBlankChar = false;
                //
                // HTML Special Chars
                if (c == '"')
                    sb.append("&quot;");
                else if (c == '&')
                    sb.append("&amp;");
                else if (c == '<')
                    sb.append("&lt;");
                else if (c == '>')
                    sb.append("&gt;");
                else if (c == '\n')
                    // Handle Newline
                    sb.append("&lt;br/&gt;");
                else {
                    int ci = 0xffff & c;
                    if (ci < 160 )
                        // nothing special only 7 Bit
                        sb.append(c);
                    else {
                        // Not 7 Bit use the unicode system
                        sb.append("&#");
                        sb.append(new Integer(ci).toString());
                        sb.append(';');
                        }
                    }
                }
            }
        return sb.toString();


}
}

1 Ответ

2 голосов
/ 31 января 2012

В случае multipart/form-data запросов данные доступны методами getPart() и getParts(), а не getParameter(), getParameterValues() и консорциумами.

Обратите внимание, что эти методы введены в Servlet 3.0 и что в более старых версиях не существует стандартного средства API для извлечения данных из multipart/form-data запросов.Для этого используется defacto API, хорошо известный как Apache Commons FileUpload .


Не связано с конкретной проблемой, это ИМО плохой способ предотвратить XSS.Во время повторного отображения ввода, управляемого пользователем, XSS следует предотвратить на стороне обзора, прямо там , где это может причинить вред.Экранирование перед обработкой ввода, управляемого пользователем, может привести только к двойному экранированию, поскольку это не «стандартный» способ предотвращения XSS.Разработчики должны просто убедиться, что они всегда избегают контролируемых пользователем данных на стороне представления, используя JSTL <c:out> или fn:escapeXml() или любые другие средства, предоставляемые инфраструктурой MVC (JSF, например, по умолчанию экранирует все).

См. Также

...