前几天碰到一个问题,使用普通登陆抓取所有登录信息,环境如下:
账号Collect_user拥有数据库Collect的执行权限
Collect库上有个存储过程usp_collect_login_information
create proc usp_collect_login_information as
select * from sys.syslogins(nolock)
那么当使用Collect_user执行时只能得到sa和collect_user的信息,我又不想给Collect_user过大的权限,当时想到了使用存储过程中的with execute as owner方法,结果只在其中的一台服务器上能够执行,在其他的服务器上还是返回一条记录,后来发现原来必须设置数据库Collect的trustwothy属性为on,Alter database Collect trustworthy on,这样当我再使用Collect_user执行这个存储过程就会得到所有登录信息了。
虽然问题解决了,但是问题也接着来了.
尽管Collecct_user在其他数据库上没有用户,但是只要存储过程里加了with execute as owner,那么他就可以在存储过程里查询任意其他数据库的数据,并且执行过查询的数据库,他就更改存储过程,执行其他例如create table,drop table等操作,例如
create proc usp_trustworthy_test1
with execute as owner
as
select * from mydb1.Table1
go
create proc usp_trustworthy_test2
with execute as owner
as
drop table mydb1.table1
go
execute as login='Collect_user'
exec usp_trustworthy_test1
exec usp_trustworthy_test2
你会发现尽管collect_user在mydb1上都没有用户,但是依然可以成功执行两个存储过程
mydb1.table1也会被删除
结论就是如果你使用了trustworthy参数,那么必须严格审核带有execute as owner的存储过程,否则将给数据库带来严重风险