背景

  • 之前公司信息安全部门对公司项目进行网络安全升级时,发现项目里可能会出现XSS脚本攻击漏洞,所以就需要对其参数进行过滤拦截。

XSS

  • 百度百科:XSS攻击全称:cross site scripting(这里是为了和CSS区分,所以叫XSS),跨站脚本攻击(XSS),是最普遍的Web应用安全漏洞。这类漏洞能够使得攻击者嵌入恶意脚本代码到正常用户会访问到的页面中,当正常用户访问该页面时,则可导致嵌入的恶意脚本代码的执行,从而达到恶意攻击用户的目的。攻击者可以使用户在浏览器中执行其预定义的恶意脚本,其导致的危害可想而知,如劫持用户会话,插入恶意内容、重定向用户、使用恶意软件劫持用户浏览器、繁殖XSS蠕虫,甚至破坏网站、修改路由器配置信息等。
  • xss漏洞攻击分为三种:

    • 反射性XSS攻击:前端在发送请求时,在url参数里携带一些脚本命令,然后等服务端把脚本在反射给浏览器执行脚本代码,进行XSS漏洞攻击
    • 存储性XSS攻击:和反射性XSS漏洞攻击相似,但是服务器会进行持久化保存脚本命令,后续用户访问该数据时持久性进行XSS漏洞攻击
    • DOS性XSS攻击:和服务端没有交互,靠浏览器的DOM解析进行XSS攻击

Java过滤

  • 预防XSS漏洞攻击除了web端进行解析过滤外,也还需要服务端进行校验过滤
  • 本次使用springboot项目中过滤器进行对前端传来的参数进行过滤拦截
/*** springboot注册过滤器** @author: zrh* @date: 2021-11-17*/@Configuration
public class XssFilterConfig {@Beanpublic FilterRegistrationBean xssFilterRegistrationBean () {FilterRegistrationBean initXssFilterBean = new FilterRegistrationBean();// 设置自定义过滤器initXssFilterBean.setFilter(new XssFilter());// 设置优先级(值越低,优先级越高)initXssFilterBean.setOrder(1);// 设置过滤路径initXssFilterBean.addUrlPatterns("/*");// 设置过滤器名称initXssFilterBean.setName("XSS_filter");// 设置过滤器作用范围(可以配置多种,这里指定过滤请求资源)initXssFilterBean.setDispatcherTypes(DispatcherType.REQUEST);return initXssFilterBean;}
}
  • spring项目中可以使用web.xml定义过滤器,springboot中没有web.xml配置文件,那么就可以使用FilterRegistrationBean类把过滤器实例注册到容器
/*** 自定义过滤器** @author: zrh* @date: 2021-11-17*/
@Slf4j
public class XssFilter implements Filter {@Overridepublic void init (FilterConfig filterConfig) {// 初始化调用}@Overridepublic void doFilter (ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {final XssHttpServletRequestWrapper requestWrapper = new XssHttpServletRequestWrapper((HttpServletRequest) servletRequest);filterChain.doFilter(requestWrapper, servletResponse);}@Overridepublic void destroy () {// 销毁调用}
}
/*** 重写请求参数过滤** @author: zrh* @date: 2021-11-17*/
@Slf4j
public class XssHttpServletRequestWrapper extends HttpServletRequestWrapper {public XssHttpServletRequestWrapper (HttpServletRequest request) {super(request);}/*** 对GET请求中参数进行过滤校验** @param name* @return*/@Overridepublic String[] getParameterValues (String name) {String[] values = super.getParameterValues(name);if (values == null) {return null;}int count = values.length;String[] cleanParams = new String[count];for (int i = 0; i < count; i++) {cleanParams[i] = String.valueOf(XssUtil.filterParam(values[i]));log.info("getParameterValues -> name:{},过滤前参数:{},过滤后参数:{}", name, values[i], cleanParams[i]);}return cleanParams;}/*** 对POST请求头进行参数过滤校验** @param header* @return*/@Overridepublic Enumeration getHeaders (String header) {final String value = super.getHeader(header);final LinkedList list = new LinkedList();if (value != null) {final Object param = XssUtil.filterParam(value);list.addFirst(param);log.info("getHeaders -> header:{},过滤前参数:{},过滤后参数:{}", header, value, param);}return Collections.enumeration(list);}/*** 对POST请求中body参数进行校验** @return* @throws IOException*/@Overridepublic ServletInputStream getInputStream () throws IOException {final ByteArrayInputStream stream = new ByteArrayInputStream(inputHandlers(super.getInputStream()).getBytes());return new ServletInputStream() {@Overridepublic int read () {return stream.read();}@Overridepublic boolean isFinished () {return false;}@Overridepublic boolean isReady () {return false;}@Overridepublic void setReadListener (ReadListener readListener) {}};}/*** 解析请求流参数** @param servletInputStream* @return*/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) {log.error("异常 e:", e);} finally {if (servletInputStream != null) {try {servletInputStream.close();} catch (IOException e) {log.error("servletInputStream 关闭异常 e:", e);}}if (reader != null) {try {reader.close();} catch (IOException e) {log.error("reader 关闭异常 e:", e);}}}final String param = XssUtil.filterBody(sb.toString());log.info("getInputStream -> 过滤前参数:{},过滤后参数:{}", sb, param);return param;}
}
  • 重写HttpServletRequestWrapper类用于过滤改变请求参数值
/*** 参数校验工具类** @author: zrh* @date: 2021-11-17*/
@Slf4j
public final class XssUtil {private XssUtil () {}/*** 网上找的XSS匹配正则表达式*/private final static Pattern[] PATTERNS = new Pattern[]{// Script fragmentsPattern.compile("<script>(.*?)</script>", Pattern.CASE_INSENSITIVE),// src='...'Pattern.compile("src[\r\n]*=[\r\n]*\'(.*?)\'", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),Pattern.compile("src[\r\n]*=[\r\n]*\"(.*?)\"", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),// lonely script tagsPattern.compile("</script>", Pattern.CASE_INSENSITIVE),Pattern.compile("<script(.*?)>", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),// eval(...)Pattern.compile("eval\((.*?)\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),// expression(...)Pattern.compile("expression\((.*?)\)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),// javascript:...Pattern.compile("javascript:", Pattern.CASE_INSENSITIVE),// vbscript:...Pattern.compile("vbscript:", Pattern.CASE_INSENSITIVE),// 空格英文单双引号Pattern.compile("[\s'"]+", Pattern.CASE_INSENSITIVE),// onload(...)=...Pattern.compile("onload(.*?)=", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),// alertPattern.compile("alert(.*?)", Pattern.CASE_INSENSITIVE | Pattern.MULTILINE | Pattern.DOTALL),Pattern.compile("<", Pattern.MULTILINE | Pattern.DOTALL),Pattern.compile(">", Pattern.MULTILINE | Pattern.DOTALL),//Checks any html tags i.e. <script, <embed, <object etc.Pattern.compile("(<(script|iframe|embed|frame|frameset|object|img|applet|body|html|style|layer|link|ilayer|meta|bgsound))")};/*** 对请求对象参数进行过滤校验** @param params* @return*/public static String filterBody (String params) {try {if (StringUtils.isBlank(params)) {return params;}final Map<String, Object> map = JSONObject.parseObject(params, Map.class);if (map.isEmpty()) {return params;}// 参数过滤final Iterator<Map.Entry<String, Object>> iterator = map.entrySet().stream().iterator();while (iterator.hasNext()) {final Map.Entry<String, Object> next = iterator.next();next.setValue(filterParam(next.getValue()));}return JSON.toJSONString(map);} catch (Exception e) {log.error("XSS过滤异常:", e);}return params;}/*** 对请求字符串参数进行过滤校验** @param param* @param <T>* @return*/public static <T> Object filterParam (T param) {if (param instanceof String) {try {String value = String.valueOf(param);for (Pattern pattern : PATTERNS) {value = pattern.matcher(value).replaceAll("");}return value;} catch (Exception e) {log.error("XSS参数过滤异常:", e);}}return param;}
}
  • XSS过滤参数的正则工具类
/**** @Author: ZRH* @Date: 2021/11/17*/
@RestController
public class XssTest {@PostMapping("/xss/test")public String test (@RequestBody JSONObject jsonObject) {System.out.println(jsonObject.toJSONString());return "OK";}@GetMapping("/xss/test")public String test (@RequestParam Integer data, @RequestParam String result) {System.out.println(data);return "OK";}
}模拟请求响应结果:
17:07:06.597 - [http-nio-8888-exec-1] - getHeaders -> header:content-type,过滤前参数:application/json,过滤后参数:application/json
17:07:06.598 - [http-nio-8888-exec-1] - getHeaders -> header:token,过滤前参数:123,过滤后参数:123
17:07:06.598 - [http-nio-8888-exec-1] - getHeaders -> header:a,过滤前参数:123,过滤后参数:123
17:07:06.598 - [http-nio-8888-exec-1] - getHeaders -> header:b,过滤前参数:<script>alert("XSS");</script>,过滤后参数:
17:07:06.599 - [http-nio-8888-exec-1] - getHeaders -> header:content-length,过滤前参数:67,过滤后参数:67
17:07:06.599 - [http-nio-8888-exec-1] - getHeaders -> header:host,过滤前参数:localhost:8888,过滤后参数:localhost:8888
17:07:06.599 - [http-nio-8888-exec-1] - getHeaders -> header:connection,过滤前参数:Keep-Alive,过滤后参数:Keep-Alive
17:07:06.599 - [http-nio-8888-exec-1] - getHeaders -> header:user-agent,过滤前参数:Apache-HttpClient/4.5.12 (Java/11.0.8),过滤后参数:Apache-HttpClient/4.5.12(Java/11.0.8)
17:07:06.599 - [http-nio-8888-exec-1] - getHeaders -> header:accept-encoding,过滤前参数:gzip,deflate,过滤后参数:gzip,deflate
17:07:06.648 - [http-nio-8888-exec-1] - getInputStream -> 过滤前参数:{  "a": "1",  "b": 2,  "c": "<script>alert(\"XSS\");</script>"},过滤后参数:{"a":"1","b":2,"c":""}
{"a":"1","b":2,"c":""}

最后

  • 除了可以使用过滤器以外,还可以使用拦截器进行拦截校验。大致流程也差不多,先获取参数,然后进行校验,最后重新赋值。
  • 上述代码例子只是简单粗化版,在实际项目中要根据需求进行代码调整和性能优化后才可在线上使用。
  • 虚心学习,共同进步 -_-

Java过滤XSS脚本攻击记录一下相关推荐

  1. java 过滤xss脚本_Java Web应用程序的反跨站点脚本(XSS)过滤器

    java 过滤xss脚本 这是为Java Web应用程序编写的一个好简单的反跨站点脚本(XSS)过滤器. 它的基本作用是从请求参数中删除所有可疑字符串,然后将其返回给应用程序. 这是我以前关于该主题的 ...

  2. java 过滤脚本_【快学SpringBoot】过滤XSS脚本攻击(包括json格式)

    XSS攻击是什么 XSS攻击全称跨站脚本攻击,是为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS,XSS是一种在web应用中的计算机安 ...

  3. XSS脚本攻击防御(Antisamy)

    由于公司的产品准备全面互联网化,所以就对安全问题进行了一系列的排查,排查过程中发现了xss脚本攻击的问题,开始着手了解和修改代码 xss攻击的简单解释 跨站脚本(Cross-site scriptin ...

  4. vue 如何防止xss攻击 框架_LearningNotes-1/Vue/Vue中防止XSS脚本攻击 at master · axuu/LearningNotes-1 · GitHub...

    Vue中防止XSS脚本攻击 最近写了一个博客评论模块,因为引入了表情包,所以就将原来的v-text的形式,改成了v-html,也就是渲染html标签,但是这样不可不免的会带来问题,就是XSS跨站脚本攻 ...

  5. 如何尽量规避XSS(跨站点脚本)攻击

    2019独角兽企业重金招聘Python工程师标准>>> 跨站攻击,即Cross Site Script Execution(通常简写为XSS,因为CSS与层叠样式表同名,故改为XSS ...

  6. java解决XSS攻击常用方法总结

    前言 在项目验收阶段,通常会对待验收项目做一些安全漏洞的测试,比如接口攻击,并发测试,XSS注入,SQL恶意注入测试,安全越权等操作,这时,就是考验项目的安全方面是否做的足够健壮的时候,本篇对XSS脚 ...

  7. 45-互联网安全架构-Web常用攻击手段之XSS脚本SQL注入攻击

    文章目录 1. 什么是XSS攻击&XSS攻击应用场景 2. XSS脚本攻击原理分析 3. 使用过滤器防御XSS攻击 4. 使用#传递参数防御SQL注入攻击 1. 什么是XSS攻击&XS ...

  8. 网络安全——XSS跨站脚本攻击

    一.XSS概述 1.XSS被称为跨站脚本攻击,由于和CSS重名,所以改为XSS: 2.XSS主要基于JavaScript语言完成恶意的攻击行为,因为JavaScript可以非常灵活的操作html.CS ...

  9. java防XSS攻击的 关键词过滤实现

    继承HttpServletRequestWrapper,实现对请求参数的过滤/*** xss请求适配器*/ public class XssHttpServletRequestWrapper exte ...

最新文章

  1. 模板资源管理器的使用
  2. VC获取其他进程ListCtrl内容
  3. 【解题报告】2020蓝桥杯B组模拟 计蒜客 结果填空:苹果
  4. php 查询数据是否大于,怎么实现从数据查询数据的时候判断如果数据大于N条分次查询 递归吗?...
  5. Array(数组-转树)
  6. linux虚拟机 dev sda2,虛擬機linux下 /dev/sda2 滿了怎么辦,測試用過,真實可行
  7. 超经典实用APP UI产品界面设计模板
  8. 从PCA到Kernel PCA(Python)
  9. c# winform 窗体间的传值
  10. 【Android容器组件—AdapterView】
  11. 解决:error: Microsoft Visual C++ 14.0 or greater is required. Get it with “Microsoft C++ Build Tools“
  12. Day3:MVP+ButterKnife+Dagger2的使用
  13. (19年最新,操作极简)linux下使用xmind zen破解版
  14. skinsdog 狗网支持马上直接取回CSGO饰品皮肤开箱网站
  15. webservice 405 java_用浏览器测试Get与Post Webservice,Post一直报405错误,而Get能够成功的原因与解决方法...
  16. uniapp vue百度人脸实名认证(V4)接口
  17. oracle如何设置连接数,关于Oracle连接数设置
  18. JAVA实现资源文件映射
  19. 64位 RT-Thread 移植到 Cortex-A53 系统 bug 修复笔记
  20. 中国小三多,是因为女人缺乏精神上的独立,男人缺乏人格上的体面。

热门文章

  1. icon和文本垂直居中对齐
  2. 数据地图绘制工具汇总
  3. 微信小程序实现瀑布流布局
  4. 微信公众号支付,iframe跨域
  5. 在培训机构花了好几万学Java,当了程序员还常被鄙视,这是招谁惹谁了?
  6. glassfish java ee_GlassFish 3.1.2发布 开源的JavaEE应用服务器
  7. 零基础数据挖掘入门系列(三) - 数据清洗和转换技巧
  8. DDC EDID 介绍
  9. 无法启动服务,错误1053
  10. 深入理解JVM(十五)垃圾回收相关概念