Alter Database Set Trustworthy On設定資料庫信任,來達到跨資料庫存取資源
某些時候我們會遇見需要存取其他資料庫上的物件,例如msdb上的msdb.dbo.sp_send_dbmail預存程序
。我們會想利用該預存程序達到寄發信件的目的。還有利用msdb.dbo.sp_update_schedule讓前端程式可
以修改JOB排程。而一般的做法都是在目的資料庫建立使用者並授予足夠的權限來達到目的。
但有朋友提出如果有相同的帳號(例:User1)已存在兩個DB(例:DB1及DB2),而此時DB2中的User2是否可以
利用Execute As User來模擬User1身分進而存取到DB1的資源呢?
做個實驗
步驟一 : 如下圖所示,我們先建立兩個資料庫(DB1跟DB2)及兩個登入帳號(User1及User2)。而User1可以
連接DB1及DB2,而User2只有連接DB2的權限。
步驟二 : 如下圖所示,我們在DB1上建立一個預存程序叫sp1。並且允許User1來執行它。
步驟三 : 如下圖所示,我們在DB2上建立兩個預存程序叫sp2及sp3。並且允許User1及User2都可以執行它們。
* sp2的預存程序並沒有使用Execute As子句 (以預設值來看就是Execute As Caller)。
* sp3的預存程序我們使用Execute As User方式來模擬User1的身分。
步驟四 : 如下圖所示,User1在DB2資料庫同時執行sp2及sp3兩支預存程序。您可以看見沒有使用Execute As子句的
sp2執行成功,而使用Execute As User(模擬User1)的sp3卻顯示無權限存取DB1(這裡很有趣,User1利用Execute As
User來模擬自己後就無法存取DB1了。根據我的測試在沒有開啟Trustworthy狀態下,User1只有在sp是Execute As
Caller狀況下可以存取到DB1的資源)。
步驟五 : 同樣的方式,我們改用User2在DB2資料庫同時執行sp2及sp3兩支預存程序。您可以看見不管是執行sp2還是sp3
都顯示無權限存取DB1。
步驟六 : 重頭戲,我們將DB2資料庫的Trustworthy屬性設定為ON(除msdb外,其他預設都是OFF)。
步驟七 : 重新使用User1來執行DB2上的sp2及sp3。如下圖所示兩支預存程序都順利執行。
步驟八 : 重新使用User2來執行DB2上的sp2及sp3。如下圖所示使用Execute As User(模擬User1)的sp3執行成功,
但沒使用Execute As 子句的sp2執行失敗(這是正常的,由於sp2沒使用Execute As 子句,所以是採預設Execute
As Caller方式執行,而Caller是User2,因此SQL會驗證User2是否有權限執行。而我們實驗中並沒有讓User2有權限
去執行DB1的sp1,因此發生錯誤 )。
完成上述實驗後我們可以知道開啟資料庫的Trustworthy屬性後。DB2上的User2可藉由預存程序模擬User1的身分去存取
DB1上的資源。雖然很方便但相對也是很危險,一旦有心人士擁有某個資料庫db_owner或 db_ddladmin 等相關安全權利,
且知道 login 及其他資料庫的 user 關係,就有安全疑慮。因為他可以輕易的利用Execute As的方式存取原本不可以碰觸的
資源。(備註:要Alter Database Set TrustWorthy,需要Sysadmin的權限)
參考資料來源
1 . EXECUTE AS 子句
2 . TRUSTWORTHY 資料庫屬性
我是ROCK
rockchang@mails.fju.edu.tw