我会SQL注入的一点困惑

minhua1983 2009-02-23 10:49:15
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个单引号,不能完全避免注入的说法,有人能解释说明一下吗?最好有例子。谢谢了。
...全文
469 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
readfuture 2009-02-24
  • 打赏
  • 举报
回复
sp1234强啊,把能说的都说了,我没得说了...
stonehy520 2009-02-24
  • 打赏
  • 举报
回复
学习一下
Terry717 2009-02-24
  • 打赏
  • 举报
回复
sp1234 太强了,帮他顶!!!
金大哈 2009-02-24
  • 打赏
  • 举报
回复
学习
amandag 2009-02-24
  • 打赏
  • 举报
回复
简单地说,如果接受的参数还要在存储过程中拼接字符串,就仍然需要过滤
别样苍茫 2009-02-24
  • 打赏
  • 举报
回复
sp1234
超级偶像
  • 打赏
  • 举报
回复
正常地来说,假设我们要在t-sql存储过程中拼字符串,我们可以写
declare @strsql varchar(8000)
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,那样不容易出错。
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 hubofly 的回复:]
其实现在微软推行的ORM框架里面的linq entity 都可以避免写sql语句了,这样的话,被注入的几率又降低了
[/Quote]

并非如此。如果不用程序员去手写存储过程,才能说这个部分基本上可以避免漏洞。手写t-sql存储过程跟写c#等代码一样都有这个问题要注意。
  • 打赏
  • 举报
回复
[Quote=引用楼主 minhua1983 的帖子:]
那些说1个单引号替换成2个单引号,不能完全避免注入的说法,有人能解释说明一下吗?最好有例子。谢谢了。[/Quote]

我只能解释出“1个单引号替换为2个单引号”是正确的逻辑,如果发现问题那么一定可以看出编程逻辑错误问题,而不是这个规则的问题。
  • 打赏
  • 举报
回复
这里必须对 @strwhere 变量中的写法是错误的 --> 这里必须很快意识到 @strwhere 变量中的写法是错误的

仔细看一下

'username like ''%jim'' dog%'''

既然待匹配的字符串的开头和结尾是两个单引号,那么中间的引号难道还能再写为两个单引号么?实际上比较仔细认真的人一眼就能看出这个问题。
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 minhua1983 的回复:]
就拿网上通用的分页存储过程来说
它就是动态拼接的

先DECLARE SQL,然后拼接SQL,需要的字段,表明,WHERE条件,排序方式等等,很灵活,但是是动态拼接的,
最后通过EXEC(SQL)来执行,这样肯定能注入。

参考链接
http://www.cnblogs.com/yukaizhao/archive/2007/03/09/pagination_proc_problem.html
[/Quote]

文中,代码
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语法的。
hubofly 2009-02-23
  • 打赏
  • 举报
回复
其实现在微软推行的ORM框架里面的linq entity 都可以避免写sql语句了,这样的话,被注入的几率又降低了

只是效率上可能也会低一些
wdx2008 2009-02-23
  • 打赏
  • 举报
回复
我一般都是伪静态,不使用ID=?这样的链接,另外也是主要过滤单引号和or ,and等SQL注入的关键字,没有出现过问题
minhua1983 2009-02-23
  • 打赏
  • 举报
回复
就拿网上通用的分页存储过程来说
它就是动态拼接的

先DECLARE SQL,然后拼接SQL,需要的字段,表明,WHERE条件,排序方式等等,很灵活,但是是动态拼接的,
最后通过EXEC(SQL)来执行,这样肯定能注入。

参考链接
http://www.cnblogs.com/yukaizhao/archive/2007/03/09/pagination_proc_problem.html
chenyijiu 2009-02-23
  • 打赏
  • 举报
回复
mark,
1.带Parameter参数的SQL或储存过程不能动态拼接,否则还是能注入。
动态拼接就注入?

62,025

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧