csu*_*azo 5 sql-server stored-procedures sql-server-2012 database-mail
我使用这个系统存储过程 dbo.sp_send_dbmail
从我的数据库发送电子邮件,我想知道这个过程是否可以防止 SQL 注入?
如果你有一些参考,这对我来说是有用的。
提前致谢。
遗憾的是,您可以毫无问题地进行 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 可以利用模拟(ref1,ref2),然后您只需要将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)