SpringBoot如何防护XSSSQL注入攻击?终于懂了!
1。XSS跨站脚本攻击XSS漏洞介绍
跨站脚本攻击XSS是指攻击者往Web页面里插入恶意Script代码,当用户浏览该页之时,嵌入其中Web里面的Script代码会被解析执行,从而达到恶意攻击用户的目的。XSS攻击针对的是用户层面的攻击!
XSS漏洞分类
存储型XSS:存储型XSS,持久化,代码是存储在服务器中的,如在个人信息或发表文章等地方,插入代码,如果没有过滤或过滤不严,那么这些代码将储存到服务器中,用户访问该页面的时候触发代码执行。这种XSS比较危险,容易造成蠕虫,盗窃cookie
反射型XSS:非持久化,需要欺骗用户自己去点击链接才能触发XSS代码(服务器中没有这样的页面和内容),一般容易出现在搜索页面
DOM型XSS:不经过后端,DOMXSS漏洞是基于文档对象模型(DocumentObjeetModel,DOM)的一种漏洞,DOMXSS是通过url传入参数去控制触发的,其实也属于反射型XSS。防护建议限制用户输入,表单数据规定值得类型,例如年龄只能是int,name为字母数字组合。对数据进行htmlencode处理。过滤或移除特殊的html标签。过滤javascript事件的标签。2。SQL注入攻击SQL注入漏洞介绍
SQL注入(SQLi)是一种注入攻击,可以执行恶意SQL语句。它通过将任意SQL代码插入数据库查询,使攻击者能够完全控制Web应用程序后面的数据库服务器。攻击者可以使用SQL注入漏洞绕过应用程序安全措施;可以绕过网页或Web应用程序的身份验证和授权,并检索整个SQL数据库的内容;还可以使用SQL注入来添加,修改和删除数据库中的记录;关注公众号:码猿技术专栏,回复关键词:1111获取阿里内部Java性能优化手册!
SQL注入漏洞可能会影响使用SQL数据库(如MySQL,Oracle,SQLServer或其他)的任何网站或Web应用程序。犯罪分子可能会利用它来未经授权访问用户的敏感数据:客户信息,个人数据,商业机密,知识产权等。SQL注入攻击是最古老,最流行,最危险的Web应用程序漏洞之一。防护建议
使用mybatis中{}可以有效防止sql注入。
使用{}时:selectidgetBlogByIdresultTypeBlogparameterTypeintselectid,title,author,contentfromblogwhereid{id}select
打印出执行的sql语句,会看到sql是这样的:selectid,title,author,contentfromblogwhereid?
不管输入什么参数,打印出的sql都是这样的。这是因为mybatis启用了预编译功能,在sql执行前,会先将上面的sql发送给数据库进行编译,执行时,直接使用编译好的sql,替换占位符?就可以了。因为sql注入只能对编译过程起作用,所以像{}这样预编译成?的方式就很好地避免了sql注入的问题。
mybatis是如何做到sql预编译的呢?
其实在框架底层,是jdbc中的PreparedStatement类在起作用,PreparedStatement是我们很熟悉的Statement的子类,它的对象包含了编译好的sql语句。这种准备好的方式不仅能提高安全性,而且在多次执行一个sql时,能够提高效率,原因是sql已编译好,再次执行时无需再编译。
使用{}时selectidorderBlogresultTypeBlogparameterTypemapselectid,title,author,contentfromblogorderby{orderParam}select
仔细观察,内联参数的格式由{xxx}变为了{xxx}。如果我们给参数orderParam赋值为id,将sql打印出来,是这样的:selectid,title,author,contetfromblogorderbyid
显然,这样是无法阻止sql注入的,参数会直接参与sql编译,从而不能避免注入攻击。但涉及到动态表名和列名时,只能使用{}这样的参数格式,所以,这样的参数需要我们在代码中手工进行处理来防止注入。
其实,这些都在Java面试库小程序上都有答案,如果你近期准备面试跳槽,建议在上面刷题,涵盖2000道Java面试题,几乎覆盖了所有主流技术面试题。3。SpringBoot中如何防止XSS攻击和sql注入
对于Xss攻击和Sql注入,我们可以通过过滤器来搞定,可根据业务需要排除部分请求创建Xss请求过滤类XssHttpServletRequestWraper
代码如下:publicclassXssHttpServletRequestWraperextendsHttpServletRequestWrapper{LoggerlogLoggerFactory。getLogger(this。getClass());publicXssHttpServletRequestWraper(){super(null);}publicXssHttpServletRequestWraper(HttpServletRequesthttpservletrequest){super(httpservletrequest);}过滤springmvc中的RequestParam注解中的参数publicString〔〕getParameterValues(Strings){Stringstr〔〕super。getParameterValues(s);if(strnull){returnnull;}intistr。length;Stringas1〔〕newString〔i〕;for(intj0;ji;j){System。out。println(getParameterValues:str〔j〕);as1〔j〕cleanXSS(cleanSQLInject(str〔j〕));}log。info(XssHttpServletRequestWraper净化后的请求为:as1);returnas1;}过滤request。getParameter的参数publicStringgetParameter(Strings){Strings1super。getParameter(s);if(s1null){returnnull;}else{Strings2cleanXSS(cleanSQLInject(s1));log。info(XssHttpServletRequestWraper净化后的请求为:s2);returns2;}}过滤请求体json格式的OverridepublicServletInputStreamgetInputStream()throwsIOException{finalByteArrayInputStreambaisnewByteArrayInputStream(inputHandlers(super。getInputStream())。getBytes());returnnewServletInputStream(){Overridepublicintread()throwsIOException{returnbais。read();}OverridepublicbooleanisFinished(){returnfalse;}OverridepublicbooleanisReady(){returnfalse;}OverridepublicvoidsetReadListener(ReadListenerreadListener){}};}publicStringinputHandlers(ServletInputStreamservletInputStream){StringBuildersbnewStringBuilder();BufferedReaderreadernull;try{readernewBufferedReader(newInputStreamReader(servletInputStream,Charset。forName(UTF8)));Stringline;while((linereader。readLine())!null){sb。append(line);}}catch(IOExceptione){e。printStackTrace();}finally{if(servletInputStream!null){try{servletInputStream。close();}catch(IOExceptione){e。printStackTrace();}}if(reader!null){try{reader。close();}catch(IOExceptione){e。printStackTrace();}}}returncleanXSS(sb。toString());}publicStringcleanXSS(Stringsrc){Stringtempsrc;srcsrc。replaceAll(,)。replaceAll(,);srcsrc。replaceAll((,()。replaceAll(),));srcsrc。replaceAll(,);srcsrc。replaceAll(;,;);bgh20180530新增startsrcsrc。replaceAll(,lt;)。replaceAll(,gt;);srcsrc。replaceAll((,40;)。replaceAll(),41);srcsrc。replaceAll(eval((。)),);srcsrc。replaceAll(〔〕〔s〕javascript:(。)〔〕,);srcsrc。replaceAll(script,);srcsrc。replaceAll(link,);srcsrc。replaceAll(frame,);endPatternpatternPattern。compile((eval((。))script),Pattern。CASEINSENSITIVE);Matchermatcherpattern。matcher(src);srcmatcher。replaceAll();patternPattern。compile(〔〕〔s〕javascript:(。)〔〕,Pattern。CASEINSENSITIVE);matcherpattern。matcher(src);srcmatcher。replaceAll();增加脚本srcsrc。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);thrownewCustomerException(xss攻击检查:参数含有非法攻击字符,已禁止继续访问!!);}returnsrc;}输出publicvoidoutputMsgByOutputStream(HttpServletResponseresponse,Stringmsg)throwsIOException{ServletOutputStreamoutputStreamresponse。getOutputStream();获取输出流response。setHeader(contenttype,texthtml;charsetUTF8);通过设置响应头控制浏览器以UTF8的编码显示数据,如果不加这句话,那么浏览器显示的将是乱码byte〔〕dataByteArrmsg。getBytes(UTF8);将字符转换成字节数组,指定以UTF8编码进行转换outputStream。write(dataByteArr);使用OutputStream流向客户端输出字节数组}需要增加通配,过滤大小写组合publicStringcleanSQLInject(Stringsrc){StringlowSrcsrc。toLowerCase();Stringtempsrc;StringlowSrcAfterlowSrc。replaceAll(insert,forbidI)。replaceAll(select,forbidS)。replaceAll(update,forbidU)。replaceAll(delete,forbidD)。replaceAll(and,forbidA)。replaceAll(or,forbidO);if(!lowSrcAfter。equals(lowSrc)){log。error(sql注入检查:输入信息存在SQL攻击!);log。error(原始输入信息temp);log。error(处理后信息lowSrc);thrownewCustomerException(sql注入检查:参数含有非法攻击字符,已禁止继续访问!!);}returnsrc;}}把请求过滤类XssHttpServletRequestWraper添加到Filter中,注入容器ComponentpublicclassXssFilterimplementsFilter{LoggerlogLoggerFactory。getLogger(this。getClass());忽略权限检查的url地址privatefinalString〔〕excludeUrlsnewString〔〕{null};publicvoiddoFilter(ServletRequestarg0,ServletResponsearg1,FilterChainarg2)throwsIOException,ServletException{HttpServletRequestreq(HttpServletRequest)arg0;HttpServletResponseresponse(HttpServletResponse)arg1;StringpathInforeq。getPathInfo()null?:req。getPathInfo();获取请求url的后两层Stringurlreq。getServletPath()pathInfo;获取请求你ip后的全部路径Stringurireq。getRequestURI();注入xss过滤器实例XssHttpServletRequestWraperreqWnewXssHttpServletRequestWraper(req);过滤掉不需要的Xss校验的地址for(Stringstr:excludeUrls){if(uri。indexOf(str)0){arg2。doFilter(arg0,response);return;}}过滤arg2。doFilter(reqW,response);}publicvoiddestroy(){}publicvoidinit(FilterConfigfilterconfig1)throwsServletException{}}
上述代码已经可以完成请求参数、JSON请求体的过滤,但对于json请求体还有其他的方式实现,有兴趣的请看下面的扩展!
扩展:还可以重写spring中的MappingJackson2HttpMessageConverter来过滤Json请求体
因为请求体在进出Contoroller时,会经过MappingJackson2HttpMessageConverter的一个转换,把请求体转换成我们需要的json格式,所以可以在这里边做一些修改!ConfigurationpublicclassMyConfiguration{BeanpublicMappingJackson2HttpMessageConvertermappingJackson2HttpMessageConverter(){自定义转换器MappingJackson2HttpMessageConverterconverternewMappingJackson2HttpMessageConverter();转换器日期格式设置ObjectMapperobjectMappernewObjectMapper();SimpleDateFormatsmtnewSimpleDateFormat(yyyyMMddHH:mm:ss);objectMapper。setDateFormat(smt);converter。setObjectMapper(objectMapper);转换器添加自定义Module扩展,主要是在这里做XSS过滤的!!,其他的是其他业务,不用看SimpleModulesimpleModulenewSimpleModule();添加过滤逻辑类!simpleModule。addDeserializer(String。class,newStringDeserializer());converter。getObjectMapper()。registerModule(simpleModule);设置中文编码格式ListMediaTypelistnewArrayList();list。add(MediaType。APPLICATIONJSONUTF8);converter。setSupportedMediaTypes(list);returnconverter;}}
真正的过滤逻辑类StringDeserializer:检验请求体的参数ComponentpublicclassStringDeserializerextendsJsonDeserializerString{OverridepublicStringdeserialize(JsonParserjsonParser,DeserializationContextdeserializationContext)throwsIOException,JsonProcessingException{StringstrjsonParser。getText()。trim();sql注入拦截if(sqlInject(str)){thrownewCustomerException(参数含有非法攻击字符,已禁止继续访问!);}returnxssClean(str);}publicbooleansqlInject(Stringstr){if(StringUtils。isEmpty(str)){returnfalse;}去掉;字符strorg。apache。commons。lang3。StringUtils。replace(str,,);strorg。apache。commons。lang3。StringUtils。replace(str,,);strorg。apache。commons。lang3。StringUtils。replace(str,;,);strorg。apache。commons。lang3。StringUtils。replace(str,,);转换成小写strstr。toLowerCase();非法字符String〔〕keywords{master,truncate,insert,select,delete,update,declare,alert,alter,drop};判断是否包含非法字符for(Stringkeyword:keywords){if(str。indexOf(keyword)!1){returntrue;}}returnfalse;}xss攻击拦截publicStringxssClean(Stringvalue){if(valuenull。equals(value)){returnvalue;}非法字符String〔〕keywords{,,,(),),(,javascript:,script,alter,,};判断是否包含非法字符for(Stringkeyword:keywords){if(value。indexOf(keyword)!1){thrownewCustomerException(参数含有非法攻击字符,已禁止继续访问!);}}returnvalue;}}
使用这种形式也可以完成json请求体的过滤,但个人更推荐使用XssHttpServletRequestWraper的形式来完成xss过滤!!最后说一句(别白嫖,求关注)
每一篇文章都是精心输出,如果这篇文章对你有所帮助,或者有所启发的话,帮忙点赞、关注、转发,你的支持就是我坚持下去的最大动力!
麦田长出十层高楼?河南虞城建设手续不完备,立案查处12月18日,河南商丘虞城县委宣传部微信公众号虞城发布针对河南芒种桥乡麦田长出十层高楼一事发布情况说明近日,网上关于河南芒种桥乡麦田长出十层高楼的信息出现后,虞城县委县政府高度重视
竞价看龙头竞价看龙头财联社12月19日电,市场焦点股格力地产(6板)竞价涨停,食品饮料板块西安饮食(5板)低开1。16黑芝麻(5天4板)高开2。39全聚德(3天2板)高开8。70,新冠防治概
婚后七年的生活状态变化,简直太过于真实,你是否也在其中?在游戏当中做个皇帝,也是很不错的。少转给我十元!奥特曼都解决不了的问题,把我也给难住了。这样的公司,你喜欢吗?小时候得不到的东西,长大后一定要得到。是魔怔。遇事xian不要慌,拿个
发展油茶产业恰逢其时来源经济日报油茶是我国特有的木本油料植物,与油橄榄油棕椰子并称世界四大木本油料植物,在我国已经有2000多年种植历史。它生长在山中,不与人争田,不与粮争地,有大力发展之必要。从保障
从小就做漫画主人公!嘉定妈妈用90幅漫画记录孩子成长初为父母,总想记录下孩子成长的珍贵瞬间。有人选择拍照片,有人选择写亲子日记,而安亭这位85后妈妈则以漫画的方式,记录儿子狗宝成长的点点滴滴。2018年,陈丽霞的儿子出生,因正值农历
远见超童丨最全自然拼读法基本规则和小窍门,掌握后见词就能读!自然拼读法(Phonics)是指看到一个英语单词,就可以根据英文字母在单词里的发音规律把这个单词念出来的一种方法。在美国,小孩从三岁起,就开始接受自然拼读法的教育了,这种拼读方法是
2022年的9种新型智商税,不要再上当了头号周刊矫形鞋垫。真正的矫形鞋垫,跟配眼镜一样,需要进行一系列专业的分析检查,量身定制。而网上很多卖的都是野鸡鞋垫,不仅没有正规标签合格证,而且起不到矫形的作用,不仅治不了扁平足,
妈妈被形容像陀螺,楷模也挺难的原创观点,谢绝抄袭看到杜熊粉夸某个人的妈妈,居然用陀螺来形容,忽然觉得,像楷模这样自称直来直去的人,应该想到的不是陀螺的喻意,而是字面意思。那就是说,她妈妈就像陀螺,圆且短,还是别
41岁伊万卡全家出游!她穿开叉裙把名媛范刻进骨子里,女儿胖乎乎伊万卡曾经贵为韩国第一千金,出色的外貌跟高情商,让她为特朗普挽回了很多形象分,可以说是爸爸的好帮手,不过在特朗普继续竞争总统之位时,伊万卡却公开表示,不会再为父助选,完全回归了自己
身为星二代,事业远不如同学杨紫李现,在县委大院中被骂惨了正午阳光出品,必属精品,这口号至今还是很响亮,在年底播出的县委大院,一开播就火了。电视剧走红除了剧情非常的真实接地气外,庞大的演员阵容,也是这部电视剧成功吸引眼球的一个关键原因。电
东方玛丽莲梦露,一生只爱一个人钟楚红的美丽,是全香港的骄傲8090年代的香港娱乐圈流行一句话再发,发不过周润发再红,红不过钟楚红。周润发与钟楚红,他们是终生挚友,生命经历也相仿,皆是底层社会扎根,从南丫岛和重庆大厦的穷苦少年少女,攀至香港