详解java解决XSS攻击常用方法总结
前言
在项目验收阶段,通常会对待验收项目做一些安全漏洞的测试,比如接口攻击,并发测试,XSS注入,SQL恶意注入测试,安全越权等操作,这时,就是考验项目的安全方面是否做的足够健壮的时候,本篇对XSS脚本攻击在实际WEB项目中的处理办法,提供2种可实行的方法
xss攻击
XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript,但实际上也可以包括Java、 VBScript、ActiveX、 Flash 或者甚至是普通的HTML。攻击成功后,攻击者可能得到包括但不限于更高的权限(如执行一些操作)、私密网页内容、会话和cookie等各种内容
简单说就是说,通过在输入框输入一些js代码,如在账号密码输入框中输入
<video src=1 onerror=alert(/xss/)/>
或者
<script>alert("@@") </script>
这样点击提交的时候就会触发alert弹窗,分别弹出 xss 和 @@ 的内容,这里只是做个简单的演示,弹了个窗口,还能存储病毒下载地址到服务端,进入的时候自动下载,或者修改你的cookie啥的,这里感兴趣可以百度查查xss攻击
解决方式一:强制修改html敏感标签内容
这是一种相对容易理解的方式,解决思路就是,当恶意注入的字段中,包含了类似<script>alert(ooo)</script>
这种html标签时,后台程序代码中强制替换或更改标签内容,这样存入数据库的内容再次返回至页面时,就不会以html的形式进行执行了
下面提供一个工具类
/** * xss特殊字符拦截与过滤 * * @author zhangcy * @date 2021-04016 */ public class XssStrUtils { /** * 滤除content中的危险 HTML 代码, 主要是脚本代码, 滚动字幕代码以及脚本事件处理代码 * @param content 需要滤除的字符串 * @return 过滤的结果 */ public static String replaceHtmlCode(String content) { if (null == content) return null; if (0 == content.length()) return ""; // 需要滤除的脚本事件关键字 String[] eventKeywords = { "onmouseover", "onmouseout", "onmousedown", "onmouseup", "onmousemove", "onclick", "ondblclick", "onkeypress", "onkeydown", "onkeyup", "ondragstart", "onerrorupdate", "onhelp", "onreadystatechange", "onrowenter", "onrowexit", "onselectstart", "onload", "onunload", "onbeforeunload", "onblur", "onerror", "onfocus", "onresize", "onscroll", "oncontextmenu", "alert" }; content = replace(content, "<script", "<script", false); content = replace(content, "</script", "</script", false); content = replace(content, "<marquee", "<marquee", false); content = replace(content, "</marquee", "</marquee", false); content = replace(content, "'", "_", false);// 将单引号替换成下划线 content = replace(content, "\"", "_", false);// 将双引号替换成下划线 // 滤除脚本事件代码 for (int i = 0; i < eventKeywords.length; i++) { content = replace(content, eventKeywords[i], "_" + eventKeywords[i], false); // 添加一个"_", 使事件代码无效 } return content; } /** * 将字符串 source 中的 oldStr 替换为 newStr, 并以大小写敏感方式进行查找 * * @param source 需要替换的源字符串 * @param oldStr 需要被替换的老字符串 * @param newStr 替换为的新字符串 */ private static String replace(String source, String oldStr, String newStr) { return replace(source, oldStr, newStr, true); } /** * 将字符串 source 中的 oldStr 替换为 newStr, matchCase 为是否设置大小写敏感查找 * * @param source 需要替换的源字符串 * @param oldStr 需要被替换的老字符串 * @param newStr 替换为的新字符串 * @param matchCase 是否需要按照大小写敏感方式查找 */ private static String replace(String source, String oldStr, String newStr,boolean matchCase) { if (source == null) return null; // 首先检查旧字符串是否存在, 不存在就不进行替换 if (source.toLowerCase().indexOf(oldStr.toLowerCase()) == -1) return source; int findStartPos = 0; int a = 0; while (a > -1) { int b = 0; String str1, str2, str3, str4, strA, strB; str1 = source; str2 = str1.toLowerCase(); str3 = oldStr; str4 = str3.toLowerCase(); if (matchCase) { strA = str1; strB = str3; } else { strA = str2; strB = str4; } a = strA.indexOf(strB, findStartPos); if (a > -1) { b = oldStr.length(); findStartPos = a + b; StringBuffer bbuf = new StringBuffer(source); source = bbuf.replace(a, a + b, newStr) + ""; // 新的查找开始点位于替换后的字符串的结尾 findStartPos = findStartPos + newStr.length() - b; } } return source; } }
我们用一个实际的接口做一下简单的测试
@PostMapping("/getAccName") public String getAccName(@RequestBody NameParams params){ String s = XssStrUtils.replaceHtmlCode(params.getName()); return s; }
使用接口工具调一下,
使用这种方式,即使前端恶意注入了某些非法的html标签,经过后端的过滤处理,返回的内容就不会执行html的相关操作事件了
解决方式二:利用过滤器过滤非法html标签
第二种思路,考虑在过滤器中添加对所有请求接口的参数进行参数的拦截过滤,即程序认为的不合法标签都会自动做过滤,至于过滤的规则,可以借助现有的第三方组件,比如spring框架的htmlUtil类,这里使用hutool工具集提供的相关API做处理
导入依赖
<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.5.9</version> </dependency>
1、添加自定义过滤器增强包装类
public class XssHttpRequestWrapper extends HttpServletRequestWrapper { public XssHttpRequestWrapper(HttpServletRequest request) { super(request); } @Override public String getParameter(String name) { String value = super.getParameter(name); if(!StringUtils.isEmpty(value)){ value = HtmlUtil.filter(value); } return value; } @Override public String[] getParameterValues(String name) { String[] values = super.getParameterValues(name); if(values!=null){ for(int i=0;i<values.length;i++){ String value = values[i]; if(!StringUtils.isEmpty(value)){ value = HtmlUtil.filter(value); } values[i]=value; } } return values; } @Override public Map<String, String[]> getParameterMap() { Map<String, String[]> parameters = super.getParameterMap(); Map<String, String[]> map = new LinkedHashMap<>(); if(parameters !=null){ for(String key : parameters.keySet()){ String[] values = parameters.get(key); for(int i=0;i<values.length;i++){ String value = values[i]; if(!StringUtils.isEmpty(value)){ value = HtmlUtil.filter(value); } values[i]=value; } map.put(key,values); } } return map; } @Override public String getHeader(String name) { String value = super.getHeader(name); if(!StringUtils.isEmpty(value)){ value = HtmlUtil.filter(value); } return value; } @Override public ServletInputStream getInputStream() throws IOException { InputStream in = super.getInputStream(); InputStreamReader reader = new InputStreamReader(in, Charset.forName("UTF-8")); BufferedReader buffer = new BufferedReader(reader); StringBuffer body = new StringBuffer(); String line = buffer.readLine(); while (line !=null){ body.append(line); line = buffer.readLine(); } buffer.close(); reader.close(); in.close(); Map<String,Object> map = JSONUtil.parseObj(body.toString()); Map<String,Object> result = new LinkedHashMap<>(); for(String key : map.keySet()){ Object val = map.get(key); if(val instanceof String){ if(!StringUtils.isEmpty(val.toString())){ result.put(key,HtmlUtil.filter(val.toString())); } }else { result.put(key,val); } } String json = JSONUtil.toJsonStr(result); ByteArrayInputStream bain = new ByteArrayInputStream(json.getBytes()); return new ServletInputStream() { @Override public boolean isFinished() { return false; } @Override public boolean isReady() { return false; } @Override public void setReadListener(ReadListener readListener) { } @Override public int read() throws IOException { return bain.read(); } }; } }
可以理解为,在自定义过滤器中添加上面的增强类,那么所有请求后端的接口都将先走改类的逻辑,参数进行过滤
2、自定义过滤器并注入全局bean
public class XssFilter implements Filter { @Override public void init(FilterConfig filterConfig) throws ServletException { } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest)servletRequest; XssHttpRequestWrapper requestWrapper = new XssHttpRequestWrapper(request); filterChain.doFilter(requestWrapper,servletResponse); } @Override public void destroy() { } }
@Configuration public class XSSFilterRegister { @Bean public FilterRegistrationBean<XssFilter> RegistTest1(){ //通过FilterRegistrationBean实例设置优先级可以生效 FilterRegistrationBean<XssFilter> bean = new FilterRegistrationBean<XssFilter>(); bean.setFilter(new XssFilter());//注册自定义过滤器 bean.setName("flilter");//过滤器名称 bean.addUrlPatterns("/*");//过滤所有路径 return bean; } }
仍然使用上面的接口做一下测试
@PostMapping("/getAccName") public String getAccName(@RequestBody NameParams params){ return "name is : "+ params.getName(); }
通过这种方式,直接将注入的敏感标签符号去掉,这样确保了入库的数据的安全性,返回给页面的数据就不存在非法html标签问题了
到此这篇关于详解java解决XSS攻击常用方法总结的文章就介绍到这了,更多相关java XSS攻击 内容请搜索猪先飞以前的文章或继续浏览下面的相关文章希望大家以后多多支持猪先飞!
相关文章
- 这篇文章主要介绍了如何利用java语言实现经典《复杂迷宫》游戏,文中采用了swing技术进行了界面化处理,感兴趣的小伙伴可以动手试一试...2022-02-01
java 运行报错has been compiled by a more recent version of the Java Runtime
java 运行报错has been compiled by a more recent version of the Java Runtime (class file version 54.0)...2021-04-01- 这篇文章主要介绍了在java中获取List集合中最大的日期时间操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-15
- 这篇文章主要介绍了教你怎么用Java获取国家法定节假日,文中有非常详细的代码示例,对正在学习java的小伙伴们有非常好的帮助,需要的朋友可以参考下...2021-04-23
- 这篇文章主要介绍了Java如何发起http请求的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-31
- 说起C#和Java这两门语言(语法,数据类型 等),个人以为,大概有90%以上的相似,甚至可以认为几乎一样。但是在工作中,我也发现了一些细微的差别...2020-06-25
- 作为前端,一直以来都知道HTTP劫持与XSS跨站脚本、CSRF跨站请求伪造。防御这些劫持最好的方法是从后端入手,前端能做的太少。而且由于源码的暴露,攻击者很容易绕过防御手段。但这不代表我们去了解这块的相关知识是没意义的,本文的许多方法,用在其他方面也是大有作用。...2021-05-24
- 这篇文章主要介绍了解决Java处理HTTP请求超时的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-03-29
- 这篇文章主要介绍了java 判断两个时间段是否重叠的案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-15
java 画pdf用itext调整表格宽度、自定义各个列宽的方法
这篇文章主要介绍了java 画pdf用itext调整表格宽度、自定义各个列宽的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2021-01-31- 这篇文章主要介绍了超简洁java实现双色球若干注随机号码生成(实例代码),本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-04-02
- 这篇文章主要介绍了Java生成随机姓名、性别和年龄的实现示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2020-10-01
- 这篇文章主要介绍了java正则表达式判断前端参数修改表中另一个字段的值,需要的朋友可以参考下...2021-05-07
Java使用ScriptEngine动态执行代码(附Java几种动态执行代码比较)
这篇文章主要介绍了Java使用ScriptEngine动态执行代码,并且分享Java几种动态执行代码比较,需要的朋友可以参考下...2021-04-15- 这篇文章主要介绍了Java开发实现人机猜拳游戏,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2020-08-03
- 这篇文章主要介绍了Java List集合返回值去掉中括号('[ ]')的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-08-29
Java 8 Stream 的终极技巧——Collectors 功能与操作方法详解
这篇文章主要介绍了Java 8 Stream Collectors 功能与操作方法,结合实例形式详细分析了Java 8 Stream Collectors 功能、操作方法及相关注意事项,需要的朋友可以参考下...2020-05-20Java中lombok的@Builder注解的解析与简单使用详解
这篇文章主要介绍了Java中lombok的@Builder注解的解析与简单使用,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2021-01-06- 下面小编就为大家带来一篇java中String类型变量的赋值问题介绍。小编觉得挺不错的。现在分享给大家,给大家一个参考。...2016-03-28
- 这篇文章主要介绍了Java线程池中的各个参数如何合理设置操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教...2021-06-19