存儲(chǔ)過(guò)程與觸發(fā)器是Sql Server進(jìn)行數(shù)據(jù)庫(kù)開(kāi)發(fā)與管理經(jīng)常使用的兩個(gè)對(duì)象,但是如果對(duì)存儲(chǔ)過(guò)程與觸發(fā)器的權(quán)限設(shè)置不當(dāng),則會(huì)給數(shù)據(jù)庫(kù)帶來(lái)巨大的安全隱患,抑或是MS就是這么設(shè)計(jì)的,是本人杞人憂天。
本文測(cè)試環(huán)境:sql server2005。
首先,建立測(cè)試環(huán)境
建立測(cè)試數(shù)據(jù)庫(kù) create database test
在測(cè)試數(shù)據(jù)庫(kù)中建立兩張表
create table t1(id int ,name varchar(10))
create table t2(id int ,name varchar(10))
向t2表中插入一行數(shù)據(jù)
insert into t2
select 1,'trieagle'
建立sql身份驗(yàn)證的登陸賬號(hào) trieagle ,同時(shí)test數(shù)據(jù)庫(kù)中建立用trieagle
一、存儲(chǔ)過(guò)程
情景說(shuō)明:如果某用戶擁有創(chuàng)建和執(zhí)行存儲(chǔ)過(guò)程的權(quán)限,則該用戶可以建立一個(gè)存儲(chǔ)過(guò)程,在該存儲(chǔ)過(guò)程操作其他表中的數(shù)據(jù)。那么即使該用戶對(duì)其他表沒(méi)有操作權(quán)限,則調(diào)用該存儲(chǔ)過(guò)程,可以對(duì)其他表中的數(shù)據(jù)進(jìn)行操作。
1、為trieagle用戶授予創(chuàng)建存儲(chǔ)過(guò)程的權(quán)限以及執(zhí)行存儲(chǔ)過(guò)程的權(quán)限
grant create proc to trieagle
注意:trieagle用戶要?jiǎng)?chuàng)建存儲(chǔ)過(guò)程的話,可能還需要修改schema的權(quán)限
grant alter on schema :: dbo to trieagle
2、trieagle建立存儲(chǔ)過(guò)程
Create proc p1
as
select * from t2
3、向trieagle用戶賦予執(zhí)行p1存儲(chǔ)過(guò)程的權(quán)限
grant exec on p1 to trieagle
4、trieagle執(zhí)行p1存儲(chǔ)過(guò)程
Exec P1
結(jié)果
Id name
1 trieagle
成功的查看到t2表中的數(shù)據(jù)。
安全隱患在于:如果用戶能夠執(zhí)行、修改存儲(chǔ)過(guò)程的話,那么實(shí)際上你的數(shù)據(jù)庫(kù)中的數(shù)據(jù)是出于一種既不安全的狀態(tài)。
解決方法:如果該允許某個(gè)用戶創(chuàng)建存儲(chǔ)過(guò)程的話,讓該用戶在其自己的schema上來(lái)創(chuàng)建,這樣可以避免上述問(wèn)題。即:
管理員:grant create schema to trieagle
用戶:create schema trieagle
Go
Create proc trieagle.p1
as
select * from t2
go
Exec trieagle.P1
結(jié)果:
消息229,級(jí)別14,狀態(tài)5,過(guò)程p1,第3 行
拒絕了對(duì)對(duì)象't2' (數(shù)據(jù)庫(kù)'test',架構(gòu)'dbo')的SELECT 權(quán)限。
同樣的情況在oracle上也存在,oracle的解釋是:執(zhí)行者執(zhí)行存儲(chǔ)過(guò)程時(shí),會(huì)使用存儲(chǔ)過(guò)程設(shè)計(jì)者所具有的權(quán)限,但是可以使用authid current_user指定用戶運(yùn)行存儲(chǔ)過(guò)程時(shí)使用的權(quán)限。Sql server中有類(lèi)似的語(yǔ)句是 在execute as ,但使用方法還未學(xué)習(xí),例如:
create proc p1
with execute as 'trieagle'
as
select * from t2
二、觸發(fā)器
情景說(shuō)明:如果某用戶擁有修改表的權(quán)限以及向表中有(insert、update、delete)權(quán)限之一的話,則該用戶即可創(chuàng)建觸發(fā)器。那么該用戶在觸發(fā)器中可以查看其他表的數(shù)據(jù),甚至插入、修改、刪除其他表的數(shù)據(jù),即使該用戶對(duì)其他表沒(méi)有任何的操作權(quán)限。
一、建立測(cè)試環(huán)境
為trieagle用戶授予向t1插入數(shù)據(jù)的權(quán)限,以及修改t1的權(quán)限
grant alter on t1 to trieagle
grant insert on t1 to trieagle
注意,在此并沒(méi)有為trieagle用戶賦予t2表的任何權(quán)限
二、trieagle用戶創(chuàng)建觸發(fā)器
create trigger t_query_t2
on t1
for insert
as
select * from t2
三、trieagle向t1表中插入數(shù)據(jù)
insert into t1 select 2,'wang'
觀察結(jié)果,你會(huì)發(fā)現(xiàn),會(huì)成功顯示t2表中的數(shù)據(jù)。結(jié)果:
Id name
trieagle
安全隱患在于:如果用戶能夠創(chuàng)建觸發(fā)器,并且在該表上有insert、update、delete權(quán)限之一的話,則實(shí)際上你的數(shù)據(jù)庫(kù)中的數(shù)據(jù)是出于一種不安全的狀態(tài)。
跟樓主的觀點(diǎn)相反。我認(rèn)為存儲(chǔ)過(guò)程恰恰是DBA控制數(shù)據(jù)權(quán)限的最最強(qiáng)大的工具。用存儲(chǔ)過(guò)程來(lái)控制權(quán)限,那表達(dá)能力可遠(yuǎn)超過(guò)什么select update delete之類(lèi)的授權(quán)。
例如用戶UserA下建立一個(gè)工資表Salar。對(duì)于用戶UserB可以給員工漲工資,但他的官可能比較下,每次只能給用戶甲一百元。對(duì)于用戶UserC是的大領(lǐng)導(dǎo),他可以給大家的工資加個(gè)0.這情況下在數(shù)據(jù)庫(kù)層面上,用授權(quán)語(yǔ)句顯然不能結(jié)果問(wèn)題,存儲(chǔ)過(guò)程就排上用場(chǎng)了。
首先,授權(quán)用戶UserB和UserC對(duì)UserA.Salar有select權(quán)限,但禁止其update,delete。
在UserA下建立存儲(chǔ)過(guò)程ProAdd100 為salar表中的工資加100;
授予UserB執(zhí)行Proadd100的權(quán)利;
在UserA下建立存儲(chǔ)過(guò)程ProMulti10 為salar表工資乘10;
授予UserC執(zhí)行Promulti10的權(quán)限。
這樣不就可以隨心所欲的控制數(shù)據(jù)的權(quán)限了。多強(qiáng)大。
DBA殺手........
在mssql中,存儲(chǔ)過(guò)程中引用了其它的存儲(chǔ)過(guò)程可以不存在,這也是一個(gè)小隱患
這有什么隱患呢。如果是程序直接訪問(wèn)數(shù)據(jù)庫(kù),還可能訪問(wèn)不存在的表呢。這也是隱患嗎。條條大路通羅馬。關(guān)鍵不在走哪條路,關(guān)鍵在于質(zhì)量。異常處理是必須的。