我找到了阻止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 , if you do that you loss
// word breaking
if (lastWasBlankChar) {
lastWasBlankChar = false;
sb.append(" ");
}
else {
lastWasBlankChar = true;
sb.append(' ');
}
}
else {
lastWasBlankChar = false;
//
// HTML Special Chars
if (c == '"')
sb.append(""");
else if (c == '&')
sb.append("&");
else if (c == '<')
sb.append("<");
else if (c == '>')
sb.append(">");
else if (c == '\n')
// Handle Newline
sb.append("<br/>");
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();
}
}
答案 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默认情况下转义所有内容)来逃避视图中的用户控制数据。