当前位置: 首页 > 科技观察

Java最新的SQL注入原因及预防解决方案(通俗易懂)_0

时间:2023-03-14 22:38:30 科技观察

前沿的SQL注入预防在现有框架中已经做得很好,我们需要做的是尽量不要使用sql拼接来调用javasql注入原因及预防解决方案(通俗易懂)1.SQL注入1.1原理SQL注入是通过客户端的输入,将SQL命令注入到应用数据库中,从而执行恶意的SQL语句。1.2演示1.2.1案例1有一个登录框需要输入用户名和密码,然后输入我们的密码'或'123'='123这样。当我们查询用户名和密码是否正确时,原来执行的sql语句是:select*fromuserwhereusername=''andpassword=''。这样一条sql语句,现在我们如上输入密码,然后我们将通过参数进行拼接,拼接后的sql语句为:select*fromuserwhereusername=''andpassword=''or'123'='123';如果是这样,那么就会出现or语句,只要这两个其中一个正确,则条件成立,所以123=123成立。因此跳过验证。这只是一个简单的例子。1.2.2Case2密码是这样的:';droptableuser;,在这种情况下,sql命令变为:select*fromuserwhereusername=''andpassword='';droptableuser;',那么此时我们就直接删除user表。1.3预防1.3.1前端前端表单控制参数格式;1.3.2我们可以在后台使用准备好的语句(PreparedStatement)。在这种情况下,即使我们使用sql语句作为参数,当它到达服务器时,伪造的sql语句的参数也只是一个简单的字符,起不到攻击的作用。使用正则表达式过滤传入参数注意:切勿将未经检查的用户输入值直接传递给数据库java来判断验证字符串是否包含sql包cn.javanode.thread;importjava.util.regex。Pattern;/***@authorxgt(小光头)*@version1.0*@date2021-1-811:48*/publicclassCheckSqlDemo{/**正则表达式**/privatestaticStringreg="(?:')|(?:--)|(/\\*(?:.|[\\n\\r])*?\\*/)|"+"(\\b(选择|更新|联合|和|或|delete|insert|trancate|char|into|substr|ascii|declare|exec|count|master|into|drop|execute)\\b)";privatestaticPatternsqlPattern=Pattern.compile(reg,Pattern.CASE_INSENSITIVE);privatestaticbooleanisValid(Stringstr){if(sqlPattern.matcher(str).find()){System.out.println("过滤失败:str="+str);returnfalse;}returntrue;}publicstaticvoidmain(String[]args){System.out.println(isValid("tongji_user_add"));}}补充PreparedStatement如何防止SQL注入?1、拼接参数(sql注入)Connectionconnection=DriverManager.getConnection(DB_URL,USER,PASS);PreparedStatementpreparedStatement=connection。prepareStatement(sql);Stringparam="'test'or1=1";Stringsql="selectfilefromfilewherename="+param;//拼接SQL参数ResultSetresultSet=preparedStatement.executeQuery();System.out.println(resultSet.next());输出结果为真,DB中执行的SQL是--永恒条件1=1成为查询条件的一部分,可以返回所有数据,导致SQL注入问题selectfilefromfilewherename='test'or1=12。setString(anti-injection)Connectionconnection=DriverManager.getConnection(DB_URL,USER,PASS);PreparedStatementpreparedStatement=connection.prepareStatement(sql);preparedStatement.setString(1,account);//设置参数preparedStatement.setString(2,password);ResultSetresultSet=preparedStatement.executeQuery();//执行查询sql得到结果集输出结果为false,DB中执行的SQL为selectfilefromfilewherename='\'test\'or1=1'。我们可以看到输出的SQL将整个参数用引号包裹起来,并且将参数中的引号作为转义符,从而避免了参数作为条件的一部分3.源码分析结论preparedStatement.setString会判断是否为符号当前参数的of需要转义,如果是,则加上转义符,如果不需要,直接加引号//完整代码publicvoidsetString(intparameterIndex,Stringx)throwsSQLException{synchronized(checkClosed().getConnectionMutex()){//如果传入的字符串为空,则设置该列为空(x==null){setNull(parameterIndex,Types.CHAR);}else{checkClosed();intstringLength=x.length();if(this.connection.isNoBackslashEscapesSet()){//Scanforanynastychars//判定是否需要转义booleanneedsHexEscape=isEscapeNeededForString(x,stringLength);if(!needsHexEscape){byte[]parameterAsBytes=null;StringBuilderquotedString=newStringBuilder(x.length()+2);quotedString.append('\'');quotedString.append(x);quotedString.append('\'');if(!this.isLoadDataQuery){parameterAsBytes=StringUtils.getBytes(quotedString.toString(),this.charConverter,this.charEncoding,this.connection.getServerCharset(),this.connection.parserKnowsUnicode(),getExceptionInterceptor());}else{//SendwithplatformcharacterencodingparameterAsBytes=StringUtils.getBytes(quotedString.toString());}setInternal(parameterIndex,parameterAsBytes);}else{byte[]parameterAsBytes=null;if(!this.isLoadDataQuery){parameterAsBytes=StringUtils.getBytes(x,this.charConverter,this.charEncoding,this.connection.getServerCharset(),this.connection.parserKnowsUnicode(),getExceptionInterceptor());}else{//SendwithplatformcharacterencodingparameterAsBytes=StringUtils.getBytes(x);}setBytes(parameterIndex,parameterAsBytes);}return;}【小编推荐】这篇文章教你检测虚拟环境是否正常物理机、虚拟机或容器?对比9款代码质量工具,看看哪个更好用推荐十个程序员钓鱼有用的网站,我来玩玩吧!2021年网络安全趋势:更高的预算、对端点和云安全的重视为什么编码员不应该在面试中同意编码测试