如果我的用户只有权限有限 - 只有db_datareader和db_datawriter,它应该只允许用户查询数据并插入/编辑/删除数据,而不允许用户在数据库中添加/修改/删除表。
可能需要用户能够执行存储过程。如果给予用户执行权限(通过以下sql:“GRANT EXECUTE TO UserName”),是否仍会对用户尝试通过存储过程执行的操作强制执行先前的限制(datareader和datawriter)?或者执行权限真的打开了潘多拉的其他安全漏洞(如果是这样的话)?
答案 0 :(得分:4)
如果存储过程的所有者有权对表进行选择,插入,更新或删除,则只要调用者对存储的执行权限,就会执行存储过程内的选择,插入,更新和删除语句。过程,即使调用者没有权利直接对表执行选择,插入,更新或删除。
但是,除非调用者有权执行DDL,即使存储过程的所有者具有DDL权限,否则存储过程无法执行DDL。请注意,这也适用于截断表。
答案:在您的情况下,向用户授予db_datareader
和db_datawriter
已经为用户提供了所有表格的完整DML。授予执行任何存储过程不会给予任何其他权限。
通过提供所有外部程序必须通过的门,可以使用存储过程来提高数据完整性。不要授予插入,删除或更新,但要创建执行工作的SP并强制执行有关数据的适当规则。 (超出限制可以做的事情。)正如Joe Kuemerle指出的那样,存储过程可以用来提高安全性。
我在SQL Server 2000上开发应用程序时观察到这种行为,甚至在SQL Server 2008上重新测试并发现了相同的行为。我无法找到有关此行为的文档。
以DBO和SA身份登录创建一个表:
create table dbo.SO (PK int identity constraint SO_PK primary key
, SomeData varchar(1000)
)
然后为基本DML创建一些存储过程:
create procedure dbo.InsertSO (@SomeData varchar(1000)) as
begin
insert into dbo.SO (SomeData) values (@SomeData)
return SCOPE_IDENTITY()
end
go
create procedure dbo.SelectSO (@PK int=null) as
begin
if @PK is not null
select PK, SomeData from dbo.SO where PK = @PK
else
select PK, SomeData from dbo.SO
end
go
create procedure dbo.CountSO as
begin
select COUNT(*) as CountSO from SO
end
go
create procedure dbo.DeleteSO (@PK int=null ) as
begin
if @PK is not null
delete dbo.SO where PK = @PK
else
delete dbo.SO
end
go
create procedure dbo.UpdateSO (@PK int, @NewSomeData varchar(1000)) as
begin`
update dbo.SO
set SomeData = @NewSomeData
where PK = @PK
end
go
create procedure dbo.TruncateSO as
begin
truncate table dbo.SO
end
go
作为dbo,我们可以运行以下SQL语句:
declare @PK_to_update int
insert into dbo.SO (SomeData) values ('Hello world!')
set @PK_to_update = SCOPE_IDENTITY()
declare @PK_to_delete int
insert into dbo.SO (SomeData) values ('Goodbye cruel world!')
set @PK_to_delete = SCOPE_IDENTITY()
insert into dbo.SO (SomeData) values ('Four score and seven years ago...')
select PK, SomeData
from dbo.SO
delete dbo.so
where PK = @PK_to_delete
update dbo.SO
set SomeData = 'Hello Milky Way!'
where PK = @PK_to_update
select PK, SomeData
from dbo.SO
truncate table dbo.SO
select COUNT(*) as CountSO from dbo.SO
或者通过存储过程执行等效操作
go
declare @PK_to_update int
exec @PK_to_update = dbo.InsertSO 'Hello world!'
declare @PK_to_delete int
exec @PK_to_delete = dbo.InsertSO 'Goodbye cruel world!'
exec dbo.InsertSO 'Four score and seven years ago...'
exec dbo.SelectSO
exec dbo.DeleteSO @PK_to_delete
exec dbo.UpdateSO @PK_to_update, 'Hello Milky Way!'
exec dbo.SelectSO
exec dbo.TruncateSO
exec dbo.CountSO
现在,创建一个DDL存储过程并测试:
create procedure dbo.DropSO as
begin
drop table dbo.SO
end
go
begin transaction
select TABLE_NAME from INFORMATION_SCHEMA.TABLES
where TABLE_NAME = 'SO'
exec dbo.DropSO
select TABLE_NAME from INFORMATION_SCHEMA.TABLES
where TABLE_NAME = 'SO'
rollback transaction
现在创建另一个用户并授予对所有存储过程的执行权限。不授予任何其他权利。 (假设公共没有额外的权限和混合模式身份验证。不建议使用混合模式身份验证,但会测试如何更轻松地处理权限。)
exec sp_addlogin @loginame = 'SoLogin' , @passwd = 'notsecure', @defdb = 'Scratch'
exec sp_adduser @loginame = 'SoLogin', @name_in_db = 'SoUser'
go
grant execute on dbo.InsertSo to SoUser
grant execute on dbo.InsertSO to SoUser
grant execute on dbo.SelectSO to SoUser
grant execute on dbo.CountSO to SoUser
grant execute on dbo.DeleteSO to SoUser
grant execute on dbo.UpdateSO to SoUser
grant execute on dbo.TruncateSO to SoUser
grant execute on dbo.DropSO to SoUser
以SoLogin身份登录。试试DML:
declare @PK_to_update int
insert into dbo.SO (SomeData) values ('Hello world!')
set @PK_to_update = SCOPE_IDENTITY()
declare @PK_to_delete int
insert into dbo.SO (SomeData) values ('Goodbye cruel world!')
set @PK_to_delete = SCOPE_IDENTITY()
insert into dbo.SO (SomeData) values ('Four score and seven years ago...')
select PK, SomeData
from dbo.SO
delete dbo.so
where PK = @PK_to_delete
update dbo.SO
set SomeData = 'Hello Milky Way!'
where PK = @PK_to_update
select PK, SomeData
from dbo.SO
truncate table dbo.SO
go
select COUNT(*) as CountSO from dbo.SO
go
drop table dbo.so
只有错误:
Msg 229, Level 14, State 5, Line 2
The INSERT permission was denied on the object 'SO', database 'Scratch', schema 'dbo'.
Msg 229, Level 14, State 5, Line 6
The INSERT permission was denied on the object 'SO', database 'Scratch', schema 'dbo'.
Msg 229, Level 14, State 5, Line 9
The INSERT permission was denied on the object 'SO', database 'Scratch', schema 'dbo'.
Msg 229, Level 14, State 5, Line 11
The SELECT permission was denied on the object 'SO', database 'Scratch', schema 'dbo'.
Msg 229, Level 14, State 5, Line 14
The SELECT permission was denied on the object 'SO', database 'Scratch', schema 'dbo'.
Msg 229, Level 14, State 5, Line 14
The DELETE permission was denied on the object 'SO', database 'Scratch', schema 'dbo'.
Msg 229, Level 14, State 5, Line 17
The SELECT permission was denied on the object 'SO', database 'Scratch', schema 'dbo'.
Msg 229, Level 14, State 5, Line 17
The UPDATE permission was denied on the object 'SO', database 'Scratch', schema 'dbo'.
Msg 229, Level 14, State 5, Line 21
The SELECT permission was denied on the object 'SO', database 'Scratch', schema 'dbo'.
Msg 1088, Level 16, State 7, Line 24
Cannot find the object "SO" because it does not exist or you do not have permissions.
Msg 229, Level 14, State 5, Line 1
The SELECT permission was denied on the object 'SO', database 'Scratch', schema 'dbo'.
Msg 3701, Level 14, State 20, Line 2
Cannot drop the table 'SO', because it does not exist or you do not have permission.
尝试基本的DML存储过程:
declare @PK_to_update int
exec @PK_to_update = dbo.InsertSO 'Hello world!'
declare @PK_to_delete int
exec @PK_to_delete = dbo.InsertSO 'Goodbye cruel world!'
exec dbo.InsertSO 'Four score and seven years ago...'
exec dbo.SelectSO
exec dbo.DeleteSO @PK_to_delete
exec dbo.UpdateSO @PK_to_update, 'Hello Milky Way!'
exec dbo.SelectSO
他们工作,因为SP的所有者拥有正确的权利,即使SoUser没有。
尝试截断或删除存储过程:
exec dbo.TruncateSO
go
exec dbo.DropSO
再次出错:
Msg 1088, Level 16, State 7, Procedure TruncateSO, Line 4
Cannot find the object "SO" because it does not exist or you do not have permissions.
Msg 3701, Level 14, State 20, Procedure DropSO, Line 4
Cannot drop the table 'SO', because it does not exist or you do not have permission.
答案 1 :(得分:2)
执行权限不会打开任何额外的安全漏洞。在我看来,更大的漏洞是用户对表有直接的读/写访问权。
由于SQL Server实现了所有权链接,因此您可以通过撤消datareader / datawriter权限并通过用户只具有执行权限的存储过程提供所有数据访问来提供对数据的可控,可审计的访问。这将确保某人不能随意插入/更新/删除表。它还将在深度防御策略中提供另一层,因为如果使用数据库的应用程序容易受到SQL注入攻击,则攻击者无法读取/写入他们想要的任何表。
执行此操作的唯一警告是,如果您使用ORM,则可能需要一些额外的开发工作来使用sprocs而不是让ORM动态生成SQL。
答案 2 :(得分:1)
您想要的概念是“ownership chaining”
基本上,不会检查存储过程使用的同一模式(比如dbo)中的对象的权限。除外:始终检查拒绝。
因此,如果存储proc dbo.uspDoStuff使用表dbo.Parent和dbo.Child,则表上不需要任何权限,它只是起作用。除非您运行“DENY SELECT ON dbo.Parent to MyUser
”。
注意:您通常会执行“CREATE ROLE MyRole”,将用户添加到角色,并为角色授予权限。例如,db_datareader只是一个特殊的保留角色。
答案 3 :(得分:0)
授予执行权限将允许该人执行该存储过程在该存储过程的上下文中执行的任何操作(因此,如果sproc删除表,则用户将能够执行sproc以删除表)。
编辑,我刚检查过,我错了。拒绝访问不会撤消在存储过程中执行操作的能力。
以下是MSDN上的文章,它指定拒绝访问不会影响存储过程。
http://msdn.microsoft.com/en-us/library/bb669058.aspx
更新: 您可以做的是通过存储过程中的sp_executeSQL执行drop table命令,并拒绝用户删除表的能力。这应该可以防止存储过程成功执行命令(除非用户有权这样做),因为要使用sp_executesql,用户需要具有执行sql操作的权限,而不仅仅是访问存储过程。 / p>