mysql注入式攻击_sql注入攻击及其防止办法

一、sequlize.query防止sql注入

在nodejs中使用sequlize库来查询mysql数据库,提供了常用的方法有两种:

//1、直接查询sql语句

sequelize.query();//需要做sql防注入//2、通过接口

Project.findAll(); //在实现上就做了sql防注入处理,但是必须配合model使用,不灵活

sequelize.query() 原生查询使用replacements 防sql注入

sequelize.query('SELECT * FROM projects WHERE status = ?',

{ replacements: ['active'], type: sequelize.QueryTypes.SELECT }

).then(projects=>{

console.log(projects)

})

sequelize的第2种查询方法在实现上做了防注入处理, 但该方法使用并不是很灵活, 对于经常使用原生sql语句的人来说, 总有一种不适应, 感觉手脚被束缚; 而对于使用方法1, 则必须注意防sql注入;

1、产生原因

下面的查询语句, 加入了用户输入的时间项: begin, end, 正常情况是:

begin = 20161101;

SELECT .. FROM tbl WHERE pdate>=20161101 AND ...;

而如果有人故意输入如下的参数, 则就会出现sql注入:

begin = '20161101 AND 1=1; -- hack';

SELECT .. FROM tbl WHERE pdate>=20161101 AND 1=1; -- hack ...;

2、解决办法

解决上面的办法, 通常有两种:

(1)对输入的参数进行转义, 因为sql注入通常需要'符号来闭合前面的', 这样如果位面在输入的参数中的'全部转义为\', 则查询时就不会出现中断(执行两条sql语句), 参看下面的例子;

(2)设置mysql只能一次执行一条sql语句;

3、测试

sequelize.query()与Project.findAll()对比,先看代码

var tblName = 'tbl_test', begin = '20160923 AND 1=1;-- hack', end = 20160928;var sqlQuery = `SELECT * FROM ${tblName} WHERE pdate>=${begin} AND pdate<=${end} GROUP BY pdate`;

Promise.resolve([//第一条查询

sequelize.query(sqlQuery),//第一二条查询

Project.findAll({

attributes: { exclude:['id'] },where: {

pdate: {

$and:{//参数中加上了'来闭合前面的', 后面的1=1为注入语句

$gte: "20160923' AND 1=1;-- hack",

$lte: end

}

}

}

})

]).spread(function(sql1, sql2){

})

(1)上面第一个为sequelize.query()执行, 最终执行的查询语句为:

select * from tbl_test where padte>=20160923 and 1=1;-- hack and pdate<=....;

结果出现注入, pdate<=..这一块的条件没有被执行;

(2)上面第二个查询为Project.findAll()执行, 最终执行的语句为:

select * from tbl_test where pdate>'20160923\' AND 1=1;-- hack' AND pdate<='...'.....;

显然,这里参数里的20160923'引号没有起作用, 被转换为了`20160923\”,所以有效避免了注入, 制查询了符合要求的数据或空数据;

4、sequelize.query() + 参数绑定

下面通过sequelize.query()接口提供的参数绑定和查询方法指定来防止sql注入的发生。

下面的查询语句解析为:

select * from tbl_test where padte>='20160923 and 1=1;-- hack' and pdate<=....;

字符串被直接替换,没有被注入;

注意,这里的表名table不能通过bind的参数传进去, 因为这样在语句里会表达为字符串: …. from ‘tbl_test’ where …, 这样是错误的语句,所以上面用字符串模板传入,也可以硬编码进去;

var tblName = 'tbl_test', begin = '20160923 AND 1=1;-- hack', end = 20160928;var sqlQuery = `SELECT * FROM ${tblName} WHERE pdate>=$begin AND pdate<=$end GROUP BY pdate`;

Promise.resolve([

sequelize.query(sqlQuery,

type: ymModel.sequelize.QueryTypes.SELECT,//指定sql为SELECT

bind: {

begin: begin,

end: end

}

),

]).spread(function(sql1){

})

二、浅析sql攻击

SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库。

1、适用范围:

(1)如果一个系统是通过

SELECT * FROM accounts WHERE username='admin' and password = 'password'

这种显式的SQL来进行登陆校验,也就是执行这个SQL语句,如果数据库中存在用户名为admin, password为password的用户,就登陆成功,否则就登陆失败。

(2)系统没有对用户输入进行全面的过滤

(3)系统后台使用的是MYSQL数据库

2、攻击原理:

利用MYSQL的注释功能,也就是"/*",mysql执行SQL脚本时,如果遇到  /*  标示符,就会把之以后的SQL当做注释而不会执行,

正常情况下用户在用户名框内输入"admin",在password框内输入"password",后台执行的SQL语句就为:SELECT * FROM accounts WHERE username='admin' and password = 'password';

但是如果在用户名框内输入"admin' AND 1=1 /*", 在密码框内输入任意字符串,那么后台执行的SQL就为:SELECT * FROM accounts WHERE username='admin' AND 1=1 /* and password = 'aa',

可以看到数据库实际执行的SQL为:SELECT * FROM accounts WHERE username='admin' AND 1=1, 而 /* 后面的SQL就被当做注释而忽略掉了,登陆成功!

这就是sql注入攻击。

3、sql注入攻击的总体思路

(1)寻找到SQL注入的位置

(2)判断服务器类型和后台数据库类型

(3)针对不同的服务器和数据库特点进行SQL注入攻击

4、sql注入攻击实例

比如在一个登录界面,要求输入用户名和密码:

可以这样输入实现免帐号登录:

用户名: ‘ or 1 = 1 –

密 码:

点登陆,如若没有做特殊处理,那么这个非法用户就很得意的登陆进去了。(当然现在的有些语言的数据库API已经处理了这些问题)

这是为什么呢? 下面我们分析一下:

从理论上说,后台认证程序中会有如下的SQL语句:

String sql = "select * from user_table where username='" + userName + "' and password='" + password + "'";

当输入了上面的用户名和密码,上面的SQL语句变成:

SELECT * FROM user_table WHERE username=

'’or 1 = 1 -- and password='’

分析SQL语句:

条件后面 username='' or 1=1 用户名等于 '' 或 1=1 那么这个条件一定会成功;

然后后面加两个-,这意味着注释,它将后面的语句注释,让他们不起作用,这样语句永远都能正确执行,用户轻易骗过系统,获取合法身份。这还是比较温柔的,如果是执行

SELECT *FROM user_table WHERE

username='' ;DROP DATABASE (DB Name) --'and password=''

其后果可想而知。

5、应对方法

(1)采用预编译语句集,它内置了处理SQL注入的能力,只要使用它的setXXX方法传值即可。

一般ORM框架都有提供,直接调用其内部方法即可。sql注入只对sql语句的准备(编译)过程有破坏作用,而比如PreparedStatement已经准备好了,执行阶段只是把输入串作为数据处理,而不再对sql语句进行解析准备,因此也就避免了sql注入问题。

(2)使用正则表达式过滤传入的参数或者比如具体的字符串过滤等

(3)进行参数转码解码等

总的说来,防范一般的SQL注入只要在代码规范上下点功夫就可以了。凡涉及到执行的SQL中有变量时,可以使用数据持久层提供的内置方法即可,切记不要用拼接字符串的方法;或者对所传参数进行过滤或转换处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值