如何保护带有参数化表名的查询不被注入

时间:2019-05-23 06:46:37

标签: sql-server sql-injection sanitization

寻找一种与同一台服务器上不同表中的数据进行交互的方法,我遇到了this question上提供的解决方案。据我所能找到的,没有其他方法可以将表名“传递”给查询。问题在于它似乎容易受到SQL注入的攻击;例如,我可以使用此代码将某人添加到名为“ School1”的数据库的“学生”表中:

CREATE PROCEDURE AddStudent (
    @DBName char(10), 
    @FirstName char(30), 
    @LastName char(30)
    ) AS
DECLARE @SqlScript varchar(MAX) = '
    INSERT INTO ' + @DBName + '.dbo.student (FirstName, LastName) VALUES (' +
        @FirstName + ', ' + @LastName + ');'
EXECUTE (@SqlScript)

当我将存储过程称为“ AddStudent”时,我只需传递变量“ School1”,“ Bobby”和“ Tables”。您可能会看到前进的方向...

即使数据库名称以某种方式(因此安全)以编程方式确定了客户端,little Bobby Tables could choose to use his full name并使用@FirstName = Robert @LastName = '); DROP TABLE学生;- 导致我们各种各样的问题。

当然,这可能是一个不太可能且极端的示例,但是您可以理解。有什么办法可以防止这种情况?

1 个答案:

答案 0 :(得分:0)

Dale提到每个数据库都必须有一个独立的存储过程,这给了我将其分为两个独立的想法。一个仅计算出要使用的数据库,然后将值传递给另一个数据库,该数据库实际上添加了学生记录。它并不是特别优雅,但是它可以让您在SQL中完成很多工作:

首先,完全按照您的期望添加学生的查询-将其放入每个数据库中:

CREATE Procedure [dbo].[AddStudent] (@FirstName char(10), @LastName char(10)) AS
    INSERT INTO SCHOOL1.dbo.Student (FirstName, LastName) VALUES
        (@FirstName, @LastName);

然后是另一个数据库,该数据库可以存在于master数据库中,也可以存在于每个数据库中,具体取决于将其发送到哪个数据库最方便:

CREATE Procedure [dbo].[AddStudentUniversal] (@DbName char(10), @FirstName char(10), @LastName char(10)) AS
    IF (@DbName = 'SCHOOL1')  EXECUTE SCHOOL1.dbo.AddStudent @FirstName, @LastName
    IF (@DbName = 'SCHOOL2')  EXECUTE SCHOOL2.dbo.AddStudent @FirstName, @LastName