SQL注入学习过程:
1.以前学asp时,防止SQL注入,人家和我说过滤select,update,delete等关键字。
2.刚学asp.net时,还是按以前的做法,过滤select,update,delete等关键字。
3.后来发现asp.net可以用Parameter,只要用Parameter参数的SQL语句或存储过程就能防止注入。
4.后来上CSDN多了,发现用Parameter参数的SQL语句或存储过程不是绝对防止注入的,只要动态拼接SQL或存储过程,即使带Parameter参数,还是能注入的。目前我得出防止SQL注入的观点:
1.带Parameter参数的SQL或储存过程不能动态拼接,否则还是能注入。
2.如果动态拼接SQL或储存过程,在传入字符串类型的数据时,用Replace("'","''"),也能防止注入。但是网上说1个单引号替换成2个单引号,不能完全避免注入。
但是我的理解就是单引号就是注入的灵魂,如果SQL语句的WHERE部分是动态拼接,如:错误的写法: cmd.CommandText = "SELECT * FROM 表 WHERE 字段='" + username + "'";
//这里动态拼接SQL,但是没username = username.Replace("'", "''");所以肯定能注入。
正确的写法: cmd.CommandText = "SELECT * FROM 表 WHERE 字段=@username";
cmd.Parameters.Add("@username", username);
//这里是标准的命令参数写法,不是动态拼接的SQL我的写法: username = username.Replace("'", "''");
cmd.CommandText = "SELECT * FROM 表 WHERE 字段='" + username + "'";
//这里动态拼接SQL,但是已经在传入SQL之前就把1个单引号替换成2个单引号,所以我觉得不能注入。网上说用16进制的SQL语句可以绕过单引号和一些类似select,update,delete等关键字进行注入。我想绕过那些关键字,肯定没问题,毕竟都转换成16进制了,然后可以注入了(类似每个varchar类型的字段上都加上<script src="..."></script>或更恶毒的操作),但是我觉得这些注入的前提SQL是动态拼接的,且没把1个单引号替换成2个单引号(我试过确实能注入),既然这样,我是不是只要把1个单引号替换成2个单引号,就能绝对防止字符串类型数据的注入了呢?那些说1个单引号替换成2个单引号,不能完全避免注入的说法,有人能解释说明一下吗?最好有例子。谢谢了。
1.以前学asp时,防止SQL注入,人家和我说过滤select,update,delete等关键字。
2.刚学asp.net时,还是按以前的做法,过滤select,update,delete等关键字。
3.后来发现asp.net可以用Parameter,只要用Parameter参数的SQL语句或存储过程就能防止注入。
4.后来上CSDN多了,发现用Parameter参数的SQL语句或存储过程不是绝对防止注入的,只要动态拼接SQL或存储过程,即使带Parameter参数,还是能注入的。目前我得出防止SQL注入的观点:
1.带Parameter参数的SQL或储存过程不能动态拼接,否则还是能注入。
2.如果动态拼接SQL或储存过程,在传入字符串类型的数据时,用Replace("'","''"),也能防止注入。但是网上说1个单引号替换成2个单引号,不能完全避免注入。
但是我的理解就是单引号就是注入的灵魂,如果SQL语句的WHERE部分是动态拼接,如:错误的写法: cmd.CommandText = "SELECT * FROM 表 WHERE 字段='" + username + "'";
//这里动态拼接SQL,但是没username = username.Replace("'", "''");所以肯定能注入。
正确的写法: cmd.CommandText = "SELECT * FROM 表 WHERE 字段=@username";
cmd.Parameters.Add("@username", username);
//这里是标准的命令参数写法,不是动态拼接的SQL我的写法: username = username.Replace("'", "''");
cmd.CommandText = "SELECT * FROM 表 WHERE 字段='" + username + "'";
//这里动态拼接SQL,但是已经在传入SQL之前就把1个单引号替换成2个单引号,所以我觉得不能注入。网上说用16进制的SQL语句可以绕过单引号和一些类似select,update,delete等关键字进行注入。我想绕过那些关键字,肯定没问题,毕竟都转换成16进制了,然后可以注入了(类似每个varchar类型的字段上都加上<script src="..."></script>或更恶毒的操作),但是我觉得这些注入的前提SQL是动态拼接的,且没把1个单引号替换成2个单引号(我试过确实能注入),既然这样,我是不是只要把1个单引号替换成2个单引号,就能绝对防止字符串类型数据的注入了呢?那些说1个单引号替换成2个单引号,不能完全避免注入的说法,有人能解释说明一下吗?最好有例子。谢谢了。
1.带Parameter参数的SQL或储存过程不能动态拼接,否则还是能注入。
动态拼接就注入?
它就是动态拼接的先DECLARE SQL,然后拼接SQL,需要的字段,表明,WHERE条件,排序方式等等,很灵活,但是是动态拼接的,
最后通过EXEC(SQL)来执行,这样肯定能注入。参考链接
http://www.cnblogs.com/yukaizhao/archive/2007/03/09/pagination_proc_problem.html
文中,代码declare @strsql varchar(8000)
declare @strwhere varchar(1000)
set @strwhere = 'username like ''%jim'' dog%'''
set @strsql = 'select top 20 * from [useraccount] where ' + @strwhere + ' order by id desc'
exec (@strsql)
这里必须对 @strwhere 变量中的写法是错误的。还是那句话,要多读读SQL语法。语法中一个字符常量串中的单引号要变为两个单引号,那么如果单引号中还有一个将作为作为字符串常量的内容其中的单引号因为嵌套的关系自然就需要再将两个单引号分别再改为两个单引号,也就是说要写set @strwhere = 'username like ''%jim'''' dog%'''
这才能说你的 @strwhere 变量中是一个合格的 SQL 语句片段。否则,就只能说是一个胡乱写的字符串,而不是符合SQL语法的。
并非如此。如果不用程序员去手写存储过程,才能说这个部分基本上可以避免漏洞。手写t-sql存储过程跟写c#等代码一样都有这个问题要注意。
declare @strwhere varchar(1000)
set @strsql = 'select top 20 * from [useraccount] where username like ''' + replace(@strlike,'''','''''') + ''' order by id desc'
exec (@strsql)请注意,这才是正确的t-sql编程。如果对T-SQL语法不了解不谨慎,不要过分强求写过多的存储过程,用高级的.net代码来完成程序处理吧,或者开始使用Linq,那样不容易出错。