我想知道SQL Server 2012 是否保护msdb.dbo.sp_send_dbmail 参数?

csu*_*azo 5 sql-server stored-procedures sql-server-2012 database-mail

我使用这个系统存储过程 dbo.sp_send_dbmail从我的数据库发送电子邮件,我想知道这个过程是否可以防止 SQL 注入?

如果你有一些参考,这对我来说是有用的。

提前致谢。

Joh*_*ner 5

遗憾的是,您可以毫无问题地进行 SQL 注入。这是我刚刚使用提升帐户运行的一个简单测试,结果包括:

USE [master]
GO

DECLARE @msgbody NVARCHAR(4000)
SET @msgbody = N'Test to see if this SP can suffer from SQL Injection' + CHAR(13) + CHAR(10) + CHAR(13) + CHAR(10)

EXEC msdb.dbo.sp_send_dbmail @profile_name='MyDBMailProfile'
    , @recipients = 'john.eisbrener@Contoso.com'
    , @reply_to = 'john.eisbrener@Contoso.com'
    , @subject = 'SQL Injection Test'
    , @query = 'CREATE TABLE MyDB.dbo.johnSITest
(
      ID INT IDENTITY(1,1)
    , VAL VARCHAR(50)
)

INSERT INTO MyDB.dbo.johnSITest
    (VAL)
VALUES
    (''yes''), (''you''), (''can'')'
    , @body = @msgbody
GO


Mail (Id: 36756) queued.



SELECT *
FROM MyDB.dbo.johnSITest
GO


ID          VAL
----------- --------------------------------------------------
1           yes
2           you
3           can

(3 row(s) affected)




DROP TABLE MyDB.dbo.johnSITest
GO
Run Code Online (Sandbox Code Playgroud)

现在,如果执行它的帐户没有提升的权限,这应该会限制 SP 的曝光。帐户执行此 SP 所需的最低权限如下:

权限

sp_send_dbmail 的执行权限默认授予msdb数据库中DatabaseMailUser数据库角色的所有成员。但是,当发送消息的用户没有使用该请求的配置文件的权限时,sp_send_dbmail将返回错误并且不发送消息。

最小权限原则应该总是决定你的安全方法,但同样,是的,它可以是SQL注入就像任何摄取动态SQL。

编辑:为了回应您在评论中的后续问题,您可以通过将调用包装到sp_send_dbmail另一个存储过程中来进一步锁定,其中@query参数是静态定义的或更严格控制的。然后,这个新的 SP 可以利用模拟(ref1ref2),然后您只需要将EXECUTE权限授予要向其公开此功能的显式用户。这应该可以很好地锁定事物,并且根据您如何限制@query传递给的参数的使用sp_send_dbmail,您可能能够完全消除正常帐户中发生 SQL 注入的可能性。同样,任何可以直接调用的提升帐户sp_send_dbmail 仍然有能力勒索 SQL 注入的潜力,但这种方法将尽可能地将其锁定。

因为我匆忙输入了这个,这里还有一个例子,希望它能更好地展示这种方法:

-- CREATE THIS PROCEDURE USING AN ACCOUNT THAT HAS SUFFICIENT ACCESS TO THE DATA AND SP_SEND_DBMAIL
CREATE PROCEDURE [dbo].[limited_sp_send_dbmail]
      @messageBody NVARCHAR(MAX)
    , @recipientList VARCHAR(MAX)
    , @reply_to_address VARCHAR(MAX)
    , @subject_line NVARCHAR(255)
WITH EXECUTE AS SELF
AS
    -- does not allow the usage of @query parameter
    EXEC msdb.dbo.sp_send_dbmail @profile_name='MyDBMailProfile'
        , @recipients = @recipientList
        , @reply_to = @reply_to_address
        , @subject = @subject_line
        , @body = @messageBody
GO

EXECUTE [limited_sp_send_dbmail] @messageBody = N'Hello World!', @recipientList = 'john.eisbrener@Contoso.com', @reply_to_address = 'john.eisbrener@Contoso.com', @subject_line = N'Hello World!'
GO

Mail (Id: 36757) queued.
Run Code Online (Sandbox Code Playgroud)