数据库注入是比较常见的一种攻击手段,与XSS类似,感兴趣可以去查看我的XSS攻击总结都是从客户端界面输入代码,抓住系统的存在的数据库注入的漏洞,由前台未进行检测过滤直接传送到服务端后台,以此来达到攻击者目的的一种手段。
举个最简单的例子,基础的登录界面,一个账号密码输入表单,一个登录激活按钮,前台传输用户输入的内容到了后台,后台根据数据内容进行SQL语句查询,如果可以查询到,则成功登录,如果失败,则提示错误。
在这里,前台的账号密码对应的变量名分别是name和pwd,数据库对应账号密码字段是username和password数据库查询语句为
select * from users where username='$name' and password='$pwd'
示例测试一下,账号为admin,密码为123,查询语句为:
select * from users where username='admin' and password='123'
当执行语句查找到数据,则为true,反之false,怎么样,是不是感觉很正常,好像并没有什么问题。
那么接下来输入进行这样一步操作,在账号一栏中输入:’ or 1=1#,注意,一定要有最前面的单引号,具体原因后面解释,密码可以随便输,但是不要空着,因为系统可能会有检测是否为空的判断语句。接下里点击登录,神奇的事情发生了,居然登录成功了,但这是为什么呢?回到SQL语句,发现执行的语句是这样的:
select * from users where username='' or 1=1#' and password='abaaba'
其中的**#**在SQL语句中是注释字符,在此之后的语句会被注释掉,那么上面的SQL语句就等价于
select * from users where username='' or 1=1
好了,现在可以看到之前所加的单引号的作用了,如果不加的话,SQl语句就会因为语法错误而报错。现在解释一下这条SQL语句,1=1恒为真,配合上or或连接符,无论or之前是什么,都视为真,因此该条SQL就为真,可以登陆成功,当然or也可以换位**–,但是注意–要有空格,效果是一样的,这就是一个简单的SQL注入示例。
数据库注入分为两种,上述的为数字型注入**,由于username不确定,因此无法确定登录的是哪一个用户,在一些需要获取用户数据的地方可能会报错,那么可以进行字符型注入,这种方法需要事先猜测或者获取到用户的username,常被用来进行攻击后台登录,一般后台管理员的账号为admin或者root,以admin为例,那么可以在账号一栏输入内容:admin’ and 1 = 1 #,所执行的SQL语句如下:
select * from users where username='admin' or 1=1#' and password='abaaba'
相当于:
select * from users where username='admin' or 1=1
对于没有防止数据库注入的系统,一旦被猜对了username,那么数据库注入就显得轻而易举了。
当然,这些只是简单的数据库注入的例子,如果说在前台输入内容中包含对数据库操作的一些语句,那么后果可能是很严重的,比如:
为了防止这些事件的发生,有几种预防手段:
- 过滤参数中的(’ ” \尖括号&*;)等特殊字符;以及NULL、回车符、换行符等扩展字符。可以通过转义字符,但不建议严格筛选,毕竟要保证用户的个性化,
- 对于数字,在将其传入SQL语句之前将其从字符串(String)转换成数字(Number);或者用isnumeric函数确定是否为数字。
- 严格限制变量类型,比如整型变量就采用intval()函数过滤,数据库中的存储字段必须对应为int型。
- 数据长度应该严格规定,能在一定程度上防止比较长的SQL注入语句无法正确执行。
- 网站每个数据层的编码统一,建议全部使用UTF-8编码,上下层编码不一致有可能导致一些过滤模型被绕过。
- 严格限制网站用户的数据库的操作权限,给此用户提供仅仅能够满足其工作的权限,从而最大限度的减少注入攻击对数据库的危害。
- 避免网站显示SQL错误信息,比如类型错误、字段不匹配等,防止攻击者利用这些错误信息进行一些判断。
- 在网站发布之前建议使用一些专业的SQL注入检测工具进行检测,及时修补这些SQL注入漏洞。
如果想深入理解的话,可以看一下这位大佬的博客数据库注入的深入理解