1.sql注入是什么
sql注入见名知意,是指一些非法用户通过将一些特殊字符或者sql语句插入到要提交的表单之中,从而让服务器在不知情的情况下执行恶意的sql命令,从而引发一系列的安全隐患。
讲的通俗一点就是说,用户利用sql语法将一些sql语句加在某些字段后面,提交表单的时候,服务器执行sql命令并未达到想要的结果反而引发异常和数据泄露。
这就是典型的系统漏洞,因此sql注入对系统的危害是非常大的,做好防止sql注入也是系统必须完善的。
2.sql注入实例
写了个简单的登录程序,框架是Spring+SpringMVC+Mybatis。如下:
(1)特殊符号,如 ’ 和 .等
可以看到当我输入一个特殊符号,而后台未经过过滤的时候,便会抛出sql异常
并且如果没有进行全局异常处理,用户便可以通过浏览器的开发者模式中获取到数据库和查询语句的相关信息。
而这个对系统来说是很危险的漏洞。
(2)sql语句的注入
当输入正确的账号密码的时候,可以看到执行时成功的。
但是如果加上这么一句sql语句在表单,我们可以看到结果依然可以执行成功
非法用户可以通过这个来测试数据库的表名字、该表的其他字段名、数据的量级等等。
举个例子:尝试获取到该表的其他字段名
只需要将刚才的表单中的“1=1”替换成测试sql语句即可,如果执行成功则代表该表中有这个字段存在。
看一下最后执行的sql语句:
就一目了然了。这通用是因为注入引起的。
类似的还有:‘or’‘=’ 不仅能执行成功,同时还有查询多全部的数据。
(3)通过sql语句的in和order by进行注入
以上的三点主要是因为在mybatis中使用了${}, sql语句没有执行预编译,无法防止sql注入。
3.mybatis框架下如何解决sql注入问题
mybatis框架本身就有防止sql注入的特性,这就要求我们必须在写sql语句时候遵循框架的书写规范。
(1)用#{param}替换所有的${param}
因为${}是拼接sql字符实现没有预编译的查询,因为是无法防御sql注入,而#{}则需要进行预编译,可以很大程度上防止sql注入。
在一些#{}使用时候会报错的地方,如like 查询、in 查询、order by排序等,
a) like:
select * from Users where username like '%${username}%'
替换成:
select * from Users where username like concat('%', #{username}, '%')
b) in
select * from Users where id in (${id})
替换成mybatis框架自带的foreach循环:
c) order by
不要直接使用:拼接排序
如:
select *from Users order by ${id}
而是在Java层面做映射,然后用来做判断
(2)对用户输入的数据进行sql注入校验
SqlServer本身的防sql注入机制,利用存储过程可以避免sql注入。应该禁止用户输入一些关键的特殊符号,如分号、分隔符、单引号等,同时对于一些关键位置进行sql关键字的屏蔽,如or、and等。必须对用户输入的内容的类型、长度、格式、范围进行校验。
(3)要对用户的权限进行区分
普通用户的权限和管理员的权限之间,必须严格区分开来,对管理员实现安全级别更高的验证,从而防止人为获取到更高权限时候的sql注入攻击。
(4)更高级别的验证
在后端代码和数据库中都开启对sql注入的验证,同时用专业的注入工具查找本系统的漏洞进行修复,也可以进行账号诱骗,将一些如“admin”之类的容易受到攻击的用户设置上千位的密码,让攻击者的软件因为解析量大而负载过大,从而耗尽资源而宕机。