XSS跨站脚本攻击

跨站脚本攻击(Cross Site Script为了区别于CSS简称为XSS)指的是恶意攻击者往Web页面里插入恶意html代码,当用户浏览该页之时,嵌入其中Web里面的html代码会被执行,从而达到恶意用户的特殊目的。

类别:

常见的 XSS 攻击有三种:反射型、DOM-based 型、存储型。 其中反射型、DOM-based 型可以归类为非持久型 XSS 攻击,存储型归类为持久型 XSS 攻击。

1.反射型

反射型 XSS 一般是攻击者通过特定手法(如电子邮件),诱使用户去访问一个包含恶意代码的 URL,当受害者点击这些专门设计的链接的时候,恶意代码会直接在受害者主机上的浏览器执行。

对于访问者而言是一次性的,具体表现在我们把我们的恶意脚本通过 URL 的方式传递给了服务器,而服务器则只是不加处理的把脚本“反射”回访问者的浏览器而使访问者的浏览器执行相应的脚本。反射型 XSS 的触发有后端的参与,要避免反射性 XSS,必须需要后端的协调,后端解析前端的数据时首先做相关的字串检测和转义处理。

此类 XSS 通常出现在网站的搜索栏、用户登录口等地方,常用来窃取客户端 Cookies 或进行钓鱼欺骗。

2.DOM-based 型

客户端的脚本程序可以动态地检查和修改页面内容,而不依赖于服务器端的数据。例如客户端如从 URL 中提取数据并在本地执行,如果用户在客户端输入的数据包含了恶意的 JavaScript 脚本,而这些脚本没有经过适当的过滤和消毒,那么应用程序就可能受到 DOM-based XSS 攻击。需要特别注意以下的用户输入源 document.URL、 location.hash、 location.search、 document.referrer 等。

3.存储型

攻击者事先将恶意代码上传或储存到漏洞服务器中,只要受害者浏览包含此恶意代码的页面就会执行恶意代码。这就意味着只要访问了这个页面的访客,都有可能会执行这段恶意脚本,因此储存型XSS的危害会更大。

存储型 XSS 一般出现在网站留言、评论、博客日志等交互处,恶意脚本存储到客户端或者服务端的数据库中。

解决方案:参考:https://blog.csdn.net/Ideality_hunter/article/details/80621138

方法一:使用过滤器

1.NewXssFilter

 1 public class NewXssFilter  implements Filter {
 2 
 3     FilterConfig filterConfig = null;
 4 
 5     @Override
 6     public void destroy() {
 7         this.filterConfig = null;
 8     }
 9 
10     @Override
11     public void doFilter(ServletRequest request, ServletResponse response,
12             FilterChain chain) throws IOException, ServletException {
13         String path = ((HttpServletRequest) request).getContextPath();
14 //        String basePath = request.getScheme() + "://" + request.getServerName()
15 //                + ":" + request.getServerPort() + path + "/";
16         
17         String basePath = request.getServerName();
18         
19         
20         
21         // HTTP 头设置 Referer过滤
22         String referer = ((HttpServletRequest) request).getHeader("Referer"); // REFRESH
23         
24         NewXssHttpServletRequestWrapper xssRequest = null;
25         
26         try{
27 //        if (referer != null && referer.indexOf(basePath) < 0) {
28 //            ((HttpServletRequest) request).getRequestDispatcher(((HttpServletRequest) request).getRequestURI()).forward(((HttpServletRequest) request), response);
29 //            System.out.println("referer不为空,referer >>>>>>>>>>>>>> " + referer);
30 //        }
31             
32             xssRequest = new NewXssHttpServletRequestWrapper((HttpServletRequest) request);
33             chain.doFilter(xssRequest, response);
34         }
35         catch(Exception ex){
36             ex.printStackTrace();
37         }
38 //        NewXssHttpServletRequestWrapper xssRequest = new NewXssHttpServletRequestWrapper((HttpServletRequest) request);
39         
40     }
41 
42     @Override
43     public void init(FilterConfig filterConfig) throws ServletException {
44         this.filterConfig = filterConfig;
45     }
46 
47 }

2.web.xml

1   <filter>
2     <filter-name>XssSqlFilter</filter-name>
3     <filter-class>com.wx.business.common.xssprotect.NewXssFilter</filter-class>
4   </filter>

3.NewXssHttpServletRequestWrapper 

  1 public class NewXssHttpServletRequestWrapper extends HttpServletRequestWrapper {
  2 
  3     HttpServletRequest orgRequest = null;
  4 
  5     public NewXssHttpServletRequestWrapper(HttpServletRequest request) {
  6         super(request);
  7         orgRequest = request;
  8     }
  9 
 10     /**
 11      * 覆盖getParameter方法,将参数名和参数值都做xss过滤。<br/>
 12      * 如果需要获得原始的值,则通过super.getParameterValues(name)来获取<br/>
 13      * getParameterNames,getParameterValues和getParameterMap也可能需要覆盖
 14      */
 15     @Override
 16     public String getParameter(String name) {
 17         // System.out.println("NewXssFilter处理前的 Value = " + super.getParameterValues(name));
 18 
 19         String value = super.getParameter(xssEncode(name));
 20         if (value != null) {
 21             value = xssEncode(value);
 22         }
 23 
 24         // System.out.println("NewXssFilter处理后的 Value = " + value);
 25 
 26         return value;
 27     }
 28 
 29     @Override
 30     public Map getParameterMap() {
 31         Map returnMap = new HashMap();
 32         Map map = super.getParameterMap();
 33 
 34         Iterator entries = map.entrySet().iterator();
 35         Map.Entry entry;
 36         String name = "";
 37         while (entries.hasNext()) {
 38             entry = (Map.Entry) entries.next();
 39             name = xssEncode((String) entry.getKey());
 40 
 41             // System.out.println(name);
 42 
 43             Object valueObj = entry.getValue();
 44             if (null == valueObj) {
 45                 returnMap.put(name, valueObj);
 46             } else if (valueObj instanceof String[]) {
 47                 String[] values = (String[]) valueObj;
 48                 String[] escapeVal = new String[values.length];
 49                 for (int i = 0; i < values.length; i++) {
 50                     escapeVal[i] = xssEncode(values[i]);
 51                 }
 52                 returnMap.put(name, escapeVal);
 53             } else {
 54                 returnMap.put(name, valueObj);
 55             }
 56 
 57         }
 58         return returnMap;
 59     }
 60 
 61     /**
 62      * 覆盖getHeader方法,将参数名和参数值都做xss过滤。<br/>
 63      * 如果需要获得原始的值,则通过super.getHeaders(name)来获取<br/>
 64      * getHeaderNames 也可能需要覆盖
 65      */
 66     @Override
 67     public String getHeader(String name) {
 68 
 69         String value = super.getHeader(xssEncode(name));
 70         if (value != null) {
 71             value = xssEncode(value);
 72         }
 73         return value;
 74     }
 75 
 76     /**
 77      * 将容易引起xss漏洞的半角字符直接替换成全角字符
 78      * 
 79      * @param s
 80      * @return
 81      */
 82     public String xssEncode(String s) {
 83         if ((s == null) || s.isEmpty()) {
 84             return s;
 85         }
 86 
 87         String result = stripXSS(s);
 88         if (null != result) {
 89             result = escape(result);
 90         }
 91 
 92         return result;
 93     }
 94 
 95     public String escape(String s) {
 96         StringBuilder sb = new StringBuilder(s.length() + 16);
 97         for (int i = 0; i < s.length(); i++)
 98         {
 99             char c = s.charAt(i);
100             switch (c)
101             {
102             case '>':
103                 sb.append('>');// 全角大于号
104                 break;
105             case '<':
106                 sb.append('<');// 全角小于号
107                 break;
108             /*case '\'':
109                 sb.append('‘');// 全角单引号
110                 break;
111             case '\"':
112                 sb.append('“');// 全角双引号
113                 break;
114             case '\\':
115                 sb.append('\');// 全角斜线
116                 break;
117             case '%':
118             sb.append('%'); // 全角冒号
119             break;*/
120             default:
121                 sb.append(c);
122                 break;
123             }
124 
125         }
126         return sb.toString();
127         //return s;
128     }
129 
130     private String stripXSS(String value) {
131         if (value != null) {
132             // NOTE: It's highly recommended to use the ESAPI library and
133             // uncomment the following line to
134             // avoid encoded attacks.
135             // value = ESAPI.encoder().canonicalize(value);
136             // Avoid null characters
137             value = value.replaceAll("", "");
138             // Avoid anything between script tags
139             Pattern scriptPattern = Pattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE);
140             value = scriptPattern.matcher(value).replaceAll("");
141             // Avoid anything in a src='...' type of expression
142             scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\'(.*?)\\\'", Pattern.CASE_INSENSITIVE
143                     | Pattern.MULTILINE | Pattern.DOTALL);
144             value = scriptPattern.matcher(value).replaceAll("");
145             scriptPattern = Pattern.compile("src[\r\n]*=[\r\n]*\\\"(.*?)\\\"", Pattern.CASE_INSENSITIVE
146                     | Pattern.MULTILINE | Pattern.DOTALL);
147             value = scriptPattern.matcher(value).replaceAll("");
148             // Remove any lonesome </script> tag
149             scriptPattern = Pattern.compile("</script>", Pattern.CASE_INSENSITIVE);
150             value = scriptPattern.matcher(value).replaceAll("");
151             // Remove any lonesome <script ...> tag
152             scriptPattern = Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
153                     | Pattern.DOTALL);
154             value = scriptPattern.matcher(value).replaceAll("");
155             // Avoid eval(...) expressions
156             scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
157                     | Pattern.DOTALL);
158             value = scriptPattern.matcher(value).replaceAll("");
159             // Avoid expression(...) expressions
160             scriptPattern = Pattern.compile("expression\\((.*?)\\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
161                     | Pattern.DOTALL);
162             value = scriptPattern.matcher(value).replaceAll("");
163             // Avoid javascript:... expressions
164             scriptPattern = Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE);
165             value = scriptPattern.matcher(value).replaceAll("");
166             // Avoid vbscript:... expressions
167             scriptPattern = Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE);
168             value = scriptPattern.matcher(value).replaceAll("");
169             // Avoid onload= expressions
170             scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
171                     | Pattern.DOTALL);
172             value = scriptPattern.matcher(value).replaceAll("");
173 
174             scriptPattern = Pattern.compile("<iframe>(.*?)</iframe>", Pattern.CASE_INSENSITIVE);
175             value = scriptPattern.matcher(value).replaceAll("");
176 
177             scriptPattern = Pattern.compile("</iframe>", Pattern.CASE_INSENSITIVE);
178             value = scriptPattern.matcher(value).replaceAll("");
179             // Remove any lonesome <script ...> tag
180             scriptPattern = Pattern.compile("<iframe(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE
181                     | Pattern.DOTALL);
182             value = scriptPattern.matcher(value).replaceAll("");
183         }
184         return value;
185     }
186 
187     /**
188      * 获取最原始的request
189      * 
190      * @return
191      */
192     public HttpServletRequest getOrgRequest() {
193         return orgRequest;
194     }
195 
196     /**
197      * 获取最原始的request的静态方法
198      * 
199      * @return
200      */
201     public static HttpServletRequest getOrgRequest(HttpServletRequest req) {
202         if (req instanceof NewXssHttpServletRequestWrapper) {
203             return ((NewXssHttpServletRequestWrapper) req).getOrgRequest();
204         }
205 
206         return req;
207     }
208 
209 }

方法二:jfinal实现

参考:https://blog.csdn.net/zzzgd_666/article/details/80356266

 

posted @ 2019-05-08 14:30  littlecarzz  阅读(762)  评论(0编辑  收藏  举报