xss攻击预防,网上有很多介绍,发现很多都是只能预防GET方式请求的xss攻击,并不能预防POST方式的xss攻击。主要是由于POST方式的参数只能用流的方式读取,且只能读取一次,经过多次尝试,也只做到了能够接受GET、POST方式的参数并进行相关转义,但是最终通过方法获取的参数仍是未转义的参数。很是遗憾。目前先把综合了网上介绍的方法的相关代码在这里整理一下,有了新的突破再来更新。 |
参考主要网址: http://blog.csdn.net/Lan_Xuan/article/details/73826065 |
maven依赖: <!-- https://mvnrepository.com/artifact/antlr/antlr --> |
web.xml
1 <filter> 2 <filter-name>XssEscape</filter-name> 3 <filter-class>com.*.webshell.XSSFilter</filter-class> 4 </filter> 5 <filter-mapping> 6 <filter-name>XssEscape</filter-name> 7 <url-pattern>/*</url-pattern> 8 <dispatcher>REQUEST</dispatcher> 9 </filter-mapping>
ThreadCache.java
1 public class ThreadCache { 2 // ThreadLocal里只存储了简单的String对象,也可以自己定义对象,存储更加复杂的参数 3 private static ThreadLocal<String> threadLocal = new ThreadLocal<String>(); 4 5 public static String getPostRequestParams(){ 6 return threadLocal.get(); 7 } 8 9 public static void setPostRequestParams(String postRequestParams){ 10 threadLocal.set(postRequestParams); 11 } 12 13 public static void removePostRequestParams(){ 14 threadLocal.remove(); 15 } 16 }
XSSFilter.java
1 import java.io.IOException; 2 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 11 import org.slf4j.Logger; 12 import org.slf4j.LoggerFactory; 13 14 public class XSSFilter implements Filter { 15 private static Logger log = LoggerFactory.getLogger(XSSFilter.class); 16 17 @Override 18 public void init(FilterConfig filterConfig) throws ServletException { 19 } 20 21 @Override 22 public void destroy() { 23 } 24 25 @Override 26 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) 27 throws IOException, ServletException { 28 try { 29 WrappedHttpServletRequest requestWrapper = new WrappedHttpServletRequest((HttpServletRequest) request); 30 31 if ("POST".equals(requestWrapper.getMethod().toUpperCase())) { 32 // 获取请求参数 33 String params = requestWrapper.getRequestParams(); 34 ThreadCache.setPostRequestParams(params); 35 log.info("filer-post请求参数:[params={}]", params); 36 System.out.println("filer-post请求参数:[params={}]"+ params); 37 } else { 38 log.info("非post请求"); 39 } 40 41 // 这里doFilter传入我们实现的子类 42 chain.doFilter(requestWrapper, response); 43 } catch (Exception e) { 44 log.error(e.getMessage(), e); 45 } 46 } 47 }
WrappedHttpServletRequest.java
1 import org.apache.commons.io.IOUtils; 2 3 import javax.servlet.ReadListener; 4 import javax.servlet.ServletInputStream; 5 import javax.servlet.http.HttpServletRequest; 6 import javax.servlet.http.HttpServletRequestWrapper; 7 import java.io.*; 8 9 public class WrappedHttpServletRequest extends HttpServletRequestWrapper { 10 11 private byte[] bytes; 12 private WrappedServletInputStream wrappedServletInputStream; 13 14 public WrappedHttpServletRequest(HttpServletRequest request) throws IOException { 15 super(request); 16 // 读取输入流里的请求参数,并保存到bytes里 17 bytes = IOUtils.toByteArray(request.getInputStream()); 18 ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes); 19 this.wrappedServletInputStream = new WrappedServletInputStream(byteArrayInputStream); 20 21 // 很重要,把post参数重新写入请求流 22 reWriteInputStream(); 23 24 } 25 26 public String[] getParameterValues(String parameter) { 27 String[] values = super.getParameterValues(parameter); 28 if (values == null) { 29 return null; 30 } 31 int count = values.length; 32 String[] encodedValues = new String[count]; 33 for (int i = 0; i < count; i++) { 34 encodedValues[i] = cleanXSS(values[i]); 35 } 36 return encodedValues; 37 } 38 39 public String getParameter(String parameter) { 40 41 if ("POST".equals(super.getMethod().toUpperCase())) { 42 String cleanXSS = cleanXSS(ThreadCache.getPostRequestParams()); 43 System.out.println("cleanXSS:" + cleanXSS); 44 return cleanXSS; 45 } 46 47 String value = super.getParameter(parameter); 48 if (value == null) { 49 return null; 50 } 51 return cleanXSS(value); 52 } 53 54 public String getHeader(String name) { 55 String value = super.getHeader(name); 56 if (value == null) 57 return null; 58 return cleanXSS(value); 59 } 60 61 private String cleanXSS(String value) { 62 value = value.replaceAll("<", "& lt;").replaceAll(">", "& gt;"); 63 value = value.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41;"); 64 value = value.replaceAll("‘", "& #39;"); 65 value = value.replaceAll("eval\\((.*)\\)", ""); 66 value = value.replaceAll("[\\\"\\\‘][\\s]*javascript:(.*)[\\\"\\\‘]", "\"\""); 67 value = value.replaceAll("script", ""); 68 return value; 69 } 70 71 /** 72 * 把参数重新写进请求里 73 */ 74 public void reWriteInputStream() { 75 wrappedServletInputStream.setStream(new ByteArrayInputStream(bytes != null ? bytes : new byte[0])); 76 } 77 78 @Override 79 public ServletInputStream getInputStream() throws IOException { 80 return wrappedServletInputStream; 81 } 82 83 @Override 84 public BufferedReader getReader() throws IOException { 85 return new BufferedReader(new InputStreamReader(wrappedServletInputStream)); 86 } 87 88 /** 89 * 获取post参数,可以自己再转为相应格式 90 */ 91 public String getRequestParams() throws IOException { 92 return new String(bytes, this.getCharacterEncoding()); 93 } 94 95 private class WrappedServletInputStream extends ServletInputStream { 96 97 public void setStream(InputStream stream) { 98 this.stream = stream; 99 } 100 101 private InputStream stream; 102 103 public WrappedServletInputStream(InputStream stream) { 104 this.stream = stream; 105 } 106 107 @Override 108 public int read() throws IOException { 109 return stream.read(); 110 } 111 112 @Override 113 public boolean isFinished() { 114 return true; 115 } 116 117 @Override 118 public boolean isReady() { 119 return true; 120 } 121 122 @Override 123 public void setReadListener(ReadListener readListener) { 124 125 } 126 } 127 }