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实现的默认行为,也就是说,不同的数据库表现不同,不能一概而论。

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

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 4g网络设置dns地址_4G网速越来越慢,通过这三个简单的操作,网速成倍提升[通俗易懂]

    随着互联网的进步,从零几年开始移动手机在全国开始普及起来,网速也像火箭一样快速飙升,从2G发展到了现在的5G。不过,有很多网友表示,刚从2G或者3G升级到4G时,网速体验非常好,但近两年来的4G网速越来越慢,还卡顿,甚至感觉还不如以前的3g网络。那么今天,小编就为大家介绍调整手机上网慢和卡顿的三个方法,助你快速提升4G网速!方法一:打电话给运营商客服来刷新上网数据小编为大家介绍的第一个方法是近期最…

  • web服务器有哪几种_web服务器的虚拟目录

    web服务器有哪几种_web服务器的虚拟目录当我们打开电脑,通过浏览器看到的网站,所有网站服务器多是我们所说的web服务器,具体解释就是一种驻留在Internet上的计算机程序,web服务器通过存储网站文件,放置大小不一各类数据文件,来进行工作,所以世界上每个角落多有它的身影。我们常见的Web服务器协议有三种,1、HTTP协议,2、HTML文档格式,最后是浏览器统一资源定位器,也就是我们常见的URL。第一种:IISIIS是我们网站用的最普遍的web服务器,IIS允许在公共网络上或者普通网络上发布信息的服务器,使IIS成为使用最广的web服务器之

  • 【IObit】五大软件激活码( Advanced Systemcare….)

    【IObit】五大软件激活码( Advanced Systemcare….)IObitMalwareFighter6Pro激活成功教程:打开软件安装位置,下载替换dll文件链接: https://pan.baidu.com/s/1Euz87MCANuCnRqZs

  • Maven 打包命令

    Maven 打包命令cmd命令:–>跳过测试mvn clean -Dmaven.test.skip=true package -P prod运行:java-jarxxx.jarlinux下运行jarLinux运行jar包命令如下:方式一:java -jar XXX.jar特点:当前ssh窗口被锁定,可按CTRL+C打断程序运行,或直接关闭窗口,程序退出那如何让窗口不锁定?方式二:java -jar …

  • TextMate已激活成功教程

    TextMate已激活成功教程在pcbeta的帖子里找到了这个传说中的MAC杀手级武器的激活成功教程,针对的是1.5.8版本,摘抄如下:这个号称TheMissingEditorforMacOSX的编辑器我就不介绍了,我就说说如何注册吧。第一种方法:花39欧元第二种方法:UninstallfirstandInstalagain,justopentheTextMateunix(Apps

  • Java开发手册之索引规约「建议收藏」

    Java开发手册之索引规约「建议收藏」Java开发手册之索引规约

发表回复

您的电子邮箱地址不会被公开。

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