随着web飞速的发展,XSS漏洞已经不容忽视,简单介绍一下XSS漏洞, 只要有用户输入的地方,就会出现XSS漏洞,例如在发表一篇帖子的时候,在其中加入脚本。
比如我在表单文本框中,输入
<script>alert(233)</script>
那么当这条消息存到数据库,再次在页面上访问获取数据的时候,就会弹出弹窗.
很多网站为了避免XSS的攻击,对用户的输入都采取了过滤,最常见的就是对<>转换成<以及>,经过转换以后<>虽然可在正确显示在页面上,但是已经不能构成代码语句了
前不久我写了一个JFinal的XSS,这个是在JBoot上面用到的
JFinal如何进行XSS攻击 <https://blog.csdn.net/zzzgd_666/article/details/80356266>
现在又用到SpringMvc, 自然又得重新写一份SpringMvc的过滤方法
主要思路
* 建一个过滤器,过滤来自页面的请求
* 在过滤器中,将原本的request替换成我们自己包装好的request
* 我们写一个request的装饰类,里面重写获取参数的方法,对参数进行转义和替换
具体代码
1. 过滤器
package com.hz.shop.admin.common.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;import
javax.servlet.http.HttpServletResponse;import
org.springframework.web.filter.OncePerRequestFilter;/** * 处理xss攻击的过滤器 * @author
Admin * 2018年5月23日16:12:26 */ public class RequestFilter extends
OncePerRequestFilter { @Override protected void doFilterInternal
(HttpServletRequest request, HttpServletResponse response, FilterChain
filterChain)throws ServletException, IOException { // 将request通过自定义的装饰类进行装饰
XssRequestWrapper xssRequest =new XssRequestWrapper((HttpServletRequest)
request); filterChain.doFilter(xssRequest, response); } }
2. reqeust包装类,重写getParameter()等方法,这里面对参数的转义和替换,根据实际需求更改
package com.hz.shop.api.gateway.handler; import java.util.HashMap; import
java.util.Iterator;import java.util.Map; import java.util.logging.Logger; import
java.util.regex.Pattern;import javax.servlet.http.HttpServletRequest; import
javax.servlet.http.HttpServletRequestWrapper;public class XssRequestWrapper
extends HttpServletRequestWrapper { private HttpServletRequest request; public
XssRequestWrapper(HttpServletRequest request) { super(request); this.request =
request; }/** * 重写getParameter方法 */ @Override public String getParameter(String
name) { String value =super.getParameter(name); if (value == null) { return null
; } value = format(value);return value; } /** * 重写getParameterMap */ @Override
@SuppressWarnings("unchecked") public Map<String, String[]> getParameterMap() {
HashMap<String, String[]> paramMap = (HashMap<String, String[]>)super
.getParameterMap(); paramMap = (HashMap<String, String[]>) paramMap.clone();for
(Iterator iterator = paramMap.entrySet().iterator(); iterator.hasNext(); ) {
Map.Entry<String, String[]> entry = (Map.Entry<String, String[]>)
iterator.next(); String [] values = entry.getValue();for (int i = 0; i <
values.length; i++) {if(values[i] instanceof String){ values[i] =
format(values[i]); } } entry.setValue(values); }return paramMap; } /** *
重写getParameterValues */ @Override public String[] getParameterValues(String
name) { String[] values =super.getParameterValues(name); int count =
values.length; String[] encodedValues =new String[count]; for (int i = 0; i <
count; i++) { encodedValues[i] = format(values[i]); }return encodedValues; }
/** * 重写getHeader */ @Override public String getHeader(String name) { // TODO
Auto-generated method stub return format(super.getHeader(name)); } public String
filter(String message) { if (message == null) return (null); message =
format(message);return message; } /** * @desc 统一处理特殊字符的方法,替换掉sql和js的特殊字符 *
@param name 要替换的字符 */ private String format(String name) { return
xssEncode(name); }/** * 将容易引起xss & sql漏洞的半角字符直接替换成全角字符 * * @param s * @return */
private static String xssEncode(String s) { if (s == null || s.isEmpty()) {
return s; }else{ s = stripXSSAndSql(s); } StringBuilder sb = new
StringBuilder(s.length() +16); for (int i = 0; i < s.length(); i++) { char c =
s.charAt(i);switch (c) { case '>': sb.append(">");// 转义大于号 break; case '<':
sb.append("<");// 转义小于号 break; // case '\'': // sb.append("'");// 转义单引号 //
break; // case '\"': // sb.append(""");// 转义双引号 // break; // case '&': //
sb.append("&");// 转义& // break; // case '#': // sb.append("#");// 转义# // break;
default: sb.append(c); break; } } return sb.toString(); } /** * *
防止xss跨脚本攻击(替换,根据实际情况调整) */ public static String stripXSSAndSql(String value) {
if (value != null) { // NOTE: It's highly recommended to use the ESAPI library
and // uncomment the following line to // avoid encoded attacks. // value =
ESAPI.encoder().canonicalize(value); // Avoid null characters /** value =
value.replaceAll("", "");***/ // Avoid anything between script tags Pattern
scriptPattern = Pattern.compile("<[\r\n| | ]*script[\r\n| | ]*>(.*?)</[\r\n| |
]*script[\r\n| | ]*>", Pattern.CASE_INSENSITIVE); value =
scriptPattern.matcher(value).replaceAll(""); // Avoid anything in a
src="http://www.yihaomen.com/article/java/..." type of e-xpression
scriptPattern = Pattern.compile("src[\r\n| | ]*=[\r\n| |
]*[\\\"|\\\'](.*?)[\\\"|\\\']", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE |
Pattern.DOTALL); value = scriptPattern.matcher(value).replaceAll(""); // Remove
any lonesome </script> tag scriptPattern = Pattern.compile("</[\r\n| |
]*script[\r\n| | ]*>", Pattern.CASE_INSENSITIVE); value =
scriptPattern.matcher(value).replaceAll(""); // Remove any lonesome <script
...> tag scriptPattern = Pattern.compile("<[\r\n| | ]*script(.*?)>",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value =
scriptPattern.matcher(value).replaceAll(""); // Avoid eval(...) expressions
scriptPattern = Pattern.compile("eval\\((.*?)\\)", Pattern.CASE_INSENSITIVE |
Pattern.MULTILINE | Pattern.DOTALL); value =
scriptPattern.matcher(value).replaceAll(""); // Avoid e-xpression(...)
expressions scriptPattern = Pattern.compile("e-xpression\\((.*?)\\)",
Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL); value =
scriptPattern.matcher(value).replaceAll(""); // Avoid javascript:... expressions
scriptPattern = Pattern.compile("javascript[\r\n| | ]*:[\r\n| | ]*",
Pattern.CASE_INSENSITIVE); value = scriptPattern.matcher(value).replaceAll("");
// Avoid vbscript:... expressions scriptPattern = Pattern.compile(
"vbscript[\r\n| | ]*:[\r\n| | ]*", Pattern.CASE_INSENSITIVE); value =
scriptPattern.matcher(value).replaceAll(""); // Avoid onload= expressions
scriptPattern = Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE |
Pattern.MULTILINE | Pattern.DOTALL); value =
scriptPattern.matcher(value).replaceAll(""); } return value; } }
3. 在web.xml中把自己写的过滤器,放在合适的地方,可以考虑放在编码过滤器后面
<!-- xss注入过滤器 --> <filter> <filter-name>xssRequestFilter</filter-name> <
filter-class>com.hz.shop.admin.common.filter.RequestFilter</filter-class> </
filter> <filter-mapping> <filter-name>xssRequestFilter</filter-name> <
url-pattern>/*</url-pattern> </filter-mapping>
4. 接下来就可以启动项目看看效果了
我们输入
<script>alert(2333)</script><font color='red'>红色的</font>哈哈哈
结果
热门工具 换一换