防止sql注入的最好方式

  1. 避免 SQL injection 攻击的传统方法之一是,把它作为一个输入合法性检查的问题来处理,只接受列在白名单中的字符,或者识别并避免那些列在黑名单中的恶意数据。白名单方法是一种非常有效方法,它可以强制执行严格的输入检查规则,但是参数化的 SQL 指令所需维护更少,而且能提供更好的安全保障。而对于通常采用的列黑名单方式,由于总是存在一些小漏洞,所以并不能有效地防止 SQL injection 威胁。例如,攻击者可以:
  2. — 把没有被黑名单引用的值作为目标
  3. — 寻找方法以绕过对某一转义序列元字符的需要
  4. — 使用存储过程来隐藏注入的元字符
  5. 上述所提到的1,2,3,4,5,白黑名单的方式则是来自于下面的文章Foritfy --Detail --Sql注入中的相关解释;
 
除了上述所提到的白黑名单的方式以外,在Sql注入中Java的最好实现方式则是,通过使用预编译的手段来实现,JDBC的实现则是使用PreparedStatement .setString(0,"")等的方式实现预编译,sql中则使用 ? 作为占位符而存在,
Hibernate中则也是通过书写hql,采用占位符的方式,再进行setParameter的方式进行参数封装即可,目前在产品中出现的一些问题则是,老的代码中存在过多的 sql 或 hql 使用 ++等方式拼接而成的执行语句,导致Fortify安全测试扫描时,出现过多的sql注入问题,
那么除此之外,为什么使用SetParameter等预编译的形式,可以阻断sql注入等的情况的发生呢,我们是否也可以模拟一个sql预编译前的代码效果,在执行sql前,先进行一下过滤呢?(似乎有点是类似于白黑名单的方式),但此处更想表明的是setParameter所做的那些操作,避免了sql注入的问题,下面简单的贴一些jdbc中setString时所做的一些操作,并不是所想象中的,直接按照位置,和形参中所得到的sql,进行一下简单的替换而已噢,在jdbc中set赋值时,还是相对交于复杂的,
(注:mybatis中,在进行传参时,就是直接使用的 ?的形式进行占位赋值,所以基本上现有的常用orm框架mybatis以及hibernate,包括jdbc都已经解决了sql注入的问题,只要使用得当一般是都没什么问题的)。
jdbc中setString时的部分源码截图:
如上所展示的3个截图,其实也只是setString时的 2/3 的代码,所以可以看到,在sql防注入的方式上,jdbc的PreparedStatement类中所做的处理操作还是很多的,
在直接setObject的时候:
PreparedStatement的操作则是使用 instanceof 判断 所要占位符赋值的类型,然后再调用相关的setInteger(),setString等方法进行赋值;
参考链接中有个知乎链接,还是很不错的,推荐可看;
 
可参考:
 

posted @ 2019-11-15 17:51  陈咬金  阅读(8813)  评论(0编辑  收藏  举报