XSS过滤到enctype =“multipart / form-data”表单

时间:2012-01-31 13:30:37

标签: xss servlet-filters multipartform-data

我找到了阻止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 个答案:

答案 0 :(得分:2)

如果发出multipart/form-data次请求,则数据可通过getPart()getParts()方法获取,而不是getParameter()getParameterValues()和配置。

请注意,这些方法是在Servlet 3.0中引入的,而在旧版本中,没有任何标准API工具可以从multipart/form-data请求中提取数据。用于它的事实API是众所周知的Apache Commons FileUpload


对具体问题

无关,这是IMO防止XSS的一种坏方法。在重新显示用户控制的输入期间,应在视图侧阻止XSS,在那里可能会造成伤害。在处理用户控制的输入之前进行转义只会冒双重转义的风险,因为它不是XSS预防的“标准”方式。开发人员应该确保他们总是使用JSTL <c:out>fn:escapeXml()或任何其他MVC框架提供的工具(例如JSF默认情况下转义所有内容)来逃避视图中的用户控制数据。

另见