我会SQL注入的一点困惑
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个单引号,不能完全避免注入的说法,有人能解释说明一下吗?最好有例子。谢谢了。