【现象】:form 提交可执行的HTML 标签或JS 代码成功。比如:"/><script>alert('啦啦啦啦啦啦')</script><!- 或者
<img src='1.jpg' οnlοad=alert(1)>
【后果】:盗取用户cookie 信息、网页钓鱼攻击、修改网站代码、网站重定向。
【原因】: 提交的内容未做任何处理就入库。
【解决方案】: 对所有入库的数据转码HtmlUtils.htmlEscape,增加加Filter
【代码实现】
1.定义一个过滤器
import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
/**
* @Description: 转义所有form数据的过滤器
*/
public class XSSFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
}
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
filterChain.doFilter(new XSSRequestWrapper(request) , servletResponse);
}
@Override
public void destroy() {
}
}
2.写一个包装类
import org.springframework.web.util.HtmlUtils;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
/**
* @Auther: Lee
* @Date: 2018-08-14
* @Description: request的包装类
*/
public class XSSRequestWrapper extends HttpServletRequestWrapper {
public XSSRequestWrapper(HttpServletRequest request) {
super(request);
}
@Override
public String[] getParameterValues(String name) {
//获取所有参数值的集合
String[] results = this.getParameterMap().get(name);
if (results != null && results.length > 0) {
int length = results.length;
for (int i = 0; i < length; i++) {
//过滤参数值
results[i] = HtmlUtils.htmlEscape(results[i]);
}
return results;
}
return null;
}
}
3.编写一个URL过滤器,得到所有需要过滤的URL的集合
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
/**
* 从springContext中获取所有ControllerMapping 并过滤出含有save的url,这些url的请求会经过TransferFilter
*/
@Component
public class FilterUrlMapping {
@Autowired
ApplicationContext applicationContext;
//@Bean
public Set<String> allUrlMappings() {
Set<String> result = new HashSet();
RequestMappingHandlerMapping rmhp = applicationContext.getBean(RequestMappingHandlerMapping.class);
Map<RequestMappingInfo, HandlerMethod> map = rmhp.getHandlerMethods();
for (RequestMappingInfo info : map.keySet()) {
//getMatchingPatterns优化
result.add(info.getPatternsCondition().toString().replace("[", "").replace("]", ""));
}
return result;
}
@Bean
public FilterRegistrationBean filterRegistration() {
FilterRegistrationBean filterRegistration = new FilterRegistrationBean();
filterRegistration.setFilter(new XSSFilter());//添加过滤器
Set<String> allSaveUrlPattern = allUrlMappings();//emsBasePrivilegeDao.findAllSaveUrlPattern();
if(CollectionUtils.isEmpty(allSaveUrlPattern)){
return filterRegistration;
}
String pattern = "/*.*save.*";// save
Set<String> urlPatterns = new LinkedHashSet();
for (String saveUrlPattern : allSaveUrlPattern) {
if (Pattern.matches(pattern, saveUrlPattern)) {
urlPatterns.add(saveUrlPattern);
}
}
filterRegistration.setUrlPatterns(urlPatterns);
filterRegistration.setName("XSSFilter");//
return filterRegistration;
}
}