避免使用参数解析器进行SQL注入

时间:2015-12-11 21:51:39

标签: sql-server function stored-procedures sql-injection

我有一个存储过程,它有许多参数(所有varchar),一些参数用在where子句中,其他参数用作表名。我读过许多文章,建议使用引号来表名,转义单引号,%和_以及白名单或黑名单字或字符。

在我的情况下,引号不起作用,因为添加[]会中断我的过程,因为我使用sys.tables,其中name = @tablename来验证从sys.columns获取列。

所以我决定创建一个泛型函数来验证参数以避免SQL注入...这个简单的函数接受@input参数并返回@input变量的修改版本(如果找到不需要的字符)。当找到以下字符(或单词)时,此函数使用replace命令:

' - / * * /%; + [UNION DROP CREATE INSERT SELECT UPDATE UNION

我构建的函数如下所示:

CREATE function [dbo].[AntiSQLInjection] (@input varchar(8000))
Returns varchar(8000)
As
Begin

Return 
    replace(
        replace(
            replace(
                replace(
                    replace(
                        replace(
                            replace(
                                replace(
                                    replace(
                                        replace(
                                            replace(
                                                replace(
                                                    replace(
                                                        replace(
                                                            replace(
                                                                replace(@input,
                                                                '''',''''''),
                                                            'UNION',''),
                                                        '--',''),
                                                    '/*',''),
                                                '*/',''),
                                            'DROP ',''),
                                        'ALTER ',''),
                                    'CREATE ',''),
                                '%','[%]'),
                            '[','[[]'),
                        ';',''),
                    '+',''),
                'SELECT ',''),
            'UPDATE ',''),
        'INSERT ',''),
    'DELETE ','')

End

我无法摆脱动态SQL ...我的问题是“这个函数是否覆盖了所有不同的角度以避免SQL注入?”

以下是一些使用参数的代码示例,我将使用AntiSQLInjection函数解析参数:

SET @SQLStr = ' SELECT c.name, CASE WHEN y.name IS NOT NULL THEN 1 ELSE 0 END AS Set_Columns 
                INTO TMP_Col
                FROM sys.tables t 
                JOIN sys.columns c on c.object_id = t.object_id 
                JOIN (SELECT c.name 
                        FROM sys.tables t 
                        JOIN sys.columns c ON c.object_id = t.object_id 
                        WHERE t.name = ''' + @tar_local + ''') x ON x.name = c.name
                    LEFT JOIN (SELECT c.name 
                        FROM sys.tables t 
                        JOIN sys.columns c ON c.object_id = t.object_id 
                        WHERE t.name = ''' + @tar_local + ''') y ON y.name = c.name and y.name in (''' + CASE WHEN @set_local IS NULL THEN 'No Set Parameter' ELSE REPLACE(@set_local,';',''',''') END + ''')
                WHERE t.name = ''TMP_9999999'''
EXEC (@SQLStr)

SET @SQLStr = 'INSERT INTO TMP_PK_TAB_9999999 (TABLE_QUALIFIER, TABLE_OWNER, TABLE_NAME, COLUMN_NAME,KEY_SEQ, PK_NAME)
                    EXEC sp_pkeys ''' + @tar_local + ''''
EXEC (@SQLStr)

而且更复杂 - > params是@tar_local,@ src_local,@ key_local ......其他变量是SP中构建的字符串,我并不担心。

SET @SQLStr = 'INSERT INTO ' + @tar_local + '(' + @ColumnsStr + ') SELECT S.' + REPLACE(@ColumnsStr,',',',S.') + ' FROM (' + @src_local + ') S LEFT JOIN ' + @tar_local + ' T ON T.' + REPLACE(REPLACE(REPLACE(@key_local,' ',''),'=:','= S.'),'AND',' AND T.') + 
                                    ' WHERE T.' + SUBSTRING(@ColumnsStr,PATINDEX('%F%',@ColumnsStr), CASE WHEN PATINDEX('%,%',@ColumnsStr) = 0 THEN LEN(@ColumnsStr)-PATINDEX('%F%',@ColumnsStr) ELSE PATINDEX('%,%',@ColumnsStr) - PATINDEX('%F%',@ColumnsStr) END) + ' IS NULL'
                    EXEC(@SQLStr)

我知道这不是最干净的方式,如果您有任何其他想法,请随时分享。

提前感谢。

0 个答案:

没有答案