当前位置:网站首页>mysql进阶(二十四)防御SQL注入的方法总结
mysql进阶(二十四)防御SQL注入的方法总结
2022-08-03 11:36:00 【InfoQ】
一、前言
这篇文章主要讲解了防御SQL注入的方法,介绍了什么是注入,注入的原因是什么,以及如何防御,需要的朋友可以参考下。
SQL注入是一类危害极大的攻击形式。虽然危害很大,但是防御却远远没有XSS那么困难。
SQL注入可以参见:
https://en.wikipedia.org/wiki/SQL_injection
SQL注入漏洞存在的原因,就是拼接 SQL 参数。也就是将用于输入的查询参数,直接拼接在 SQL 语句中,导致了SQL 注入漏洞。
二、演示下经典的SQL注入
我们看到:
select id,no from user where id=2;
如果该语句是通过sql字符串拼接得到的,比如:
String sql = "select id,no from user where id=" + id;
其中的 id 是一个用户输入的参数,那么,如果用户输入的是 2, 那么上面看到查到了一条数据,如果用户输入的是 2 or 1=1 进行sql注入攻击。
那么看到,上面的语句(
select id,no from user where id=2 or 1=1;
)将user表中的所有记录都查出来了。
这就是典型的sql注入。
再看一列:
我们看到通过 sql 注入能够直接将表 sqlinject 删除掉!可见其危害!
三、sql注入的原因
sql注入的原因,表面上说是因为拼接字符串,构成sql语句,没有使用sql语句预编译,绑定变量造成的。
但是更深层次的原因是将用户输入的字符串,当成了“sql语句”来执行。
比如上面的
String sql = "select id,no from user where id=" + id;
我们希望用户输入的id的值,仅仅作为一个字符串字面值,传入数据库执行,但是当输入了:2 or 1=1 时,其中的
or 1=1
并没有作为
where id=
的字面值,而是作为了 sql语句 来执行的。所以其本质是将用户的输入的数据,作为了命令来执行。
四、sql注入的防御
基本上大家都知道采用
sql语句预编译
和
绑定变量
,是防御sql注入的最佳方法。但是其中的深层次原因就不见得都理解了。
String sql = "select id, no from user where id=?";
PreparedStatement ps = conn.prepareStatement(sql);
ps.setInt(1, id);
ps.executeQuery();
如上所示,就是典型的采用sql语句预编译和绑定变量。为什么这样就可以防止sql 注入呢?
其原因就是:采用了
PreparedStatement
,就会将sql语句:"
select id, no from user where id=?
" 预先编译好,也就是SQL引擎会预先进行语法分析,产生语法树,生成执行计划,也就是说,后面你输入的参数,无论你输入的是什么,都不会影响该sql语句的语法结构了,因为语法分析已经完成了,而语法分析主要是分析sql命令,比如
select ,from ,where ,and, or ,order by
等等。所以即使你后面输入了这些sql命令,也不会被当成sql命令来执行了,因为这些sql命令的执行,必须先得通过语法分析,生成
执行计划
,既然语法分析已经完成,已经预编译过了,那么后面输入的参数,是绝对不可能作为sql命令来执行的,只会被当做字符串字面值参数。所以sql语句预编译可以防御sql注入。
但是,不是所有场景都能够采用 sql语句预编译,有一些场景必须的采用字符串拼接的方式,此时,我们严格检查参数的数据类型,还有可以使用一些安全函数,来方式sql注入。
比如
String sql = "select id,no from user where id=" + id;
在接收到用户输入的参数时,我们就严格检查 id,只能是int型。复杂情况可以使用正则表达式来判断。这样也是可以防止sql注入的。
安全函数的使用,比如:
MySQLCodec codec = new MySQLCodec(Mode.STANDARD);
name = ESAPI.encoder().encodeForSQL(codec, name);
String sql = "select id,no from user where name=" + name;
ESAPI.encoder().encodeForSQL(codec, name)
该函数会将 name 中包含的一些特殊字符进行编码,这样 sql 引擎就不会将name中的字符串当成sql命令来进行语法分析了。
五、总结
实际项目中,一般我们都是采用各种的框架,比如
ibatis,mybatis,hibernate
等等。他们一般也默认就是sql预编译的。对于
ibatis/mybatis
,如果使用的是
#{name}
形式的,那么就是sql预编译,使用
${name}
就不是sql预编译的。
以上就是SQL注入防御方法总结,希望对大家之后的学习有所帮助。
边栏推荐
- 当前页面的脚本发生错误如何解决_电脑出现当前页面脚本错误怎么办
- 【HCIP持续更新】STP协议相关保护机制
- 【JDBC以及内部类的讲解】
- 小身材有大作用——光模块基础知识(一)
- Cookie and Session usage
- [Explanation of JDBC and inner classes]
- 深度学习跟踪DLT (deep learning tracker)
- 微信为什么使用 SQLite 保存聊天记录?
- viewstub 的详细用法_pageinfo用法
- For invoice processing DocuWare, cast off the yoke of the paper and data input, automatic processing all the invoice received
猜你喜欢
随机推荐
2022年五面蚂蚁、三面拼多多、字节跳动最终拿offer入职拼多多
技术总监需要会些什么?也太难了!
小身材有大作用——光模块基础知识(一)
【Mysql】清理binlog日志的方法
从零开始Blazor Server(6)--基于策略的权限验证
Matlab学习13-图像处理之可视化GUI程序
LeetCode-142. 环形链表 II
矩阵的计算[通俗易懂]
Matlab学习12-图像处理之图像增强
Skills required to be a good architect: How to draw a system architecture that everyone will love?What's the secret?Come and open this article to see it!...
记住用户名案例(js)
本周四晚19:00知识赋能第4期直播丨OpenHarmony智能家居项目之设备控制实现
代码分析Objective-C中的深拷贝与浅拷贝
什么是Weex
劝退背后。
QGIS绘制演习区域示意图
LyScript 实现对内存堆栈扫描
[Detailed explanation of binary search plus recursive writing method] with all the code
LP流动性挖矿DAPP系统开发丨流动性挖矿功能原理及说明
用于发票处理的 DocuWare,摆脱纸张和数据输入的束缚,自动处理所有收到的发票