本文不是写SQL注入攻击,除了SQL注入攻击之外,还有一种SQL数据库的漏洞。写本文的目的主要是让开发者在构建网站时,能意思到这个安全问题。这个漏洞并不是太常见,我将为展示这种攻击手法,希望大家能引以为鉴,及时做好相应的防御措施。
在注册新用户时候,开发者可能会按照以下的逻辑来运行。
首先检查用户名密码:
"SELECT *
FROM users
WHERE username='用户名'"
如果用户名在数据库中不存在,执行以下SQL语句
INSERT INTO users(username, password)
VALUES ('用户名','密码')"
以下是验证用户的登录信息:
"SELECT username FROM users
WHERE username='用户名'
AND password='密码' ";
按理说这并不存在安全问题。应该是不会出错了。
但是,事实并不是想的那样。攻击者仍然可以用任意用户的身份登录系统。
在进行攻击之前,首先要说一下几个注意点。
在SQL的执行过程中,字符串末尾的空格会被删除掉。比如,一个字符串“riyudeshui” ,其实等同于“ruyudeshui ” ,大部分的情况下是成立的。比如我们使用如下两个SQL语句进行查询:
SELECT * FROM users WHERE username='ruyudeshui';
SELECT * FROM users WHERE username='ruyudeshui ';
返回的数据是一样的。但是也有特殊情况。这里不做过多讨论。
在所有的insert操作中,SQL都会根据varchar(n)来规定字符串长度,也就是说,当实际的字符串比n大时,会插入前n个字符。比如,我们限定varchar(8).我们在插入“ruyudeshui”的时候,不会将整个字符串插入,而是会截断,只插入前8个字符。实际上插入的字符为“ruyudesh” ,当然,mysql的不同版本之间会有差异,我尝试在mysql 5.5.2是截断的,但是在mysql 5.0 版本下,会提示无法插入的情况。
下面演示一下攻击的步骤:
1.首先建立一张表
CREATE TABLE users (
username varchar(20),
password varchar(20)
);
插入数据:
INSERT INTO users
VALUES('ruyudeshui', 'password1');
为了演示,先查一下
SELECT * FROM users
WHERE username='ruyudeshui ';
结果能够正常返回数据。下面开始攻击:
为了侵入一个用户的账户,获取信息,只需要使用用户名ruyudeshui [很多个空格] a'
和一个任意密码进行注册就可以了。这样的目的是绕过对用户名的检查,因为这个用户
名查询到的结果集为空,数据库中并不存在。
然后执行的是插入过程。
INSERT INTO users(username, password)
VALUES ('ruyudeshui a', 'password');
插入成功,我们重新登录用户,用刚才插入的第二个用户名和密码进行插入,这时执行的SQL语句是这样 的。
SELECT * FROM users
WHERE username='ruyudeshui';
哈哈哈哈,原始的记录被返回了!
这时会返回两条记录,这样的话,攻击者使用任意的用户名再加一堆空格,然后加一个字符串 和任意密码注册登录后。就能返回和本用户名前缀相同的用户的所有记录。这个攻击手法在mysql 5.5.2 下是成功的,据说在sqlite下也使用。感觉在其他情况下也可以用。
我们在进行开发时,一定要注意此类的漏洞,很多时候,开发者在前台进行校验,用户名不能出现空格或者特殊字符。我感觉意义并不大。因为攻击者可以通过POST提交进行注册啊。。不过,如果使用id作为主键,并且通过程序进行跟踪,是可以避免这个问题的。
ok,希望大家能注意到这个问题,在开发过程中防止信息的泄露,毕竟,信息安全是很重要滴。
欢迎转发哦。
微信:liangnote
微博:如鱼得水5838
博客:http://www.cnblogs.com/pangu/