【Mysql安全】防止sql注入

  • (1)什么是sql注入
  • (2)寻找sql注入的方法
  • (3)mybatis是如何做到防止sql注入的
    • (3.1)sql对比
    • (3.2)简单分析
    • (3.3)底层实现原理
    • (3.4)总结#{}和${}的区别
    • (3.5)总结
    • (3.6)如果手工处理“${xxx}”
  • (3)常见的sql注入问题:数据库查询参数的类型转换处理
  • (4)防范sql注入的思路
  • (5)放置sql注入的方法

(1)什么是sql注入

(1)概念
“SQL注入”是一种利用未过滤/未审核用户输入的攻击方法(“缓存溢出”和这个不同),意思就是让应用运行本不应该运行的SQL代码。就是通过sql命令插入到web表单提交或者输入域名或者页面请求的查询字符串,最终达到欺骗服务器执行恶意的sql命令。

在一些安全性要求很高的应用中(比如银行软件),经常使用将SQL语句全部替换为存储过程这样的方式,来防止SQL注入。这当然是一种很安全的方式,但我们平时开发中,可能不需要这种死板的方式。

(2)案例

  1. 正常登陆:用户名:admin 密码:admin
  2. 在正常用户名admin后增加一个单引号,单击"登录"。或在URL地址栏直接输入http://172.18.3.13:81/login.asp?name=admin’&pass=admin,若出错,证明没有对’进行过滤,存在SQL注入漏洞
  3. 开始sql注入攻击,输入http://172.18.3.13:81/login.asp?pass=admin&name=admin’ and 1=1 and ‘a’='a,原SQL语句为SELECT * FROM data Where uname=‘admin’ and 1=1 and ‘a’=‘a’,登录成功
  4. 猜解数据库表名,http://172.18.3.13:81/login.asp?pass=admin&name=admin’ and (select count(*) from data)>0 and ‘a’='a,成功,说明数据表名确为data;若不成功,则可反复测试,直至成功猜出表名
  5. 猜解数据库字段名,http://172.18.3.13:81/login.asp?pass=admin&name=admin’and (select count(uname) from data)>0 and ‘a’='a,若用户名字段确为uname,则提示登录成功,同理可猜出密码字段为upass
  6. 猜解密码长度
  7. 猜解密码

(2)寻找sql注入的方法

(1)通过get请求
(2)通过post请求
(3)其他http请求,如cookie

(3)mybatis是如何做到防止sql注入的

(3.1)sql对比

<select id="selectByNameAndPassword" parameterType="java.util.Map" resultMap="BaseResultMap">
select id, username, password, role
from user
where username = #{username,jdbcType=VARCHAR}
and password = #{password,jdbcType=VARCHAR}
</select><select id="selectByNameAndPassword" parameterType="java.util.Map" resultMap="BaseResultMap">
select id, username, password, role
from user
where username = #{username,jdbcType=VARCHAR}
and password = #{password,jdbcType=VARCHAR}
</select>

(3.2)简单分析

MyBatis的SQL是一个具有“输入+输出”的功能,类似于函数的结构,参考上面的两个例子。其中,parameterType表示了输入的参数类型,resultType表示了输出的参数类型。如果我们想防止SQL注入,理所当然地要在输入参数上下功夫。上面代码中使用#的即输入参数在SQL中拼接的部分,传入参数后,打印出执行的SQL语句,会看到SQL是这样的:

select id, username, password, role from user where username=? and password=?

因为MyBatis启用了预编译功能,在SQL执行前,会先将上面的SQL发送给数据库进行编译;等到执行时,直接使用编译好的SQL,#{username}直接替换成占位符“?”就可以了。因为SQL注入只能对编译过程起作用,所以这种“预编译”+“占位符替换”的方式就很好地避免了SQL注入的问题。

(3.3)底层实现原理

MyBatis是如何做到SQL预编译的呢?其实在框架底层,是JDBC中的PreparedStatement类在起作用,PreparedStatement是我们很熟悉的Statement的子类,它的对象包含了编译好的SQL语句。这种“准备好”的方式不仅能提高安全性,而且在多次执行同一个SQL时,能够提高效率。原因是SQL已编译好,再次执行时无需再编译。

(3.4)总结#{}和${}的区别

(1)# 将传入的数据都当成一个字符串,会对自动传入的数据加一个双引号。如:where username=#{username},如果传入的值是111,那么解析成sql时的值为where username=“111”, 如果传入的值是id,则解析成的sql为where username=“id”.

(2)$ 将传入的数据直接显示生成在sql中。
如:where username=${username},如果传入的值是111,那么解析成sql时的值为where username=111;
如果传入的值是;drop table user;,则解析成的sql为:select id, username, password, role from user where username=;drop table user;

(3)#方式能够很大程度防止sql注入,$方式无法防止Sql注入。

(4)$方式一般用于传入数据库对象,例如传入表名.

(5)一般能用#的就别用,若不得不使用“,若不得不使用“,若不得不使用“{xxx}”这样的参数,要手工地做好过滤工作,来防止sql注入攻击。

(6)在MyBatis中,“xxx”这样格式的参数会直接参与SQL编译,从而不能避免注入攻击。但涉及到动态表名和列名时,只能使用“{xxx}”这样格式的参数会直接参与SQL编译,从而不能避免注入攻击。但涉及到动态表名和列名时,只能使用“xxx”这样格式的参数会直接参与SQL编译,从而不能避免注入攻击。但涉及到动态表名和列名时,只能使用“{xxx}”这样的参数格式。所以,这样的参数需要我们在代码中手工进行处理来防止注入。

(3.5)总结

#{}:相当于JDBC中的PreparedStatement,会先进行预处理,然后使用占位符?替换,是安全的,避免sql注入问题
${}:是输出变量的值,就像取配置文件里的值一样。不做任何处理,就可能存在sql注入的危险。

在编写MyBatis的映射语句时,尽量采用“#{xxx}”这样的格式。若不得不使用“${xxx}”这样的参数,要手工地做好过滤工作,来防止SQL注入攻击。

(3.6)如果手工处理“${xxx}”

如判断一下输入的参数的长度是否正常(注入语句一般很长),更精确的过滤则可以查询一下输入的参数是否在预期的参数集合中。

(3)常见的sql注入问题:数据库查询参数的类型转换处理

(4)防范sql注入的思路

(1)普通用户与系统管理员用户的权限要有严格的区分
在权限设计中,对于终端用户,即应用软件的使用者,没有必要给他们数据库对象的建立、删除等权限。那么即使在他们使用SQL语句中带有嵌入式的恶意代码,由于其用户权限的限制,这些代码也将无法被执行。故应用程序在设计的时候,最好把系统管理员的用户与普通用户区分开来。如此可以最大限度的减少注入式攻击对数据库带来的危害。

(2)强迫使用参数化语句
如果在编写SQL语句的时候,用户输入的变量不是直接嵌入到SQL语句。而是通过参数来传递这个变量的话,那么就可以有效的防治SQL注入式攻击。也就是说,用户的输入绝对不能够直接被嵌入到SQL语句中。与此相反,用户的输入的内容必须进行过滤,或者使用参数化的语句来传递用户输入的变量。参数化的语句使用参数而不是将用户输入变量嵌入到SQL语句中。采用这种措施,可以杜绝大部分的SQL注入式攻击。不过可惜的是,现在支持参数化语句的数据库引擎并不多。不过数据库工程师在开发产品的时候要尽量采用参数化语句。

(3)加强对用户输入的验证
总体来说,防治SQL注入式攻击可以采用两种方法,一是加强对用户输入内容的检查与验证;二是强迫使用参数化语句来传递用户输入的内容。在SQLServer数据库中,有比较多的用户输入内容验证工具,可以帮助管理员来对付SQL注入式攻击。测试字符串变量的内容,只接受所需的值。拒绝包含二进制数据、转义序列和注释字符的输入内容。这有助于防止脚本注入,防止某些缓冲区溢出攻击。测试用户输入内容的大小和数据类型,强制执行适当的限制与转换。这即有助于防止有意造成的缓冲区溢出,对于防治注入式攻击有比较明显的效果。
  如可以使用存储过程来验证用户的输入。利用存储过程可以实现对用户输入变量的过滤,如拒绝一些特殊的符号。如以上那个恶意代码中,只要存储过程把那个分号过滤掉,那么这个恶意代码也就没有用武之地了。在执行SQL语句之前,可以通过数据库的存储过程,来拒绝接纳一些特殊的符号。在不影响数据库应用的前提下,应该让数据库拒绝包含以下字符的输入。如分号分隔符,它是SQL注入式攻击的主要帮凶。如注释分隔符。注释只有在数据设计的时候用的到。一般用户的查询语句中没有必要注释的内容,故可以直接把他拒绝掉,通常情况下这么做不会发生意外损失。把以上这些特殊符号拒绝掉,那么即使在SQL语句中嵌入了恶意代码,他们也将毫无作为。
  故始终通过测试类型、长度、格式和范围来验证用户输入,过滤用户输入的内容。这是防止SQL注入式攻击的常见并且行之有效的措施。

(4)多多使用SQL Server数据库自带的安全参数
  为了减少注入式攻击对于SQL Server数据库的不良影响,在SQLServer数据库专门设计了相对安全的SQL参数。在数据库设计过程中,工程师要尽量采用这些参数来杜绝恶意的SQL注入式攻击。
  如在SQL Server数据库中提供了Parameters集合。这个集合提供了类型检查和长度验证的功能。如果管理员采用了Parameters这个集合的话,则用户输入的内容将被视为字符值而不是可执行代码。即使用户输入的内容中含有可执行代码,则数据库也会过滤掉。因为此时数据库只把它当作普通的字符来处理。使用Parameters集合的另外一个优点是可以强制执行类型和长度检查,范围以外的值将触发异常。如果用户输入的值不符合指定的类型与长度约束,就会发生异常,并报告给管理员。如上面这个案例中,如果员工编号定义的数据类型为字符串型,长度为10个字符。而用户输入的内容虽然也是字符类型的数据,但是其长度达到了20个字符。则此时就会引发异常,因为用户输入的内容长度超过了数据库字段长度的限制。

(5)多层环境如何防治SQL注入式攻击
在多层应用环境中,用户输入的所有数据都应该在验证之后才能被允许进入到可信区域。未通过验证过程的数据应被数据库拒绝,并向上一层返回一个错误信息。实现多层验证。对无目的的恶意用户采取的预防措施,对坚定的攻击者可能无效。更好的做法是在用户界面和所有跨信任边界的后续点上验证输入。如在客户端应用程序中验证数据可以防止简单的脚本注入。但是,如果下一层认为其输入已通过验证,则任何可以绕过客户端的恶意用户就可以不受限制地访问系统。故对于多层应用环境,在防止注入式攻击的时候,需要各层一起努力,在客户端与数据库端都要采用相应的措施来防治SQL语句的注入式攻击。

(6)必要的情况下使用专业的漏洞扫描工具来寻找可能被攻击的点
使用专业的漏洞扫描工具,可以帮助管理员来寻找可能被SQL注入式攻击的点。不过漏洞扫描工具只能发现攻击点,而不能够主动起到防御SQL注入攻击的作用。当然这个工具也经常被攻击者拿来使用。如攻击者可以利用这个工具自动搜索攻击目标并实施攻击。为此在必要的情况下,企业应当投资于一些专业的漏洞扫描工具。一个完善的漏洞扫描程序不同于网络扫描程序,它专门查找数据库中的SQL注入式漏洞。最新的漏洞扫描程序可以查找最新发现的漏洞。所以凭借专业的工具,可以帮助管理员发现SQL注入式漏洞,并提醒管理员采取积极的措施来预防SQL注入式攻击。如果攻击者能够发现的SQL注入式漏洞数据库管理员都发现了并采取了积极的措施堵住漏洞,那么攻击者也就无从下手了。

(7)设置陷阱账号
设置两个帐号,一个是普通管理员帐号,一个是防注入的帐号。将防注入的账号设置的很象管理员,如 admin,以制造假象吸引软件的检测,而密码是大于千字以上的中文字符,迫使软件分析账号的时候进入全负荷状态甚至资源耗尽而死机。

(5)放置sql注入的方法

我们永远不要信任用户的输入,我们必须认定用户输入的数据都是不安全的,我们都需要对用户输入的数据进行过滤处理。

(1)检查变量数据类型和格式(不灵活,要写死多个检测方法)

  1. 使用正则表达式过滤传入的参数
  2. PHP函数检查变量
  3. 前端js检查是否包函非法字符

(2)过滤特殊符号

(3)绑定变量,使用预编译语句(最优解)
MySQL的mysqli驱动提供了预编译语句的支持,不同的程序语言,都分别有使用预编译语句的方法。

实际上,绑定变量使用预编译语句是预防SQL注入的最佳方式,使用预编译的SQL语句语义不会发生改变,在SQL语句中,变量用问号?表示,黑客即使本事再大,也无法改变SQL语句的结构,像上面例子中,username变量传递的plhwin’ AND 1=1-- hack参数,也只会当作username字符串来解释查询,从根本上杜绝了SQL注入攻击的发生。

【Mysql优化安全】防止sql注入相关推荐

  1. golang mysql 防注入_Go,Gorm 和 Mysql 是如何防止 SQL 注入的

    Go,Gorm 和 Mysql 是如何防止 SQL 注入的 SQL 注入和 SQL 预编译技术 什么是 SQL 注入 所谓SQL注入(sql inject),就是通过把SQL命令插入到Web表单提交或 ...

  2. mysql优化说出九条_技术分享 | MySQL 优化:为什么 SQL 走索引还那么慢?

    原标题:技术分享 | MySQL 优化:为什么 SQL 走索引还那么慢? 背景 2019-01-11 9:00-10:00 一个 MySQL 数据库把 CPU 打满了. 硬件配置:256G 内存,48 ...

  3. MySQL for Java的SQL注入测试

    2019独角兽企业重金招聘Python工程师标准>>> 只要你学JDBC,基本上所有的人都会和你说,Statement不能防止SQL注入, PreparedStatement能够防止 ...

  4. [Mysql] 防御和检查SQL注入攻击的手段

    SQL注入攻击的种类 知彼知己,方可取胜.首先要清楚SQL注入攻击有哪些种类. 1.没有正确过滤转义字符 在用户的输入没有为转义字符过滤时,就会发生这种形式的注入式攻击,它会被传递给一个SQL语句.这 ...

  5. MySQL编码转换防止SQL注入_node-mysql中防止SQL注入

    为了防止SQL注入,可以将SQL中传入参数进行编码,而不是直接进行字符串拼接.在node-mysql中,防止SQL注入的常用方法有以下四种: 方法一:使用escape()对传入参数进行编码: 参数编码 ...

  6. php使用mysql预处理语句防止sql注入 简单讲解及代码实现

    目录 前言 sql注入简单介绍 一个例子 使用预处理语句 简介 预处理语句的查询 预处理语句获取查询结果 总结 前言 最近在做一个小项目的后台,牵扯到登录等等需要操作数据库的地方,为了安全起见,特地来 ...

  7. MySQL优化篇:SQL优化流程

    MySQL中SQL优化流程 SQL优化流程如下: 慢查询的开启并捕获 explain+慢SQL分析 show profile查询SQL在MySQL服务器里面的执行细节和生命周期情况 SQL数据库服务器 ...

  8. MySQL优化之三:SQL语句优化

    一 SQL语句优化的一般步骤: 1 通过show status命令了解各种SQL语句的执行频率 mysql> show status;                #show status:显 ...

  9. mysql 走索引 很慢_技术分享 | MySQL优化:为什么SQL走索引还那么慢?

    作者:胡呈清 背景 2019-01-11 9:00-10:00 一个 MySQL 数据库把 CPU 打满了. 硬件配置:256G 内存,48 core 分析过程 接手这个问题时现场已经不在了,信息有限 ...

  10. php mysql addslashes,关于mysql:Php addslashes sql注入仍然有效吗?

    mysql日志显示此查询 SELECT * FROM   users WHERE  username = '?\' OR username = username /*' AND    password ...

最新文章

  1. 更好的内存管理-jemalloc (redis 默认使用的)
  2. ASP.NET中序列化与反序列化-以显示上一次登录的信息为例
  3. [NHibernate]获取分组查询的记录总数
  4. mac vim python3_VIM学习笔记 编译源码(Compile Code)-Python
  5. Java高级进阶:自定义ClassLoader
  6. Linux内核源码分析--内核启动之(4)Image内核启动(setup_arch函数)(Linux-3.0 ARMv7)【转】...
  7. 黄聪:Android酷炫实用的开源框架(UI框架)(转)
  8. 为什么当前互联网+法律发展艰难?
  9. 都市男女的32声叹息
  10. mongodb创建图书管理_基于MongoDB的云数据库管理系统的设计与实现
  11. apt不询问直接安装
  12. java反编译jar包
  13. 联想拯救者R720笔记本换三星970 EVO PLUS 500G固态硬盘与加装联想内存条16GX2,固态硬盘降温设置方法
  14. 看透网络执法官的本质
  15. 机器学习笔记 - 深度学习的预处理和图像白化
  16. sublime教程以及python环境的配置(二)常用插件安装和Boxy主题配置
  17. 2003sql php_Windows Server 2003下安装PHP +mssql2000
  18. 【魔兽世界插件】魔兽世界插件实战笔记从入门到放弃的心理历程 第三节-窗体颜色设置与渐变
  19. 微信朋友圈怎么设置对单人开放?
  20. PBOC规范研究之四、文件结构及访问

热门文章

  1. 【FAQ】鸿蒙3.0无法读取系统日历数据,也无法写入新的日历数据
  2. Win10的IE以及其他浏览器无法使用的解决方法
  3. [提权禁区]利用vbs添加管理员用户
  4. 使用js生成登录验证码
  5. 嵌入式软件工程师招聘
  6. rnss和rdss的应用_浅谈北斗二代RDSS与RNSS组合技术
  7. maven 项目运行找不到类
  8. 多线程爪巴虫下载进击的巨人 v.2
  9. Matplotlib科研画图.调色盘颜色提取和更改
  10. html隐藏标签disable,HTML 中 Link 元素 disable 属性详解