当前位置:   article > 正文

解决存储型Xss漏洞_存储型xss解决方案

存储型xss解决方案

近期做的一个项目进行渗透测试,检测代码存在存储型Xss漏洞。例如在界面文本域输入<h2>12345</h2>、<script>alter(12345)</script>这样的值,如果程序未进行处理,会存储至数据库。下次回显会出现异常界面或弹出异常框,如果进行恶意攻击,可能后果不堪设想。

网上搜集的大部分代码都是使用过滤器,并对请求数据进行过滤,重写getParameter(String str)方法。因项目使用的数据结构并非字符串,而是封装的Map,这种方法无法实现该项目的具体需求。反编译看了jar文件,其中有方法getParameterMap()可以使用,只需进行重写即可。

实现该功能,分三步:

  • 第一步,编写过滤器,实现Filter接口;
  • 第二步,继承HttpServletRequestWrapper,重写方法getParameterMap,替换非法字符;
  • 第三步,web.xml注册过滤器.

第一步,编写过滤器,实现Filter接口,代码如下:

  1. package com.xx;
  2. import java.io.IOException;
  3. import javax.servlet.Filter;
  4. import javax.servlet.FilterChain;
  5. import javax.servlet.FilterConfig;
  6. import javax.servlet.ServletException;
  7. import javax.servlet.ServletRequest;
  8. import javax.servlet.ServletResponse;
  9. import javax.servlet.http.HttpServletRequest;
  10. public class XSSFilter implements Filter {
  11. @Override
  12. public void init(FilterConfig arg0) throws ServletException {
  13. }
  14. @Override
  15. public void destroy() {
  16. }
  17. @Override
  18. public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
  19. throws IOException, ServletException {
  20. chain.doFilter(new XssRequestWrappers((HttpServletRequest) request), response);
  21. }
  22. }

第二步,继承HttpServletRequestWrapper,重写方法getParameterMap,代码如下:

  1. package com.xx;
  2. import java.util.HashMap;
  3. import java.util.Iterator;
  4. import java.util.Map;
  5. import java.util.Set;
  6. import javax.servlet.http.HttpServletRequest;
  7. import javax.servlet.http.HttpServletRequestWrapper;
  8. import org.springframework.util.StringUtils;
  9. import org.springframework.web.multipart.MultipartHttpServletRequest;
  10. import org.springframework.web.multipart.commons.CommonsMultipartResolver;
  11. public class XssRequestWrappers extends HttpServletRequestWrapper {
  12. private CommonsMultipartResolver multiparResolver = new CommonsMultipartResolver();
  13. public XssRequestWrappers(HttpServletRequest request) {
  14. super(request);
  15. String type = request.getHeader("Content-Type");
  16. if (!StringUtils.isEmpty(type) && type.contains("multipart/form-data")) {
  17. MultipartHttpServletRequest multipartHttpServletRequest = multiparResolver.resolveMultipart(request);
  18. Map<String, String[]> stringMap = multipartHttpServletRequest.getParameterMap();
  19. if (!stringMap.isEmpty()) {
  20. for (String key : stringMap.keySet()) {
  21. String value = multipartHttpServletRequest.getParameter(key);
  22. XSSUtils.stripXSS(key);
  23. XSSUtils.stripXSS(value);
  24. }
  25. }
  26. super.setRequest(multipartHttpServletRequest);
  27. }
  28. }
  29. @Override
  30. public String[] getParameterValues(String parameter) {
  31. String[] values = super.getParameterValues(parameter);
  32. if (values == null) {
  33. return null;
  34. }
  35. int count = values.length;
  36. String[] encodedValues = new String[count];
  37. for (int i = 0; i < count; i++) {
  38. encodedValues[i] = XSSUtil.stripXSS(values[i]);
  39. }
  40. return encodedValues;
  41. }
  42. @Override
  43. public String getParameter(String parameter) {
  44. String value = super.getParameter(parameter);
  45. return XSSUtils.stripXSS(value);
  46. }
  47. @Override
  48. public String getHeader(String name) {
  49. String value = super.getHeader(name);
  50. return XSSUtils.stripXSS(value);
  51. }
  52. @Override
  53. public Map<String, String[]> getParameterMap() {
  54. Map<String, String[]> map1 = super.getParameterMap();
  55. Map<String, String[]> escapseMap = new HashMap<String, String[]>();
  56. Set<String> keys = map1.keySet();
  57. for (String key : keys) {
  58. String[] valArr = map1.get(key);
  59. if (valArr != null && valArr.length > 0) {
  60. String[] escapseValArr = new String[valArr.length];
  61. for (int i = 0; i < valArr.length; i++) {
  62. String escapseVal = XSSUtils.striptXSS(valArr[i]);
  63. escapseValArr[i] = escapseVal;
  64. }
  65. escapseMap.put(key, escapseValArr);
  66. }
  67. }
  68. return escapseMap;
  69. }
  70. }

此处写了一个工具类XSSUtils,现在的做法是替换成空字符,CSDN的是进行转义,比如文字开头的"<"转成<。代码如下:

  1. package com.xx;
  2. import java.util.regex.Pattern;
  3. public class XSSUtils {
  4. public static String striptXSS(String value) {
  5. if (value != null) {
  6. value = value.replaceAll("", "");
  7. Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
  8. value = scriptPattern.matcher(value).replaceAll("");
  9. scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
  10. value = scriptPattern.matcher(value).replaceAll("");
  11. scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
  12. value = scriptPattern.matcher(value).replaceAll("");
  13. scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
  14. value = scriptPattern.matcher(value).replaceAll("");
  15. scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
  16. value = scriptPattern.matcher(value).replaceAll("");
  17. scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
  18. value = scriptPattern.matcher(value).replaceAll("");
  19. scriptPattern = Pattern.compile("e­xpression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
  20. value = scriptPattern.matcher(value).replaceAll("");
  21. scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
  22. value = scriptPattern.matcher(value).replaceAll("");
  23. scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
  24. value = scriptPattern.matcher(value).replaceAll("");
  25. scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL);
  26. value = scriptPattern.matcher(value).replaceAll("");
  27. scriptPattern = Pattern.compile(".*<.*", Pattern.CASE_INSENSITIVE );
  28. value = scriptPattern.matcher(value).replaceAll("");
  29. }
  30. return value;
  31. }
  32. }

第三步,web.xml注册过滤器,代码如下:

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

代码完。此代码贴在这里的没加注释,需要使用的,最好在项目中添加注释。利人利己。

扩展:后期可对这个功能进行扩展,做成可配置的,比如请求报文的头文件无需过滤;对不同的项目使用的不同的数据结构进行参数化;对这个需要过滤的文件格式进行参数配置,方便生产环境的突发意外情况。

思考:是否会有一种在web.xml里配置即可解决该问题的方法,类似CharacterEncodingFilter这样的,便于开发者操作。

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

闽ICP备14008679号