赞
踩
跨站脚本工具(cross 斯特scripting),为不和层叠样式表(cascading style sheets,CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS。恶意攻击者往web页面里插入恶意ScriptScript代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被执行,从而达到恶意攻击用户的目的。防止XSS攻击简单的预防就是对Request请求中的一些参数去掉一些比较敏感的脚本命令。原本是打算通过SpringMVC的HandlerInterceptor机制来实现的,通过获取request然后对request中的参数进行修改,结果虽然值修改了,但在Controller中获取的数值还是没有修改的。没办法就是要Filter来完成。简单来说就是创建一个新的HttpRequest类XssHttpServletRequestWrapper,然后重写一些get方法(获取参数时对参数进行XSS判断预防)
流程梳理
包装request->创建过滤器->添加过滤器
XssHttpServletRequestWrapper
-
- import java.io.BufferedReader;
- import java.io.ByteArrayInputStream;
- import java.io.IOException;
- import java.io.InputStreamReader;
- import java.nio.charset.Charset;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
-
- import javax.servlet.ReadListener;
- import javax.servlet.ServletInputStream;
- import javax.servlet.ServletOutputStream;
- import javax.servlet.http.HttpServletRequest;
- import javax.servlet.http.HttpServletRequestWrapper;
- import javax.servlet.http.HttpServletResponse;
-
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
-
- import com.sysware.framework.exceptions.SyswareRuntimeException;
- import com.sysware.framework.file.service.impl.FileGridServiceImpl;
-
-
- public class XssHttpServletRequestWraper extends HttpServletRequestWrapper {
-
- private Logger log = LoggerFactory.getLogger(FileGridServiceImpl.class);
-
-
- public XssHttpServletRequestWraper() {
- super(null);
- }
-
- public XssHttpServletRequestWraper(HttpServletRequest httpservletrequest) {
- super(httpservletrequest);
-
- }
-
- //过滤springmvc中的 @RequestParam 注解中的参数
- public String[] getParameterValues(String s) {
-
- String str[] = super.getParameterValues(s);
- if (str == null) {
- return null;
- }
- int i = str.length;
- String as1[] = new String[i];
- for (int j = 0; j < i; j++) {
- //System.out.println("getParameterValues:"+str[j]);
- as1[j] = cleanXSS(cleanSQLInject(str[j]));
- }
- log.info("XssHttpServletRequestWraper净化后的请求为:==========" + as1);
- return as1;
- }
-
- //过滤request.getParameter的参数
- public String getParameter(String s) {
- String s1 = super.getParameter(s);
- if (s1 == null) {
- return null;
- } else {
- String s2 = cleanXSS(cleanSQLInject(s1));
- log.info("XssHttpServletRequestWraper净化后的请求为:==========" + s2);
- return s2;
- }
- }
-
- //过滤请求体 json 格式的
- @Override
- public ServletInputStream getInputStream() throws IOException {
- final ByteArrayInputStream bais = new ByteArrayInputStream(inputHandlers(super.getInputStream ()).getBytes ());
-
- return new ServletInputStream() {
-
- @Override
- public int read() throws IOException {
- return bais.read();
- }
-
- @Override
- public boolean isFinished() {
- return false;
- }
-
- @Override
- public boolean isReady() {
- return false;
- }
-
- @Override
- public void setReadListener(ReadListener readListener) { }
- };
-
- }
-
-
- public String inputHandlers(ServletInputStream servletInputStream){
- StringBuilder sb = new StringBuilder();
- BufferedReader reader = null;
- try {
- reader = new BufferedReader(new InputStreamReader(servletInputStream, Charset.forName("UTF-8")));
- String line = "";
- while ((line = reader.readLine()) != null) {
- sb.append(line);
- }
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- if (servletInputStream != null) {
- try {
- servletInputStream.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- if (reader != null) {
- try {
- reader.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- return cleanXSS(sb.toString ());
- }
-
- public String cleanXSS(String src) {
- String temp = src;
-
- src = src.replaceAll("<", "<").replaceAll(">", ">");
- src = src.replaceAll("\\(", "(").replaceAll("\\)", ")");
- src = src.replaceAll("'", "");
- src = src.replaceAll(";", "");
- /**-----------------------start--------------------------*/
- src = src.replaceAll("<", "& lt;").replaceAll(">", "& gt;");
- src = src.replaceAll("\\(", "& #40;").replaceAll("\\)", "& #41");
- src = src.replaceAll("eval\\((.*)\\)", "");
- src = src.replaceAll("[\\\"\\\'][\\s]*javascript:(.*)[\\\"\\\']", "\"\"");
- // src = src.replaceAll("script", "");
- // src = src.replaceAll("link", "");
- // src = src.replaceAll("frame", "");
- /**-----------------------end--------------------------*/
- Pattern pattern = Pattern.compile("(eval\\((.*)\\)|script)",
- Pattern.CASE_INSENSITIVE);
- Matcher matcher = pattern.matcher(src);
- src = matcher.replaceAll("");
-
- pattern = Pattern.compile("[\\\"\\'][\\s]*javascript:(.*)[\\\"\\']",
- Pattern.CASE_INSENSITIVE);
- matcher = pattern.matcher(src);
- src = matcher.replaceAll("\"\"");
-
- // 增加脚本
- src = src.replaceAll("script", "").replaceAll(";", "")
- /*.replaceAll("\"", "").replaceAll("@", "")*/
- .replaceAll("0x0d", "").replaceAll("0x0a", "");
-
- // if (!temp.equals(src)) {
- // // System.out.println("输入信息存在xss攻击!");
- // // System.out.println("原始输入信息-->" + temp);
- // // System.out.println("处理后信息-->" + src);
- //
- // log.error("xss攻击检查:参数含有非法攻击字符,已禁止继续访问!!");
- // log.error("原始输入信息-->" + temp);
- //
- // throw new SyswareRuntimeException("xss攻击检查:参数含有非法攻击字符,已禁止继续访问!!");
- // }
- return src;
- }
-
- //输出
- public void outputMsgByOutputStream(HttpServletResponse response, String msg) throws IOException {
- ServletOutputStream outputStream = response.getOutputStream(); //获取输出流
- response.setHeader("content-type", "text/html;charset=UTF-8"); //通过设置响应头控制浏览器以UTF-8的编码显示数据,如果不加这句话,那么浏览器显示的将是乱码
- byte[] dataByteArr = msg.getBytes("UTF-8");// 将字符转换成字节数组,指定以UTF-8编码进行转换
- outputStream.write(dataByteArr);// 使用OutputStream流向客户端输出字节数组
- }
-
- // 需要增加通配,过滤大小写组合
- public String cleanSQLInject(String src) {
- String lowSrc = src.toLowerCase();
- String temp = src;
- String lowSrcAfter = lowSrc.replaceAll(" insert ", "forbidI")
- .replaceAll(" select ", "forbidS")
- .replaceAll(" update ", "forbidU")
- .replaceAll(" delete ", "forbidD").replaceAll(" and ", "forbidA")
- .replaceAll(" or ", "forbidO").replace("'", "");
-
- if (!lowSrcAfter.equals(lowSrc)) {
- log.error("sql注入检查:输入信息存在SQL攻击!");
- log.error("原始输入信息-->" + temp);
- log.error("处理后信息-->" + lowSrc);
- throw new SyswareRuntimeException("sql注入检查:参数含有非法攻击字符,已禁止继续访问!!");
-
- }
- return src;
- }
-
- }

注意:
getInputStream()方法的流处理,注解方式获取数据貌似是根据这个流取得的数据。
因为super.getInputStream()流只允许读取一次,所以在getInputStream()方法中
处理完流数据后返回了一个新的ServletInputStream。另外替换方法里的替换规则,
也可以根据实际业务需要进行调整。
2.创建过滤器 XssFilter
- @Component
- public class XssFilter implements Filter {
-
-
- // 忽略权限检查的url地址
- private final String[] excludeUrls = new String[]{
- "/api/item","api/document"
- };
-
- public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
- throws IOException, ServletException {
-
- HttpServletRequest req = (HttpServletRequest) arg0;
- HttpServletResponse response = (HttpServletResponse) arg1;
-
- String pathInfo = req.getPathInfo() == null ? "" : req.getPathInfo();
- //获取请求url的后两层
- String url = req.getServletPath() + pathInfo;
- //获取请求你ip后的全部路径
- String uri = req.getRequestURI();
- //注入xss过滤器实例
- XssHttpServletRequestWraper reqW = new XssHttpServletRequestWraper(req);
-
- //过滤掉不需要的Xss校验的地址
- for (String str : excludeUrls) {
- if (uri.indexOf(str) >= 0) {
- //过滤
- arg2.doFilter(reqW, response);
- return;
- }
- }
- arg2.doFilter(arg0, response);
- }
- public void destroy() {
- }
- public void init(FilterConfig filterconfig1) throws ServletException {
- }
- }

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。