将变量传递给 Openquery 和 SQL 注入
Passing variables into Openquery and SQL Injection
我有两个数据库(A 和 B),都是 SQL 服务器,在不同的服务器上。这些数据库与链接服务器相连。
我必须能够使用数据库 A 上的存储过程将具有不同值的行插入到数据库 B 中的 table 中。此存储过程使用 OPENQUERY
来执行 INSERT
语句到数据库 B.
我知道 OPENQUERY
not accept variables for its arguments. OPENQUERY
has specific syntax 如何插入链接数据库:
INSERT OPENQUERY (OracleSvr, 'SELECT name FROM joe.titles')
VALUES ('NewTitle');
尽管如此,MS documentation 展示了一种将变量传递到链接服务器查询的方法,如下所示:
DECLARE @TSQL varchar(8000), @VAR char(2)
SELECT @VAR = 'CA'
SELECT @TSQL = 'SELECT * FROM OPENQUERY(MyLinkedServer,''SELECT * FROM pubs.dbo.authors WHERE state = ''''' + @VAR + ''''''')'
EXEC (@TSQL)
这就是问题所在。假设数据库 B 中的 table 有两列,ID
(int
) 和 VALUE
(nvarchar(max)
)
因此,对于能够将不同值插入数据库 B 中的 table 的存储过程,我的过程如下所示:
CREATE PROCEDURE openquery_insert
@var1 int,
@var2 nvarchar(max)
AS
BEGIN
SET NOCOUNT ON;
BEGIN
DECLARE @SQL_string nvarchar(max)
SET @SQL_string = 'insert openquery(LINKEDSERVER, ''SELECT ID, VALUE from TABLE'') VALUES ('
+ CAST(@var1 AS NVARCHAR(5)) + ', '
+ '''' + CAST(@var2 AS NVARCHAR(max)) + ''''
+ ')'
EXEC sp_executesql @SQL_string
END
END
程序可以调用为
EXEC openquery_insert @var1 = 1, @var2 = 'asdf'
但是如果 @var2
是 ' DROP TABLE B--
,那么 SQL 注入攻击就会成功。
有没有办法防止 SQL 注入 OPENQUERY
?
- 调用过程时,我无法控制参数
@var1
和 @var2
的值
- 我无法在数据库 B 上创建函数或存储过程
- 我必须使用 OPENQUERY,我不能使用 four part naming 来执行插入
- 我必须在数据库 A 上使用存储过程
谢谢!
“hacky”方法是先将您的参数插入本地 table,然后使用 OPENQUERY
.
执行 INSERT INTO ... SELECT
如果你的 SP 曾经被一个进程以同步方式调用,这一切都很简单:你可以有一个 table,你可以在其中插入值,然后执行 OPENQUERY
来获取它们,然后你从 table.
中删除这些值
如果并发是一项要求,那么您必须编写逻辑来创建唯一命名的 tables 等,这很快就会变得有些混乱。
我有两个数据库(A 和 B),都是 SQL 服务器,在不同的服务器上。这些数据库与链接服务器相连。
我必须能够使用数据库 A 上的存储过程将具有不同值的行插入到数据库 B 中的 table 中。此存储过程使用 OPENQUERY
来执行 INSERT
语句到数据库 B.
我知道 OPENQUERY
not accept variables for its arguments. OPENQUERY
has specific syntax 如何插入链接数据库:
INSERT OPENQUERY (OracleSvr, 'SELECT name FROM joe.titles')
VALUES ('NewTitle');
尽管如此,MS documentation 展示了一种将变量传递到链接服务器查询的方法,如下所示:
DECLARE @TSQL varchar(8000), @VAR char(2)
SELECT @VAR = 'CA'
SELECT @TSQL = 'SELECT * FROM OPENQUERY(MyLinkedServer,''SELECT * FROM pubs.dbo.authors WHERE state = ''''' + @VAR + ''''''')'
EXEC (@TSQL)
这就是问题所在。假设数据库 B 中的 table 有两列,ID
(int
) 和 VALUE
(nvarchar(max)
)
因此,对于能够将不同值插入数据库 B 中的 table 的存储过程,我的过程如下所示:
CREATE PROCEDURE openquery_insert
@var1 int,
@var2 nvarchar(max)
AS
BEGIN
SET NOCOUNT ON;
BEGIN
DECLARE @SQL_string nvarchar(max)
SET @SQL_string = 'insert openquery(LINKEDSERVER, ''SELECT ID, VALUE from TABLE'') VALUES ('
+ CAST(@var1 AS NVARCHAR(5)) + ', '
+ '''' + CAST(@var2 AS NVARCHAR(max)) + ''''
+ ')'
EXEC sp_executesql @SQL_string
END
END
程序可以调用为
EXEC openquery_insert @var1 = 1, @var2 = 'asdf'
但是如果 @var2
是 ' DROP TABLE B--
,那么 SQL 注入攻击就会成功。
有没有办法防止 SQL 注入 OPENQUERY
?
- 调用过程时,我无法控制参数
@var1
和@var2
的值 - 我无法在数据库 B 上创建函数或存储过程
- 我必须使用 OPENQUERY,我不能使用 four part naming 来执行插入
- 我必须在数据库 A 上使用存储过程
谢谢!
“hacky”方法是先将您的参数插入本地 table,然后使用 OPENQUERY
.
INSERT INTO ... SELECT
如果你的 SP 曾经被一个进程以同步方式调用,这一切都很简单:你可以有一个 table,你可以在其中插入值,然后执行 OPENQUERY
来获取它们,然后你从 table.
如果并发是一项要求,那么您必须编写逻辑来创建唯一命名的 tables 等,这很快就会变得有些混乱。