springboot中怎么使用过滤器以及jsoup过滤XSS脚本怎么写(jsoup,springboot,xss,开发技术)

时间:2024-05-05 04:13:19 作者 : 石家庄SEO 分类 : 开发技术
  • TAG :

    springboot使用过滤器,jsoup过滤XSS脚本

    背景:略

    目标:完成request请求中的脚本过滤

    技术:filter,jsoup,requestWapper

    1.把可能包含脚本的参数位置分析一下

    • post/put/delete: 请求的参数中,有可能是表单提交、也有可能是使用了@requestBody注解,那么参数就是json格式,位于request的流中。

    • get/options等:可能存在于url参数中,也有可能是表单提交的预请求中,所以一般在能想到的位置都有可能存在,包括header中。

    2.分析实现过程

    2.1首先要从request请求中将各个需要过滤位置的参数取出来

    2.2然后将参数取出来进行过滤

    2.3将过滤后的参数重新包装成request传递下去

    2.4在这期间,

    • 需要准备好jsoup过滤脚本的工具类;

    • 需要自定义一个过滤器,并且在过滤器中添加匹配条件,如:那些url不需要过滤,那些请求方式必须进行过滤;

    • 对过滤器进行配置,是否开启,设置在整个过滤器链中的位置,设置过滤的白名单或者黑名单

    • 所以就很清晰了我们过滤需要哪些类,哪些配置了

    一个filter

    一个requestWapper

    一个jsoup工具类

    一个filter的配置类

    2.5进行数据测试

    3.代码实现过程

    3.1.jsoup依赖:

    <!--screenxss--><dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.9.2</version></dependency>

    3.2jsoup工具类:JsoupUtil

    importorg.jsoup.Jsoup;importorg.jsoup.nodes.Document;importorg.jsoup.safety.Whitelist;importjava.io.FileNotFoundException;importjava.io.IOException;/***@Auther:qianshanmuxue*@Date:2019/2/2719:32*@Description:xssIllegallabelfiltering*/publicclassJsoupUtil{privatestaticfinalWhitelistwhitelist=Whitelist.simpleText();//jsoup白名单种类,有四种,每一种针对的标签类型不一样,具体的可以ctrl+左键点击simpleText,在jsoup源码中有响应的注释和标签名单//addmyselfwhitelistlabelprivatestaticfinalDocument.OutputSettingsoutputSettings=newDocument.OutputSettings().prettyPrint(false);static{whitelist.addAttributes(":all","style").addTags("p").addTags("strong");//将自定义标签添加进白名单,除开白名单之外的标签都会被过滤whitelist.preserveRelativeLinks(true);//这个配置的意思的过滤如果找不到成对的标签,就只过滤单个标签,而不用把后面所有的文本都进行过滤。//(之前在这个问题上折腾了很久,当<script>标签只有一个时,会<script>标签后面的数据全部过滤)}publicstaticStringclean(Stringcontent){//过滤方法returnJsoup.clean(content,"",whitelist,outputSettings);}//testmainpublicstaticvoidmain(String[]args)throwsFileNotFoundException,IOException{Stringtext="<ahref=\"http://www.baidu.com/a\"onclick=\"alert(1);\"><strong><p>sss</p></strong></a><script>alert(0);</script>sss";System.out.println(clean(text));}}

    3.3request包装类XssHttpServletRequestWrapper

    importjava.io.*;importjava.util.*;importjavax.servlet.ReadListener;importjavax.servlet.ServletInputStream;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletRequestWrapper;importcom.xxx.utils.JsoupUtil;importorg.jsoup.nodes.Document;importorg.springframework.util.StringUtils;/***@Auther:qianshanmuxue*@Date:2019/2/2716:24*@Description:requestwapperusetogetrequestparameterandrequestbdoydataandwapperanotherrequest*/publicclassXssHttpServletRequestWrapperextendsHttpServletRequestWrapper{//因为我们需要获取request中的数据,所以需要继承java底层中HttpServletRequestWrapper这个类,重写父类中的某些方法,获取相应位置的参数privateHttpServletRequestorgRequest=null;privatestaticfinalDocument.OutputSettingsoutputSettings=newDocument.OutputSettings().prettyPrint(false);publicXssHttpServletRequestWrapper(HttpServletRequestrequest){super(request);orgRequest=request;}@OverridepublicServletInputStreamgetInputStream()throwsIOException{//getBufferedReaderbr=newBufferedReader(newInputStreamReader(orgRequest.getInputStream()));Stringline=br.readLine();Stringresult="";if(line!=null){result+=clean(line);}returnnewWrappedServletInputStream(newByteArrayInputStream(result.getBytes()));}@OverridepublicStringgetParameter(Stringname){if(("content".equals(name)||name.endsWith("WithHtml"))){returnsuper.getParameter(name);}name=clean(name);Stringvalue=super.getParameter(name);if(!StringUtils.isEmpty(value)){value=clean(value);}returnvalue;}@OverridepublicMapgetParameterMap(){Mapmap=super.getParameterMap();//返回值MapMap<String,String>returnMap=newHashMap<String,String>();Iteratorentries=map.entrySet().iterator();Map.Entryentry;Stringname="";Stringvalue="";while(entries.hasNext()){entry=(Map.Entry)entries.next();name=(String)entry.getKey();ObjectvalueObj=entry.getValue();if(null==valueObj){value="";}elseif(valueObjinstanceofString[]){String[]values=(String[])valueObj;for(inti=0;i<values.length;i++){value=values[i]+",";}value=value.substring(0,value.length()-1);}else{value=valueObj.toString();}returnMap.put(name,clean(value).trim());}returnreturnMap;}@OverridepublicString[]getParameterValues(Stringname){String[]arr=super.getParameterValues(name);if(arr!=null){for(inti=0;i<arr.length;i++){arr[i]=clean(arr[i]);}}returnarr;}/***getorgrequest**@return*/publicHttpServletRequestgetOrgRequest(){returnorgRequest;}/***wapperrequest*/publicstaticHttpServletRequestgetOrgRequest(HttpServletRequestreq){if(reqinstanceofXssHttpServletRequestWrapper){return((XssHttpServletRequestWrapper)req).getOrgRequest();}returnreq;}publicStringclean(Stringcontent){Stringresult=JsoupUtil.clean(content);returnresult;}privateclassWrappedServletInputStreamextendsServletInputStream{publicvoidsetStream(InputStreamstream){this.stream=stream;}privateInputStreamstream;publicWrappedServletInputStream(InputStreamstream){this.stream=stream;}@Overridepublicintread()throwsIOException{returnstream.read();}@OverridepublicbooleanisFinished(){returntrue;}@OverridepublicbooleanisReady(){returntrue;}@OverridepublicvoidsetReadListener(ReadListenerreadListener){}}}

    3.4filter-XssFilter

    importorg.apache.commons.lang.BooleanUtils;importorg.apache.commons.lang.StringUtils;importjava.io.IOException;importjava.util.ArrayList;importjava.util.List;importjava.util.regex.Matcher;importjava.util.regex.Pattern;importjavax.servlet.Filter;importjavax.servlet.FilterChain;importjavax.servlet.FilterConfig;importjavax.servlet.ServletException;importjavax.servlet.ServletRequest;importjavax.servlet.ServletResponse;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse;/***@Auther:qianshanmuxue*@Date:2019/2/2716:25*@Description:*///@WebFilter//@Component在这里可以不用这个注解,以为后面我们会在config中去配置这个filter,在这里只需要实现Filter接口实现相应的方法就okpublicclassXssFilterimplementsFilter{privatestaticbooleanIS_INCLUDE_RICH_TEXT=false;//用于接收配置中的参数,决定这个过滤器是否开启publicList<String>excludes=newArrayList<String>();//用于接收配置中的参数,决定哪些是不需要过滤的url(在这里,也可以修改handleExcludeURL()方法中相应的代码,使其变更为只需要过滤的url)@OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainchain)throwsIOException,ServletException{HttpServletRequestreq=(HttpServletRequest)request;HttpServletResponseresp=(HttpServletResponse)response;if(handleExcludeURL(req,resp)){chain.doFilter(request,response);return;}XssHttpServletRequestWrapperxssRequest=newXssHttpServletRequestWrapper((HttpServletRequest)request);chain.doFilter(xssRequest,response);}/***此方法是决定对当前url是否执行过滤,*在这里没有使用请求方法(post/put)来匹配,因为在本项目中使用url匹配更适合(因为get和其他请求方式也需要进行过滤),如果你有兴趣可以把这个方法更改为匹配请求方法进行过滤**/privatebooleanhandleExcludeURL(HttpServletRequestrequest,HttpServletResponseresponse){if((excludes==null||excludes.isEmpty())&&IS_INCLUDE_RICH_TEXT){returnfalse;}Stringurl=request.getServletPath();for(Stringpattern:excludes){Patternp=Pattern.compile("^"+pattern);Matcherm=p.matcher(url);if(m.find()){returntrue;}}returnfalse;}/***过滤器初始化,从配置类中获取参数,用于初始化两个参数(是否开启,排除指定的urllist)**/@Overridepublicvoidinit(FilterConfigarg0)throwsServletException{StringisIncludeRichText=arg0.getInitParameter("isIncludeRichText");if(StringUtils.isNotBlank(isIncludeRichText)){IS_INCLUDE_RICH_TEXT=BooleanUtils.toBoolean(isIncludeRichText);}Stringtemp=arg0.getInitParameter("excludes");if(temp!=null){String[]url=temp.split(",");for(inti=0;url!=null&&i<url.length;i++){excludes.add(url[i]);}}}@Overridepublicvoiddestroy(){}}

    3.5filter的配置类:XssConfig

    importcom.xxx.filter.XssFilter;importcom.google.common.collect.Maps;importorg.springframework.boot.web.servlet.FilterRegistrationBean;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;importjava.util.Map;/***@Auther:qianshanmuxue*@Date:2019/2/2716:49*@Description:xssfilterconfig*/@ConfigurationpublicclassXssConfig{@BeanpublicFilterRegistrationBeanxssFilterRegistrationBean(){FilterRegistrationBeanfilterRegistrationBean=newFilterRegistrationBean();filterRegistrationBean.setFilter(newXssFilter());filterRegistrationBean.setOrder(1);//filterorder,setitfirstfilterRegistrationBean.setEnabled(true);filterRegistrationBean.addUrlPatterns("/*");//setfilterallurlmappingMap<String,String>initParameters=Maps.newHashMap();initParameters.put("excludes","/oauth/token");///whitelisturlinitParameters.put("isIncludeRichText","true");//enableordisablefilterRegistrationBean.setInitParameters(initParameters);returnfilterRegistrationBean;}}

    调试截图:

    请求:

    springboot中怎么使用过滤器以及jsoup过滤XSS脚本怎么写

    程序截图:

    springboot中怎么使用过滤器以及jsoup过滤XSS脚本怎么写

    运行结果:

    springboot中怎么使用过滤器以及jsoup过滤XSS脚本怎么写

    可以看到body中 的脚本已经被过滤了,

    然后其他的截图我就不发了,还有一种思路就是在过滤器中把字符转义。

    感谢luckpet大佬的提示

    1 BufferedReader 使用完需要关闭 ;

    2 对于一些拿postman等工具的朋友,拼接json的话会有换行 这里result += clean(line); 需要改成: while((line = br.readLine()) != null){ if (line != null) { result += line; } }

    使用jsoup防止XSS攻击

    前阵子项目国测后,打开一个项目页面,莫名其妙弹出xss,搜了全局也没找到alert("xss"),问了一下项目经理,原来是国测做防注入的时候,在添加数据的时候做的,一脸懵逼。

    查了一下资料,以前做项目的时候都没想到这个问题,如果保存一段script脚本,查数据的时候,这段脚本就会被执行,这东西后果挺严重啊,如果是在桌面外弹框,执行个挖矿脚本,这玩意不得了啊,厉害,长知识了。。。

    <dependency><groupId>org.jsoup</groupId><artifactId>jsoup</artifactId><version>1.11.3</version></dependency>
     </div> <div class="zixun-tj-product adv-bottom"></div> </div> </div> <div class="prve-next-news">
    本文:springboot中怎么使用过滤器以及jsoup过滤XSS脚本怎么写的详细内容,希望对您有所帮助,信息来源于网络。
    上一篇:Myeclipse7.0如何汉化下一篇:

    12 人围观 / 0 条评论 ↓快速评论↓

    (必须)

    (必须,保密)

    阿狸1 阿狸2 阿狸3 阿狸4 阿狸5 阿狸6 阿狸7 阿狸8 阿狸9 阿狸10 阿狸11 阿狸12 阿狸13 阿狸14 阿狸15 阿狸16 阿狸17 阿狸18