2009-07-16 33 views
3

如果我有一个只具有有限权限的用户 - 只是db_datareader和db_datawriter,它应该只允许用户查询数据并插入/编辑/删除数据,而不允许用户添加/修改/删除数据库中的表。授予数据库用户访问权限的后果执行权限是多少?

可能需要用户能够执行存储过程。如果用户被授予执行权限(通过以下sql:“授予用户名”),以前的限制(datareader和datawriter)是否仍会强制执行通过存储过程执行的用户?或者执行特权真的打开了潘多拉的其他安全漏洞(如果是这样,什么)?

回答

4

如果存储过程的所有者的权利来选择,插入,更新或删除对表,然后选择,插入,更新和删除存储过程中的语句将执行,只要调用者有执行的权利。存储过程,即使调用者没有权限直接对表执行选择,插入,更新或删除操作。

然而,除非来电有权执行DDL即使该存储过程的所有者拥有DDL权限的存储过程不能执行DDL。注意这也适用于截断表。

答案:在您的情况下,向用户授予db_datareaderdb_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. 
0

授予执行权限将允许该人员执行该存储过程在该存储过程的上下文中执行的任何操作(因此,如果该存储过程删除表,用户将能够执行该存储过程以删除该表)。

编辑,我只是​​检查,我错了。拒绝访问不会撤销在存储过程中执行操作的能力。

这是MSDN上的文章,它指定拒绝访问不影响存储过程。

http://msdn.microsoft.com/en-us/library/bb669058.aspx

UPDATE: 你也许能够做的就是通过sp_executesql的存储过程执行DROP TABLE命令并拒绝用户的能力下降表。这应该防止存储过程能够成功执行该命令(除非用户有权这样做),因为要使用sp_executesql,用户需要执行sql操作的权限,而不仅仅是访问存储过程。

+0

所以在案件中的问题列出,如果我会明确拒绝删除表的权限的用户,那么即使存储过程有sql来删除表,当用户试图执行它时,它们将被拒绝? – 2009-07-16 17:54:02

+0

我刚刚加倍检查,我错了。 – kemiller2002 2009-07-16 17:55:48

1

你想要的概念是

基本上,权限不上对象相同的架构检查使用“ownership chaining”(比如DBO)的存储过程。除了:总是检查拒绝。

因此,如果存储过程dbo.uspDoStuff使用表dbo.Parent和dbo.Child,表上不需要权限,它只是工作。除非你运行“DENY SELECT ON dbo.Parent to MyUser”。

注:通常你会怎么做“CREATE ROLE MyRole”,将用户添加到角色,并授予权限的角色。例如,db_datareader只是一个特殊的保留角色。

2

执行权限不会打开任何额外的安全漏洞。在我看来,更大的漏洞是用户可以直接读取/写入表格。

由于SQL Server实现所有权链接可以提供通过撤销的DataReader/datawriter权限,并提供通过存储过程,用户只具有执行权限的所有数据对数据的访问控制,可审计的访问。这将确保有人不能从表中任意插入/更新/删除。如果使用数据库的应用程序容易受到SQL注入攻击的攻击,攻击者无法读取/写入他们想要的任何表,那么它还将提供深层防御策略中的另一层。

有这样做的唯一需要注意的是,如果你使用的是ORM它可能需要一些额外的开发工作,使用存储过程,而不是让ORM动态生成的SQL。