当前位置:   article > 正文

XSS安全漏洞修复解决方案_xss修复建议

xss修复建议

背景:等保测评公司针对我系统进行了一次渗透测试,并发现存在XSS漏洞,现记录修复过程。

框架:SSM。

全站XSS:

漏洞风险等级:中危

涉及页面:全站存在内容输入处

漏洞描述:所有模块可以修改内容处存在XSS,填入恶意代码后触发。 

修复建议:过滤所有输入内容。(防止恶意弹窗/跨站脚本/过滤敏感字符/违法信息等)

 

 

解决方案

列举方案1:写个DispatcherServlet

  1. import javax.servlet.http.HttpServletRequest;
  2. import org.springframework.stereotype.Controller;
  3. import org.springframework.web.method.HandlerMethod;
  4. import org.springframework.web.servlet.DispatcherServlet;
  5. import org.springframework.web.servlet.HandlerExecutionChain;
  6. @SuppressWarnings("serial")
  7. public class DispatcherServletWrapper extends DispatcherServlet {
  8. @Override
  9. protected HandlerExecutionChain getHandler(HttpServletRequest request) throws Exception {
  10. HandlerExecutionChain chain = super.getHandler(request);
  11. Object handler = chain.getHandler();
  12. if (!(handler instanceof HandlerMethod)) {
  13. return chain;
  14. }
  15. HandlerMethod hm = (HandlerMethod)handler;
  16. if (!hm.getBeanType().isAnnotationPresent(Controller.class)) {
  17. return chain;
  18. }
  19. //仅处理@Controller注解的Bean
  20. return new HandlerExecutionChainWrapper(chain,request,getWebApplicationContext());
  21. }
  22. }

在getHandler中返回HandlerExecutionChainWrapper

  1. import java.lang.reflect.Field;
  2. import java.lang.reflect.Method;
  3. import java.util.ArrayList;
  4. import java.util.List;
  5. import javax.servlet.http.HttpServletRequest;
  6. import org.springframework.beans.factory.BeanFactory;
  7. import org.springframework.cglib.proxy.Enhancer;
  8. import org.springframework.cglib.proxy.MethodInterceptor;
  9. import org.springframework.cglib.proxy.MethodProxy;
  10. import org.springframework.util.ReflectionUtils;
  11. import org.springframework.util.ReflectionUtils.FieldCallback;
  12. import org.springframework.util.ReflectionUtils.FieldFilter;
  13. import org.springframework.web.method.HandlerMethod;
  14. import org.springframework.web.servlet.HandlerExecutionChain;
  15. import org.springframework.web.util.HtmlUtils;
  16. public class HandlerExecutionChainWrapper extends HandlerExecutionChain {
  17. private BeanFactory beanFactory;
  18. private HttpServletRequest request;
  19. private HandlerMethod handlerWrapper;
  20. private byte[] lock = new byte[0];
  21. public HandlerExecutionChainWrapper(HandlerExecutionChain chain,
  22. HttpServletRequest request,
  23. BeanFactory beanFactory) {
  24. super(chain.getHandler(),chain.getInterceptors());
  25. this.request = request;
  26. this.beanFactory = beanFactory;
  27. }
  28. @Override
  29. public Object getHandler() {
  30. if (handlerWrapper != null) {
  31. return handlerWrapper;
  32. }
  33. synchronized (lock) {
  34. if (handlerWrapper != null) {
  35. return handlerWrapper;
  36. }
  37. HandlerMethod superMethodHandler = (HandlerMethod)super.getHandler();
  38. Object proxyBean = createProxyBean(superMethodHandler);
  39. handlerWrapper = new HandlerMethod(proxyBean,superMethodHandler.getMethod());
  40. return handlerWrapper;
  41. }
  42. }
  43. /**
  44. * 为Controller Bean创建一个代理实例,以便用于 实现调用真实Controller Bean前的切面拦截
  45. * 用以过滤方法参数中可能的XSS注入
  46. * @param handler
  47. * @return
  48. */
  49. private Object createProxyBean(HandlerMethod handler) {
  50. try {
  51. Enhancer enhancer = new Enhancer();
  52. enhancer.setSuperclass(handler.getBeanType());
  53. Object bean = handler.getBean();
  54. if (bean instanceof String) {
  55. bean = beanFactory.getBean((String)bean);
  56. }
  57. ControllerXssInterceptor xss = new ControllerXssInterceptor(bean);
  58. xss.setRequest(this.request);
  59. enhancer.setCallback(xss);
  60. return enhancer.create();
  61. }catch(Exception e) {
  62. throw new IllegalStateException("为Controller创建代理失败:"+e.getMessage(), e);
  63. }
  64. }
  65. public static class ControllerXssInterceptor implements MethodInterceptor {
  66. private Object target;
  67. private HttpServletRequest request;
  68. private List<String> objectMatchPackages;
  69. public ControllerXssInterceptor(Object target) {
  70. this.target = target;
  71. this.objectMatchPackages = new ArrayList<String>();
  72. this.objectMatchPackages.add("com.jwell");
  73. }
  74. public void setRequest(HttpServletRequest request) {
  75. this.request = request;
  76. }
  77. @Override
  78. public Object intercept(Object obj, Method method, Object[] args,
  79. MethodProxy proxy)
  80. throws Throwable {
  81. //对Controller的方法参数进行调用前处理
  82. //过滤String类型参数中可能存在的XSS注入
  83. if (args != null) {
  84. for (int i=0;i<args.length;i++) {
  85. if (args[i]==null)
  86. continue;
  87. if (args[i] instanceof String) {
  88. args[i] = stringXssReplace((String)args[i]);
  89. continue;
  90. }
  91. for(String pk:objectMatchPackages) {
  92. if (args[i].getClass().getName().startsWith(pk)) {
  93. objectXssReplace(args[i]);
  94. break;
  95. }
  96. }
  97. }
  98. }
  99. return method.invoke(target, args);
  100. }
  101. private String stringXssReplace(String argument) {
  102. return HtmlUtils.htmlEscape(argument);
  103. }
  104. private void objectXssReplace(final Object argument) {
  105. if (argument == null)
  106. return;
  107. ReflectionUtils.doWithFields(argument.getClass(), new FieldCallback(){
  108. @Override
  109. public void doWith(Field field) throws IllegalArgumentException, IllegalAccessException {
  110. ReflectionUtils.makeAccessible(field);
  111. String fv = (String)field.get(argument);
  112. if (fv != null) {
  113. String nv = HtmlUtils.htmlEscape(fv);
  114. field.set(argument, nv);
  115. }
  116. }
  117. }, new FieldFilter(){
  118. @Override
  119. public boolean matches(Field field) {
  120. boolean typeMatch = String.class.equals(field.getType());
  121. if (request!=null && "GET".equals(request.getMethod())) {
  122. boolean requMatch = request.getParameterMap().containsKey(field.getName());
  123. return typeMatch && requMatch;
  124. }
  125. return typeMatch;
  126. }
  127. });
  128. }
  129. }

web.xml 替换DispatcherServlet

  1. <!--将org.springframework.web.servlet.DispatcherServlet替换成自己的DispatcherServletWrapper -->
  2. <servlet>
  3. <servlet-name>SpringMVC</servlet-name>
  4. <!--安全测试 -->
  5. <!-- <servlet-class>com.xx.xx.bmms.web.filter.DispatcherServletWrapper</servlet-class> -->
  6. <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  7. <init-param>
  8. <param-name>contextConfigLocation</param-name>
  9. <param-value>classpath:spring-mvc-bpbj.xml</param-value>
  10. </init-param>
  11. <load-on-startup>1</load-on-startup>
  12. <async-supported>true</async-supported>
  13. </servlet>

再次测试,已解决,不过此方案本人不推荐,原因(会影响业务,谁用谁知道 哈哈~)

列举方案2:写个filter(推荐)

  1. import java.io.IOException;
  2. import javax.servlet.Filter;
  3. import javax.servlet.FilterChain;
  4. import javax.servlet.FilterConfig;
  5. import javax.servlet.ServletException;
  6. import javax.servlet.ServletRequest;
  7. import javax.servlet.ServletResponse;
  8. import javax.servlet.http.HttpServletRequest;
  9. public class XssFilter implements Filter{
  10. FilterConfig filterConfig = null;
  11. @Override
  12. public void destroy() {
  13. // TODO Auto-generated method stub
  14. this.filterConfig = null;
  15. }
  16. @Override
  17. public void doFilter(ServletRequest request, ServletResponse response,
  18. FilterChain chain) throws IOException, ServletException {
  19. // TODO Auto-generated method stub
  20. chain.doFilter(new XssShellInterceptor( (HttpServletRequest) request), response);
  21. }
  22. @Override
  23. public void init(FilterConfig filterConfig) throws ServletException {
  24. // TODO Auto-generated method stub
  25. this.filterConfig = filterConfig;
  26. }

XssShellInterceptor类(HttpServletRequestWrapper

  1. import javax.servlet.http.HttpServletRequest;
  2. import javax.servlet.http.HttpServletRequestWrapper;
  3. public class XssShellInterceptor extends HttpServletRequestWrapper{
  4. public XssShellInterceptor(HttpServletRequest request) {
  5. super(request);
  6. }
  7. public String[] getParameterValues(String parameter) {
  8. String[] values = super.getParameterValues(parameter);
  9. if (values==null) {
  10. return null;
  11. }
  12. int count = values.length;
  13. String[] encodedValues = new String[count];
  14. for (int i = 0; i < count; i++) {
  15. encodedValues[i] = cleanXSS(values[i]);
  16. }
  17. return encodedValues;
  18. }
  19. public String getParameter(String parameter) {
  20. String value = super.getParameter(parameter);
  21. if (value == null) {
  22. return null;
  23. }
  24. return cleanXSS(value);
  25. }
  26. public String getHeader(String name) {
  27. String value = super.getHeader(name);
  28. if (value == null)
  29. return null;
  30. return cleanXSS(value);
  31. }
  32. //过滤规则 目前我只配了过滤 script
  33. private String cleanXSS(String value) {
  34. //value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
  35. //value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;");
  36. //value = value.replaceAll("'", "& #39;");
  37. //value = value.replaceAll("eval\\((.*)\\)", "");
  38. value = value.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
  39. value = value.replaceAll("script", "");
  40. return value;
  41. }
  42. }

web.xml 添加filter

  1. <filter>
  2. <filter-name>XssFilter</filter-name>
  3. <filter-class>com.xx.xx.bmms.web.filter.XssFilter</filter-class>
  4. </filter>
  5. <filter-mapping>
  6. <filter-name>XssFilter</filter-name>
  7. <url-pattern>/*</url-pattern>
  8. </filter-mapping>

再次测试,已解决。注意:如果web.xml中有多个filter 注意执行顺序。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/羊村懒王/article/detail/338571
推荐阅读
相关标签
  

闽ICP备14008679号