sql注入及用PrepareStatement就不用担心sql注入了吗?

sql注入及用PrepareStatement就不用担心sql注入了吗?首先讲一下sql注入所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。比如先前的很多影视网站泄露

大家好,又见面了,我是你们的朋友全栈君。

首先讲一下sql注入

所谓SQL注入,就是通过把SQL命令插入到Web表单提交或输入域名或页面请求的查询字符串,最终达到欺骗服务器执行恶意的SQL命令。具体来说,它是利用现有应用程序,将(恶意)的SQL命令注入到后台数据库引擎执行的能力,它可以通过在Web表单中输入(恶意)SQL语句得到一个存在安全漏洞的网站上的数据库,而不是按照设计者意图去执行SQL语句。比如先前的很多影视网站泄露VIP会员密码大多就是通过WEB表单递交查询字符暴出的,这类表单特别容易受到sql注入攻击。
验证绕过漏洞就是’or’=’or’后台绕过漏洞,利用的就是AND和OR的运算规则,从而造成后台脚本逻辑性错误。
先举个例子,你要登录一个网站,上面让你输入用户名字和密码。那么,假如你输入的用户名是 admin ,但是你不知道密码,你就输入了一个 1′ OR ‘1’ = ‘1 ,那么,你就提交了两个参数给服务器。假如,服务器拿这两个参数拼SQL语句:SELECT T.* FROM XXX_TABLE TWHERE T.USER_ID = ‘/*param1*/’AND T.PASSWORD = ‘/*param2*/’那么,你提交的两个参数就使SQL文变成了:SELECT T.* FROM XXX_TABLE TWHERE T.USER_ID = ‘admin’AND T.PASSWORD = ‘1’ OR ‘1’ = ‘1’那么,这个SQL原来的校验功能就被你绕过去了,你的这种行为就称之为SQL注入。

接下来用PrepareStatement就不用担心sql注入了吗?

下面内容转载自https://www.cnblogs.com/iyangyuan/archive/2015/09/15/4809494.html
 言归正传,对java有了解的同学基本上都体验过JDBC,基本都了解PreparedStatement,PreparedStatement相比Statement基本解决了SQL注入问题,而且效率也有一定提升。
     关于PreparedStatement和Statement其他细节我们不讨论,只关心注入问题。无论读者是老鸟还是菜鸟,都需要问一下自己,PreparedStatement真的百分百防注入吗?
     接下来我们研究一下PreparedStatement如何防止注入,本文以MySQL数据库为例。
     为了避免篇幅过长,我这里只贴代码片段,希望读者能有一定的基础。
PreparedStatement st = conn.prepareStatement(sql); st.setString(1, "儿童"); // 参数赋值 System.out.println(st.toString()); //com.mysql.jdbc.JDBC4PreparedStatement@d704f0: select * from goods where min_name = '儿童'

这段代码属于JDBC常识了,就是简单的根据参数查询,看不出什么端倪,但假如有人使坏,想注入一下呢?

String sql = "select * from goods where min_name = ?"; // 含有参数 PreparedStatement st = conn.prepareStatement(sql); st.setString(1, "儿童'"); // 参数赋值 System.out.println(st.toString()); //com.mysql.jdbc.JDBC4PreparedStatement@d704f0: select * from goods where min_name = '儿童\''


 简单的在参数后边加一个单引号,就可以快速判断是否可以进行SQL注入,这个百试百灵,如果有漏洞的话,一般会报错。
     之所以PreparedStatement能防止注入,是因为它把单引号转义了,变成了\’,这样一来,就无法截断SQL语句,进而无法拼接SQL语句,基本上没有办法注入了。
     所以,如果不用PreparedStatement,又想防止注入,最简单粗暴的办法就是过滤单引号,过滤之后,单纯从SQL的角度,无法进行任何注入。
     其实,刚刚我们提到的是String参数类型的注入,大多数注入,还是发生在数值类型上,幸运的是PreparedStatement为我们提供了st.setInt(1, 999);这种数值参数赋值API,基本就避免了注入,因为如果用户输入的不是数值类型,类型转换的时候就报错了。
     好,现在读者已经了解PreparedStatement会对参数做转义,接下来再看个例子。

String sql = "select * from goods where min_name = ?"; // 含有参数 PreparedStatement st = conn.prepareStatement(sql); st.setString(1, "儿童%"); // 参数赋值 System.out.println(st.toString()); //com.mysql.jdbc.JDBC4PreparedStatement@8543aa: select * from goods where min_name = '儿童%'

 我们尝试输入了一个百分号,发现PreparedStatement竟然没有转义,百分号恰好是like查询的通配符。
     正常情况下,like查询是这么写的:

String sql = "select * from goods where min_name = ?"; // 含有参数 PreparedStatement st = conn.prepareStatement(sql); st.setString(1, "儿童%"); // 参数赋值 System.out.println(st.toString()); //com.mysql.jdbc.JDBC4PreparedStatement@8543aa: select * from goods where min_name = '儿童%'


  查询min_name字段以”儿童”开头的所有记录,其中”儿童”二字是用户输入的查询条件,百分号是我们自己加的,怎么可能让用户输入百分号嘛!等等!如果用户非常聪明,偏要输入百分号呢?

String sql = "select * from goods where min_name like ?"; // 含有参数 st = conn.prepareStatement(sql); st.setString(1, "%儿童%" + "%"); // 参数赋值 System.out.println(st.toString()); //com.mysql.jdbc.JDBC4PreparedStatement@8543aa: select * from goods where min_name like '%儿童%%'


 聪明的用户直接输入了”%儿童%”,整个查询的意思就变了,变成包含查询。实际上不用这么麻烦,用户什么都不输入,或者只输入一个%,都可以改变原意。
     虽然此种SQL注入危害不大,但这种查询会耗尽系统资源,从而演化成拒绝服务攻击。
     那如何防范呢?笔者能想到的方案如下:
        
          ·直接拼接SQL语句,然后自己实现所有的转义操作。这种方法比较麻烦,而且很可能没有PreparedStatement做的好,造成其他更大的漏洞,不推荐。
          ·直接简单暴力的过滤掉%。笔者觉得这方案不错,如果没有严格的限制,随便用户怎么输入,既然有限制了,就干脆严格一些,干脆不让用户搜索%,推荐。
        
     目前做搜索,只要不是太差的公司,一般都有自己的搜索引擎(例如著名的java开源搜索引擎solr),很少有在数据库中直接like的,笔者并不是想在like上钻牛角尖,而是提醒读者善于思考,每天都在写着重复的代码,却从来没有停下脚步细细品味。
     有读者可能会问,为什么我们不能手动转义一下用户输入的%,其他的再交给PreparedStatement转义?这个留作思考题,动手试一下就知道为什么了。
     注意,JDBC只是java定义的规范,可以理解成接口,每种数据库必须有自己的实现,实现之后一般叫做数据库驱动,本文所涉及的PreparedStatement,是由MySQL实现的,并不是JDK实现的默认行为,也就是说,不同的数据库表现不同,不能一概而论。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/138874.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • phpstorm2021.9激活码[最新免费获取]

    (phpstorm2021.9激活码)好多小伙伴总是说激活码老是失效,太麻烦,关注/收藏全栈君太难教程,2021永久激活的方法等着你。IntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,下面是详细链接哦~https://javaforall.net/100143.htmlS32PGH0SQB-eyJsaWNlbnNlSWQi…

    2022年3月26日
    48
  • SQL 对decimal类型转换为int类型

    SQL 对decimal类型转换为int类型CAST(SaleQtyASINT)-CAST(ISNULL(Qty,0)ASINT)CountQtyselectISNULL(CAST(E.QtyASINT),0)FROMOrderDetailE空值需要默认为0即可转载于:https://www.cnblogs.com/Warmsunshine/p/10868864.html…

    2022年7月20日
    19
  • hive基础总结(面试常用)

    hive基础总结(面试常用)

    2021年6月29日
    77
  • PHP编程效率的20个要点

    PHP编程效率的20个要点

    2021年10月9日
    40
  • IntentService的原理及使用

    在Android开发中,我们或许会碰到这么一种业务需求,一项任务分成几个子任务,子任务按顺序先后执行,子任务全部执行完后,这项任务才算成功。那么,利用几个子线程顺序执行是可以达到这个目的的,但是每个线程必须去手动控制,而且得在一个子线程执行完后,再开启另一个子线程。或者,全部放到一个线程中让其顺序执行。这样都可以做到,但是,如果这是一个后台任务,就得放到Service里面,由于Service和Ac

    2022年4月7日
    41
  • 如何制作bom表_如何制作bom表

    如何制作bom表_如何制作bom表(全路径Excel软件视频教程都可领取会员后免费学习)点我领会员免费学Excel全套基础入门教程!一、Excel软件入门MicrosoftExcel是Microsoft为使用Windows和AppleMacintosh操作系统的电脑编写的一款电子表格软件。直观的界面、出色的计算功能和图表工具,再加上成功的市场营销,使Excel成为最流行的个人计算机数据处理软件。第一章软件入门介绍第1课软件…

    2022年8月29日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号