再看ibatis Order By注入问题
接上文
http://blog.itpub.net/29254281/viewspace-1318239/
领导让开发同学鼓捣一个可配置化的后台.
又回到了原来的问题
如果要灵活,很多参数要从前端页面传过来,有SQL注入的风险.
如果参数化SQL,又很难做到灵活..
先看一个注入的例子:
importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.ResultSet;importjava.sql.SQLException;importjava.sql.Statement;publicclassTest{publicstaticvoidmain(String[]args)throwsSQLException{Stringpara="/index.html'unionallselect*fromprobe--";Connectionconn=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mvbox","xx","xx");Statementps=conn.createStatement();ResultSetrs=ps.executeQuery("select*fromprobewherepath='"+para+"'");while(rs.next()){System.out.println(rs.getString("host")+":"+rs.getString("path"));}rs.close();ps.close();conn.close();}}
如果要避免这种风险,可以选择参数化
importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.PreparedStatement;importjava.sql.ResultSet;importjava.sql.SQLException;publicclassTest{publicstaticvoidmain(String[]args)throwsSQLException{Stringpara="/index.html'unionallselect*fromprobe--";Connectionconn=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mvbox","xx","xx");PreparedStatementps=conn.prepareStatement("select*fromprobewherepath=?");ps.setString(1,para);ResultSetrs=ps.executeQuery();while(rs.next()){System.out.println(rs.getString("host")+":"+rs.getString("path"));}rs.close();ps.close();conn.close();}}
为何参数化可以防止注入?
作为MySQL JDBC驱动来说(5.1.31),其实就是对敏感字符做了转义.
观察 com.mysql.jdbc.PreparedStatement 的 setString方法
可以看到有如下的替换过程
StringparameterAsString=x;booleanneedsQuoted=true;if(this.isLoadDataQuery||isEscapeNeededForString(x,stringLength)){needsQuoted=false;//savesanallocationlaterStringBufferbuf=newStringBuffer((int)(x.length()*1.1));buf.append('\'');////Note:buf.append(char)is_faster_than//appendinginblocks,becausetheblock//appendrequiresaSystem.arraycopy()....//gofigure...//for(inti=0;i<stringLength;++i){charc=x.charAt(i);switch(c){case0:/*Mustbeescapedfor'mysql'*/buf.append('\\');buf.append('0');break;case'\n':/*Mustbeescapedforlogs*/buf.append('\\');buf.append('n');break;case'\r':buf.append('\\');buf.append('r');break;case'\\':buf.append('\\');buf.append('\\');break;case'\'':buf.append('\\');buf.append('\'');break;case'"':/*Bettersafethansorry*/if(this.usingAnsiMode){buf.append('\\');}buf.append('"');break;case'\032':/*ThisgivesproblemsonWin32*/buf.append('\\');buf.append('Z');break;case'\u00a5':case'\u20a9'://escapecharactersinterpretedasbackslashbymysqlif(charsetEncoder!=null){CharBuffercbuf=CharBuffer.allocate(1);ByteBufferbbuf=ByteBuffer.allocate(1);cbuf.put(c);cbuf.position(0);charsetEncoder.encode(cbuf,bbuf,true);if(bbuf.get(0)=='\\'){buf.append('\\');}}//fallthroughdefault:buf.append(c);}}buf.append('\'');parameterAsString=buf.toString();}
是不是可以使用 iBatis 的 $ 方式 增加灵活性,而在参数进入iBatis之前,手工进行一下敏感字符替换,而防止SQL注入攻击呢?
http://blog.itpub.net/29254281/viewspace-1318239/
领导让开发同学鼓捣一个可配置化的后台.
又回到了原来的问题
如果要灵活,很多参数要从前端页面传过来,有SQL注入的风险.
如果参数化SQL,又很难做到灵活..
先看一个注入的例子:
importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.ResultSet;importjava.sql.SQLException;importjava.sql.Statement;publicclassTest{publicstaticvoidmain(String[]args)throwsSQLException{Stringpara="/index.html'unionallselect*fromprobe--";Connectionconn=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mvbox","xx","xx");Statementps=conn.createStatement();ResultSetrs=ps.executeQuery("select*fromprobewherepath='"+para+"'");while(rs.next()){System.out.println(rs.getString("host")+":"+rs.getString("path"));}rs.close();ps.close();conn.close();}}
如果要避免这种风险,可以选择参数化
importjava.sql.Connection;importjava.sql.DriverManager;importjava.sql.PreparedStatement;importjava.sql.ResultSet;importjava.sql.SQLException;publicclassTest{publicstaticvoidmain(String[]args)throwsSQLException{Stringpara="/index.html'unionallselect*fromprobe--";Connectionconn=DriverManager.getConnection("jdbc:mysql://127.0.0.1:3306/mvbox","xx","xx");PreparedStatementps=conn.prepareStatement("select*fromprobewherepath=?");ps.setString(1,para);ResultSetrs=ps.executeQuery();while(rs.next()){System.out.println(rs.getString("host")+":"+rs.getString("path"));}rs.close();ps.close();conn.close();}}
为何参数化可以防止注入?
作为MySQL JDBC驱动来说(5.1.31),其实就是对敏感字符做了转义.
观察 com.mysql.jdbc.PreparedStatement 的 setString方法
可以看到有如下的替换过程
StringparameterAsString=x;booleanneedsQuoted=true;if(this.isLoadDataQuery||isEscapeNeededForString(x,stringLength)){needsQuoted=false;//savesanallocationlaterStringBufferbuf=newStringBuffer((int)(x.length()*1.1));buf.append('\'');////Note:buf.append(char)is_faster_than//appendinginblocks,becausetheblock//appendrequiresaSystem.arraycopy()....//gofigure...//for(inti=0;i<stringLength;++i){charc=x.charAt(i);switch(c){case0:/*Mustbeescapedfor'mysql'*/buf.append('\\');buf.append('0');break;case'\n':/*Mustbeescapedforlogs*/buf.append('\\');buf.append('n');break;case'\r':buf.append('\\');buf.append('r');break;case'\\':buf.append('\\');buf.append('\\');break;case'\'':buf.append('\\');buf.append('\'');break;case'"':/*Bettersafethansorry*/if(this.usingAnsiMode){buf.append('\\');}buf.append('"');break;case'\032':/*ThisgivesproblemsonWin32*/buf.append('\\');buf.append('Z');break;case'\u00a5':case'\u20a9'://escapecharactersinterpretedasbackslashbymysqlif(charsetEncoder!=null){CharBuffercbuf=CharBuffer.allocate(1);ByteBufferbbuf=ByteBuffer.allocate(1);cbuf.put(c);cbuf.position(0);charsetEncoder.encode(cbuf,bbuf,true);if(bbuf.get(0)=='\\'){buf.append('\\');}}//fallthroughdefault:buf.append(c);}}buf.append('\'');parameterAsString=buf.toString();}
是不是可以使用 iBatis 的 $ 方式 增加灵活性,而在参数进入iBatis之前,手工进行一下敏感字符替换,而防止SQL注入攻击呢?
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。