搜索

首页  >  问答  >  正文

保护这个函数免受SQL注入的方法是什么?

rree

P粉573943755P粉573943755389 天前751

全部回复(2)我来回复

  • P粉434996845

    P粉4349968452023-11-08 20:39:55

    据我所知,不能使用参数化查询来执行DDL语句/指定表名,至少在Oracle或Sql Server中不能。如果我必须有一个疯狂的 TruncateTable 函数,并且必须能够避免 SQL 注入,那么我会做的就是创建一个存储过程来检查输入是否是可以安全截断的表。

    -- Sql Server specific!
    CREATE TABLE TruncableTables (TableName varchar(50))
    Insert into TruncableTables values ('MyTable')
    
    go
    
    CREATE PROCEDURE MyTrunc @tableName varchar(50)
    AS
    BEGIN
    
    declare @IsValidTable int
    declare @SqlString nvarchar(50)
    select @IsValidTable = Count(*) from TruncableTables where TableName = @tableName
    
    if @IsValidTable > 0
    begin
     select @SqlString = 'truncate table ' + @tableName
     EXECUTE sp_executesql @SqlString
    end
    END

    回复
    0
  • P粉738346380

    P粉7383463802023-11-08 09:41:58

    对抗 SQL 注入的最常见建议是使用 SQL 查询参数(该线程上的几个人都建议这样做)。

    在这种情况下这是错误的答案。您不能在 DDL 语句中对表名使用 SQL 查询参数。

    SQL 查询参数只能用于代替 SQL 表达式中的文字值。这是每个 SQL 实现的标准。

    当您有表名时,我建议防止 SQL 注入是根据已知表名列表验证输入字符串。

    You can get a list of valid table names from the INFORMATION_SCHEMA:

    SELECT table_name 
    FROM INFORMATION_SCHEMA.Tables 
    WHERE table_type = 'BASE TABLE'
      AND table_name = @tableName

    现在您可以将输入变量作为 SQL 参数传递给此查询。如果查询未返回任何行,则您知道输入无效,无法用作表。如果查询返回一行,则它匹配,因此您可以更放心地使用它。

    您还可以根据您定义为可以让应用程序截断的特定表列表来验证表名称,如 @John Buchanan 建议

    Even after validating that tableName exists as a table name in your RDBMS, I would also suggest delimiting the table name, just in case you use table names with spaces or special characters. In Microsoft SQL Server, the default identifier delimiters are square brackets:

    string sqlStatement = string.Format("TRUNCATE TABLE [{0}]", tableName);

    Now you're only at risk for SQL injection if tableName matches a real table, and you actually use square brackets in the names of your tables!

    回复
    0
  • 取消回复