SQL Server - 动态PIVOT表 - SQL注入

Rob*_*Day 17 sql-server pivot sql-injection sql-server-2005 dynamic-pivot

很抱歉这个问题很长,但是这里包含了我用来测试场景的所有SQL,希望能够清楚地说明我在做什么.

我在SQL Server 2005中构建了一些动态SQL来生成PIVOT表.

下面是执行此操作的代码.使用各种选择显示原始数据使用GROUP BY的值和PIVOT中的值,我想要它们.

BEGIN TRAN
--Create the table
CREATE TABLE #PivotTest
(
    ColumnA nvarchar(500),
    ColumnB nvarchar(500),
    ColumnC int
)

--Populate the data
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('A', 'X', 1)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('A', 'Y', 2)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('A', 'Z', 3)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('A', 'X', 4)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('A', 'Y', 5)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('B', 'Z', 6)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('B', 'X', 7)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('B', 'Y', 8)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('B', 'Z', 9)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('C', 'X', 10)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('C', 'Y', 11)
INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('C', 'Z', 12)

--The data
SELECT * FROM #PivotTest

--Group BY
SELECT
    ColumnA,
    ColumnB,
    SUM(ColumnC)
FROM
    #PivotTest
GROUP BY
    ColumnA,
    ColumnB

--Manual PIVOT
SELECT
    *
FROM
    (
        SELECT
            ColumnA,
            ColumnB,
            ColumnC
        FROM
            #PivotTest
    ) DATA
    PIVOT
    (
        SUM(DATA.ColumnC)
    FOR
        ColumnB
        IN
        (
            [X],[Y],[Z]
        )
    ) PVT

--Dynamic PIVOT
DECLARE @columns nvarchar(max)

SELECT
    @columns = 
    STUFF
    (
        (
            SELECT DISTINCT
                ', [' + ColumnB + ']'
            FROM
                #PivotTest
            FOR XML PATH('')
        ), 1, 1, ''
    )

EXEC
('
    SELECT
        *
    FROM
        (
            SELECT
                ColumnA,
                ColumnB,
                ColumnC
            FROM
                #PivotTest
        ) DATA
        PIVOT
        (
            SUM(DATA.ColumnC)
        FOR
            ColumnB
            IN
            (
                ' + @columns + '
            )
        ) PVT
')

--The data again
SELECT * FROM #PivotTest

ROLLBACK
Run Code Online (Sandbox Code Playgroud)

无论什么时候我生成任何动态SQL,我总是知道SQL注入攻击.因此,我在其他INSERT语句中添加了以下行.

INSERT INTO #PivotTest (ColumnA, ColumnB, ColumnC) VALUES('A', 'FOO])) PVT; DROP TABLE #PivotTest;SELECT ((GETDATE()--', 1)
Run Code Online (Sandbox Code Playgroud)

当我现在运行SQL时,低,请注意,EXEC部分删除#PivotTest表,从而使最后一个SELECT失败.

所以我的问题是,有没有人知道在没有SQL注入攻击风险的情况下执行动态PIVOT的方法?

Phi*_*ley 16

我们做了很多类似于你的例子的工作.我们并不担心SQL的损害,部分原因是我们对所转移的数据有完全和完全的控制 - 恶意代码无法通过ETL进入我们的数据仓库.

一些想法和建议:

  • 您需要使用nvarcahr(500)色列进行旋转吗?我们是varchar(25)或数字,并且很难通过那里偷偷破坏代码.
  • 数据检查怎么样?看起来如果其中一个字符串包含"]"字符,那么无论是黑客攻击还是数据都将会爆炸.
  • 您的安全性有多强大?系统是否被锁定,以至于Malorey不能将他的黑客潜入您的数据库(直接或通过您的应用程序)?

哈.编写了所有这些来记住函数QUOTENAME().快速测试似乎表明将其添加到您的代码中会起作用(您将收到错误,而不是丢弃的临时表):

SELECT
        @columns = 
        STUFF
        (
                (
                        SELECT DISTINCT
                                ', [' + quotename(ColumnB, ']') + ']'
                        FROM
                                #PivotTest
                        FOR XML PATH('')
                ), 1, 1, ''
        )
Run Code Online (Sandbox Code Playgroud)

这应该适用于pivot(和unpivot)情况,因为你几乎总是必须[括]你的值.