日期:2014-05-17  浏览次数:20385 次

如何防止SQL注入?(存储过程,参数化都用到了!)
发现存储过程中如果是用到了SQL拼接的话那即使前台使用param参数化的话也会造成SQL注入的!
下面是我存储过程的内容:
SQL code

-- =============================================
-- Author: 牛腩
-- Create date: 2008-11-17 14:38
-- Description: 添加类别,测试存储过程是否有SQL注入危险
-- =============================================
ALTER PROCEDURE [dbo].[category_insert]
@name varchar(100)
AS
BEGIN
declare @sql varchar(1000)
set @sql = 'insert into category(name) values('''+@name+''')'
exec (@sql)
END


下面是前台ASPX页面的代码片段:
C# code

string connStr = @"server=niunan\sqlexpress; database=newssystem; uid=sa; pwd=123456";
SqlConnection conn = new SqlConnection(connStr);
conn.Open();
SqlCommand cmd = new SqlCommand("category_insert", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add(new SqlParameter("@name", "bbb');delete category where id=14--"));
int i = cmd.ExecuteNonQuery();
conn.Close();
Response.Write(i);


其中id为14的记录在数据表里是存在的,输出的结果是2,我再查询一下数据库,发现原来id为14的记录没有了,请问我们应该怎么防止这样的SQL注入呢?因为在很多地方用到分页,而分页我都是写在一个分页存储过程里的,而这个分页存储过程又是用SQL拼接而成的,这样子就会有SQL注入的危险了!!!请问应该怎么解决?

------解决方案--------------------
过滤危险字符吧
------解决方案--------------------
过滤危险字符,使用参数化SQL语句
------解决方案--------------------
过滤危险字符
------解决方案--------------------
exec 可以改用 sp_executesql 

------解决方案--------------------
你这样直接执行动态的sql当然能inject了.不是说用了存储过程就能避免inject,关键看你的参数是怎么样执行的.

用:sp_executesql(你去看sql的帮助),来实现对动态sql的参数支持.
------解决方案--------------------
对变量做有效字符验证
SqlServer中,单引号是字符串开始/结束字符,如果攻击者恶意构造含有单引号的字符串,就可以执行任意Sql语句。
如果是字符串变量,将传入变量中的' (单引号)替换成''(两个单引号)。
两个单引号,是SqlServer中单个单引号的表示方式~ 不会造成Sql语句的字符串的结束,也就不会被执行其他Sql语句了。

------解决方案--------------------
引用楼主 niunan 的帖子:
set @sql = 'insert into category(name) values('''+@name+''')'

------解决方案--------------------
探讨
你这程形式没必要拼啊

ALTER PROCEDURE [dbo].[category_insert]
@name varchar(100)
AS
into category(name) values(@name)

拼字符的话,在前台直接运行sql是一样的效率的啊

------解决方案--------------------
探讨
exec 可以改用 sp_executesql

------解决方案--------------------
C# code
 if (this.txtUserCode.Text.Contains("'") || this.txtUserCode.Text.Contains("--"))
        {
            Alert("登陆失败: " + "你的输入含有非法字符,请重新输入");
            return;
        }

------解决方案--------------------
C# code
 if (this.txtUserCode.Text.Contains("'") || this.txtUserCode.Text.Contains("--"))
        {
            Alert("登陆失败: " + "你的输入含有非法字符,请重新输入");
            return;
        }

------解决方案--------------------

ALTER PROCEDURE [dbo].[category_insert]
@name varchar(100)
AS
BEGIN
declare @sql varchar(1000)
insert into category(name) values(@name);