SpringCloud(五十一)Gateway拦截器实现防止
SQL注入是常见的系统安全问题之一,用户通过特定方式向系统发送SQL脚本,可直接自定义操作系统数据库,如果系统没有对SQL注入进行拦截,那么用户甚至可以直接对数据库进行增删改查等操作。
XSS全称为CrossSiteScript跨站点脚本攻击,和SQL注入类似,都是通过特定方式向系统发送攻击脚本,对系统进行控制和侵害。SQL注入主要以攻击数据库来达到攻击系统的目的,而XSS则是以恶意执行前端脚本来攻击系统。
项目框架中使用mybatismybatisplus数据持久层框架,在使用过程中,已有规避SQL注入的规则和使用方法。但是在实际开发过程中,由于各种原因,开发人员对持久层框架的掌握水平不同,有些特殊业务情况必须从前台传入SQL脚本。这时就需要对系统进行加固,防止特殊情况下引起的系统风险。
在微服务架构下,我们考虑如何实现SQL注入XSS攻击拦截时,肯定不会在每个微服务都实现一遍SQL注入XSS攻击拦截。根据我们微服务系统的设计,所有的请求都会经过Gateway网关,所以在实现时就可以参照前面的日志拦截器来实现。在接收到一个请求时,通过拦截器解析请求参数,判断是否有SQL注入XSS攻击参数,如果有,那么返回异常即可。
我们前面在对微服务Gateway进行自定义扩展时,增加了Gateway插件功能。我们会根据系统需求开发各种Gateway功能扩展插件,并且可以根据系统配置文件来启用禁用这些插件。下面我们就将防止SQL注入XSS攻击拦截器作为一个Gateway插件来开发和配置。1、新增SqlInjectionFilter过滤器和XssInjectionFilter过滤器,分别用于解析请求参数并对参数进行判断是否存在SQL注入XSS攻脚本。此处有公共判断方法,通过配置文件来读取请求的过滤配置,因为不是多有的请求都会引发SQL注入和XSS攻击,如果无差别的全部拦截和请求,那么势必影响到系统的性能。判断SQL注入的拦截器防sql注入authorGitEggLog4j2AllArgsConstructorpublicclassSqlInjectionFilterimplementsGlobalFilter,Ordered{。。。。。。当返回参数为true时,解析请求参数和返回参数if(shouldSqlInjection(exchange)){MultiValueMapString,StringqueryParamsrequest。getQueryParams();booleanchkRetGetParamsSqlInjectionRuleUtils。mapRequestSqlKeyWordsCheck(queryParams);booleanchkRetJsonfalse;booleanchkRetFormDatafalse;HttpHeadersheadersrequest。getHeaders();MediaTypecontentTypeheaders。getContentType();longlengthheaders。getContentLength();if(length0null!contentType(contentType。includes(MediaType。APPLICATIONJSON)contentType。includes(MediaType。APPLICATIONJSONUTF8))){chkRetJsonSqlInjectionRuleUtils。jsonRequestSqlKeyWordsCheck(gatewayContext。getRequestBody());}if(length0null!contentTypecontentType。includes(MediaType。APPLICATIONFORMURLENCODED)){log。debug(〔RequestLogFilter〕(Request)FormData:{},gatewayContext。getFormData());chkRetFormDataSqlInjectionRuleUtils。mapRequestSqlKeyWordsCheck(gatewayContext。getFormData());}if(chkRetGetParamschkRetJsonchkRetFormData){returnWebfluxResponseUtils。responseWrite(exchange,参数中不允许存在sql关键字);}returnchain。filter(exchange);}else{returnchain。filter(exchange);}}。。。。。。}判断XSS攻击的拦截器防xss注入authorGitEggLog4j2AllArgsConstructorpublicclassXssInjectionFilterimplementsGlobalFilter,Ordered{。。。。。。当返回参数为true时,记录请求参数和返回参数if(shouldXssInjection(exchange)){MultiValueMapString,StringqueryParamsrequest。getQueryParams();booleanchkRetGetParamsXssInjectionRuleUtils。mapRequestSqlKeyWordsCheck(queryParams);booleanchkRetJsonfalse;booleanchkRetFormDatafalse;HttpHeadersheadersrequest。getHeaders();MediaTypecontentTypeheaders。getContentType();longlengthheaders。getContentLength();if(length0null!contentType(contentType。includes(MediaType。APPLICATIONJSON)contentType。includes(MediaType。APPLICATIONJSONUTF8))){chkRetJsonXssInjectionRuleUtils。jsonRequestSqlKeyWordsCheck(gatewayContext。getRequestBody());}if(length0null!contentTypecontentType。includes(MediaType。APPLICATIONFORMURLENCODED)){log。debug(〔RequestLogFilter〕(Request)FormData:{},gatewayContext。getFormData());chkRetFormDataXssInjectionRuleUtils。mapRequestSqlKeyWordsCheck(gatewayContext。getFormData());}if(chkRetGetParamschkRetJsonchkRetFormData){returnWebfluxResponseUtils。responseWrite(exchange,参数中不允许存在XSS注入关键字);}returnchain。filter(exchange);}else{returnchain。filter(exchange);}}。。。。。。}2、新增SqlInjectionRuleUtils工具类和XssInjectionRuleUtils工具类,通过正则表达式,用于判断参数是否属于SQL注入XSS攻击脚本。通过正则表达式对参数进行是否有SQL注入风险的判断防sql注入工具类authorGitEggSlf4jpublicclassSqlInjectionRuleUtils{SQL的正则表达式privatestaticStringbadStrRegb(andor)b。{1,6}?(binbblikeb)。?lt;sscriptbbEXECbUNION。?SELECTUPDATE。?SETINSERTsINTO。?VALUES(SELECTDELETE)。?FROM(CREATEALTERDROPTRUNCATE)s(TABLEDATABASE);SQL的正则表达式privatestaticPatternsqlPatternPattern。compile(badStrReg,Pattern。CASEINSENSITIVE);sql注入校验mapparammapreturnpublicstaticbooleanmapRequestSqlKeyWordsCheck(MultiValueMapString,Stringmap){对post请求参数值进行sql注入检验returnmap。entrySet()。stream()。parallel()。anyMatch(entry{这里需要将参数转换为小写来处理StringlowerValueOptional。ofNullable(entry。getValue())。map(Object::toString)。map(String::toLowerCase)。orElse();if(sqlPattern。matcher(lowerValue)。find()){log。error(参数〔{}〕中包含不允许sql的关键词,lowerValue);returntrue;}returnfalse;});}sql注入校验jsonparamvaluereturnpublicstaticbooleanjsonRequestSqlKeyWordsCheck(Stringvalue){if(JSONUtil。isJsonObj(value)){JSONObjectjsonJSONUtil。parseObj(value);MapString,Objectmapjson;对post请求参数值进行sql注入检验returnmap。entrySet()。stream()。parallel()。anyMatch(entry{这里需要将参数转换为小写来处理StringlowerValueOptional。ofNullable(entry。getValue())。map(Object::toString)。map(String::toLowerCase)。orElse();if(sqlPattern。matcher(lowerValue)。find()){log。error(参数〔{}〕中包含不允许sql的关键词,lowerValue);returntrue;}returnfalse;});}else{JSONArrayjsonJSONUtil。parseArray(value);ListObjectlistjson;对post请求参数值进行sql注入检验returnlist。stream()。parallel()。anyMatch(obj{这里需要将参数转换为小写来处理StringlowerValueOptional。ofNullable(obj)。map(Object::toString)。map(String::toLowerCase)。orElse();if(sqlPattern。matcher(lowerValue)。find()){log。error(参数〔{}〕中包含不允许sql的关键词,lowerValue);returntrue;}returnfalse;});}}}通过正则表达式对参数进行是否有XSS攻击风险的判断XSS注入过滤工具类authorGitEggpublicclassXssInjectionRuleUtils{privatestaticfinalPattern〔〕PATTERNS{Avoidanythingina,Pattern。CASEINSENSITIVE),Avoidanythinginasrca2020imgdataimg。jpgdatasrc。。。typeofexpressionPattern。compile(src〔r〕〔r〕(。?),Pattern。CASEINSENSITIVEPattern。MULTILINEPattern。DOTALL),Pattern。compile(src〔r〕〔r〕(。?),Pattern。CASEINSENSITIVEPattern。MULTILINEPattern。DOTALL),RemoveanylonesomescripttagPattern。compile(script,Pattern。CASEINSENSITIVE),Avoidanythingina,Pattern。CASEINSENSITIVE),Removeanylonesome