如何防止SQL注入

发布于 2024-10-14 18:20:32 字数 907 浏览 4 评论 0原文

我正在使用存储过程。 为了节省时间,我做了一些通用的程序,使用动态sqlin命令来更新。这样的通用过程是:

CREATE PROCEDURE [dbo].[SetField]
 @company_id uniqueidentifier,
 @id bigint,
 @field_code nvarchar(50),
 @value nvarchar(50)
AS
BEGIN
 DECLARE @field_name nvarchar(50)
 SET @field_name = NULL
 SELECT @field_name=field_name
 FROM dbo.FIELD_DEFINITION
 WHERE field_code=@field_code

 IF @field_name IS NOT NULL
 BEGIN

  IF @value IS NULL OR @value=''
  BEGIN
   SET @value='NULL'
  END
  ELSE
  BEGIN
   IF @field_code='START_DATE' OR @field_code='END_DATE'
   BEGIN
    SET @value = CONVERT(datetime, @value ,103)
   END
   SET @value=''''+@value+''''
  END

  DECLARE @sql nvarchar(1000)
  SET @sql = 'UPDATE dbo.TABLE '+
     'SET '+@field_name+'='+@value+' '+
     'WHERE company_id=''' + CAST(@company_id as nvarchar(36)) + ''' AND '+
     'id='+CAST(@id as nvarchar)
  EXEC(@sql)
 END
END

如何使用此代码防止 sql 注入?

I am using stored procedures.
In order to save time, I made some generic procedures that uses dynamic sqlin order to update. Such generic procedure is:

CREATE PROCEDURE [dbo].[SetField]
 @company_id uniqueidentifier,
 @id bigint,
 @field_code nvarchar(50),
 @value nvarchar(50)
AS
BEGIN
 DECLARE @field_name nvarchar(50)
 SET @field_name = NULL
 SELECT @field_name=field_name
 FROM dbo.FIELD_DEFINITION
 WHERE field_code=@field_code

 IF @field_name IS NOT NULL
 BEGIN

  IF @value IS NULL OR @value=''
  BEGIN
   SET @value='NULL'
  END
  ELSE
  BEGIN
   IF @field_code='START_DATE' OR @field_code='END_DATE'
   BEGIN
    SET @value = CONVERT(datetime, @value ,103)
   END
   SET @value=''''+@value+''''
  END

  DECLARE @sql nvarchar(1000)
  SET @sql = 'UPDATE dbo.TABLE '+
     'SET '+@field_name+'='+@value+' '+
     'WHERE company_id=''' + CAST(@company_id as nvarchar(36)) + ''' AND '+
     'id='+CAST(@id as nvarchar)
  EXEC(@sql)
 END
END

How can I prevent sql injection with this code?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

×眷恋的温暖 2024-10-21 18:20:32

你说:

为了节省时间,我制作了一些使用动态sql进行更新的通用程序

如果您先询问,我们可以节省时间并建议这样做...

UPDATE
    dbo.TABLE
SET
    Field1 = CASE WHEN @field_name = 'Field1' THEN @value ELSE Field1 END,
    Field2 = CASE WHEN @field_name = 'Field2' THEN @value ELSE Field2 END,
    Field3 = CASE WHEN @field_name = 'Field3' THEN @value ELSE Field3 END,
    ...
    Fieldn = CASE WHEN @field_name = 'Fieldn' THEN @value ELSE Fieldn END
WHERE
    company_id = @company_id AND id = @id

You said:

In order to save time, I made some generic procedures that uses dynamic sql in order to update

If you'd asked first, we could have saved time and suggested this...

UPDATE
    dbo.TABLE
SET
    Field1 = CASE WHEN @field_name = 'Field1' THEN @value ELSE Field1 END,
    Field2 = CASE WHEN @field_name = 'Field2' THEN @value ELSE Field2 END,
    Field3 = CASE WHEN @field_name = 'Field3' THEN @value ELSE Field3 END,
    ...
    Fieldn = CASE WHEN @field_name = 'Fieldn' THEN @value ELSE Fieldn END
WHERE
    company_id = @company_id AND id = @id
和影子一齐双人舞 2024-10-21 18:20:32

关于 SQL 注入需要记住的一个重要方面是,如果可能的话,您永远不应该将用户提供的值直接嵌入到 SQL 中。这并不意味着您不能使用动态 sql(尽管如果您不使用它肯定会使事情变得更容易),但它有时确实会变得更加危险。

在您的具体示例中,您可以保留除 @field_name 之外的所有内容的参数化。不幸的是,这必须直接嵌入到 SQL 中;其他所有内容都可以再次作为参数传递,因此无需担心它们的内容。

在此特定示例中,您可以执行的最安全的操作如下:

if(exists (select 1 from INFORMATION_SCHEMA.Columns where TABLE_NAME = 'Table' and TABLE_SCHEMA = 'dbo' and COLUMN_NAME = @fieldName))
begin
    DECLARE @sql nvarchar(1000)
    SET @sql = 'UPDATE dbo.TABLE '+
       'SET ' + QUOTENAME(@field_name) + '=@value ' + 
       'WHERE company_id=@company_id AND '+
       'id=@id'

    exec sp_executesql @sql,N'@id bigint, @company_id uniqueidentifier, @value nvarchar(50)',@id,@company_id,@value
end

这会执行两件事:

  1. 它验证表中是否确实存在具有该名称的列。如果用户将任何其他 SQL 语句嵌入到该字段中,则此检查将失败并且该语句将不会被执行。您还可以调用 raiseerror 来报告错误,但我会将这个练习留给您。
  2. 它将字段名称括在方括号中,以便包含空格或保留字的字段名称不会破坏语句。这对您来说可能不是问题,但如果您自己生成 SQL,这始终是一个好习惯。

The important aspect to remember about SQL injection is that means that, if at all possible, you should never embed user-supplied values directly into your SQL. This doesn't mean that you can't use dynamic sql (though it definitely makes things easier if you don't), but it does become more dangerous at times.

In your specific example, you can keep the parameterization of everything except @field_name. This, unfortunately, must be embedded directly into the SQL; everything else can be passed as a parameter again, so there's no need to worry about their content.

The safest thing that you can do in this specific example is the following:

if(exists (select 1 from INFORMATION_SCHEMA.Columns where TABLE_NAME = 'Table' and TABLE_SCHEMA = 'dbo' and COLUMN_NAME = @fieldName))
begin
    DECLARE @sql nvarchar(1000)
    SET @sql = 'UPDATE dbo.TABLE '+
       'SET ' + QUOTENAME(@field_name) + '=@value ' + 
       'WHERE company_id=@company_id AND '+
       'id=@id'

    exec sp_executesql @sql,N'@id bigint, @company_id uniqueidentifier, @value nvarchar(50)',@id,@company_id,@value
end

This does two things:

  1. It verifies that there is actually a column with that name in the table. If the user were to embed any other SQL statements into the field, then this check would fail and the statement would not be executed. You could also call raiseerror to report the error, but I'll leave that exercise up to you.
  2. It encloses the field name in square braces so that field names that contain spaces or reserved words will not break the statement. This may not be an issue for you, but it's always good practice if you're generating the SQL yourself.
疾风者 2024-10-21 18:20:32

在您致电 SP 之前,我会开始寻找防止 sql 注入攻击的方法。请小心从查询字符串或表单数据拼凑而成的动态 SQL 字符串。使用 SqlCommand 对象。

编辑:
作为对评论的回应,这里很好地解释了参数化查询(SqlCommand 查询)如何帮助防止 SQL 注入。

来自 http://forums.asp.net/t/1568268.aspx

.. .占位符 - @Id - 已成为硬编码 SQL 的一部分。在运行时,查询字符串提供的值与硬编码的 SQL 一起传递到数据库,数据库在尝试将参数值绑定到该字段时将检查 ProductID 字段。这确保了强类型的水平。如果参数值不是数据库字段的正确类型(字符串或超出字段类型范围的数字),数据库将无法将其转换为正确的类型,并将拒绝它。如果目标字段数据类型是字符串(char、nvarchar 等),则参数值将自动“字符串化”,其中包括转义单引号。它不会构成要执行的 SQL 语句的一部分。

I would start looking at ways to prevent sql injection attacks before you ever call the SP. Be careful with dynamic SQL strings pieced together from querystring or form data. Use a SqlCommand object.

Edit:
In response to the comment, here is a nice explanation of how parameterized queries (SqlCommand queries) help prevent SQL injection.

From http://forums.asp.net/t/1568268.aspx:

...The placeholder - @Id - has become part of the hardcoded SQL. At runtime, the value provided by the querystring is passed to the database along with the hardcoded SQL, and the database will check the ProductID field as it attempts to bind the parameter value to it. This ensures a level of strong typing. If the parameter value is not the right type for the database field (a string, or numeric that's out of range for the field type), the database will be unable to convert it to the right type and will reject it. If the target field datatype is a string (char, nvarchar etc), the parameter value will be "stringified" automatically, which includes escaping single quotes. It will not form part of the SQL statement to be executed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文