如果我有一个只有有限的权限的用户 - 只要拥有db_datareader和db_datawriter,应只允许用户查询数据并插入/编辑/删除数据,而允许用户在数据库中添加/修改/删除表。
可能有需要的用户可以执行存储过程。 如果用户被赋予执行权限(通过SQL语句:“GRANT执行以用户名”),将先前的限制(的DataReader和datawriter)仍然是什么用户试图通过存储过程执行执行呢? 或者说执行权限真正打开其他安全漏洞的潘多拉之盒(如果有的话,是什么)?
如果我有一个只有有限的权限的用户 - 只要拥有db_datareader和db_datawriter,应只允许用户查询数据并插入/编辑/删除数据,而允许用户在数据库中添加/修改/删除表。
可能有需要的用户可以执行存储过程。 如果用户被赋予执行权限(通过SQL语句:“GRANT执行以用户名”),将先前的限制(的DataReader和datawriter)仍然是什么用户试图通过存储过程执行执行呢? 或者说执行权限真正打开其他安全漏洞的潘多拉之盒(如果有的话,是什么)?
如果存储过程的所有者有权利来选择,插入,更新或删除对表,然后选择,插入,更新和删除存储过程中的语句,只要调用者有执行上的存储过程的权限将执行,甚至如果调用者无权直接执行选择,插入,更新或删除对表。
然而,除非来电有权执行DDL即使该存储过程的所有者拥有DDL权限的存储过程不能执行DDL。 请注意,这也适用于截断表。
答:你的情况给予db_datareader
和db_datawriter
用户已经给出了所有表用户完全DML。 授予执行任何存储过程将不会给任何其他权利。
存储过程可以被用于通过提供一个门,使所有外部程序必须以提高数据的完整性。 不要授予插入,删除或更新,但创建办的工作SP和执行有关数据相应的规则。 (以上并超出了可以用约束来完成。)和乔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.
执行权限不打开任何额外的安全漏洞。 在我看来,一个更大的洞是一个事实,即用户可在表中直接读/写访问。
由于SQL Server实现所有权链接,你可以通过撤销的DataReader / datawriter权限,并提供通过存储过程,用户只有执行权限所有的数据访问提供对数据的可控,可审计的访问。 这将确保其他人无法随意插入/更新/从表中删除。 它还将提供在深度防御策略的另一个层在使用该数据库的应用程序很容易受到SQL注入攻击,攻击者无法读取/写入他们想要的任何表中的事件。
有这样做的唯一需要注意的是,如果你使用的是ORM它可能需要一些额外的开发工作,使用存储过程,而不是让ORM动态生成的SQL。
你想要的概念是“ 所有权链 ”
基本上,权限不会在相同的模式对象检查(说DBO)通过存储过程使用。 除了:拒绝为必检项目。
所以,如果存储过程dbo.uspDoStuff使用表dbo.Parent和dbo.Child,需要在表上没有任何权限,它只是工作。 除非你已经运行“ DENY SELECT ON dbo.Parent to MyUser
”。
注意:您通常会怎么做“CREATE ROLE MyRole”,将用户添加到角色,并在角色授予权限。 拥有db_datareader仅仅是一个特殊的,保留例如角色。
授予执行权限将允许这个人做任何事情在存储过程的情况下,其存储过程的功能(所以如果存储过程删除表,用户将能够执行存储过程的删除表)。
编辑,我刚查了,我错了。 拒绝访问并不会撤销在存储过程中执行操作的能力。
这里是MSDN上的文章,它指定拒绝访问不会影响存储过程。
http://msdn.microsoft.com/en-us/library/bb669058.aspx
更新:您可能能够做的就是通过sp_executesql的存储过程执行DROP TABLE命令并拒绝用户的能力下降表。 这应该防止能够成功地执行命令(除非用户有权限这样做),因为使用sp_executesql的用户需要的权限来执行的SQL操作,而不只是获得存储过程的存储过程。