W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
由于PostgreSQL規(guī)則系統(tǒng)對(duì)查詢的重寫,會(huì)訪問(wèn)沒(méi)有在原始查詢中指定的表/視圖。使用更新規(guī)則時(shí),這可能包括對(duì)表的寫權(quán)限。
重寫規(guī)則并不擁有一個(gè)獨(dú)立的所有者。關(guān)系(表或視圖)的所有者自動(dòng)成為為其所定義的重寫規(guī)則的所有者。PostgreSQL規(guī)則系統(tǒng)改變了默認(rèn)的訪問(wèn)控制系統(tǒng)的行為。由于規(guī)則被使用的關(guān)系會(huì)按照規(guī)則所有者的權(quán)限來(lái)檢查,而不是調(diào)用規(guī)則的用戶。這表示用戶只需要在其查詢中顯式指定的表/視圖上的所需權(quán)限。
例如:某用戶有一個(gè)電話號(hào)碼列表,其中一些是私人的,另外的一些是辦公室助理需要的。該用戶可以構(gòu)建下面的東西:
CREATE TABLE phone_data (person text, phone text, private boolean);
CREATE VIEW phone_number AS
SELECT person, CASE WHEN NOT private THEN phone END AS phone
FROM phone_data;
GRANT SELECT ON phone_number TO assistant;
除了該用戶以外(還有數(shù)據(jù)庫(kù)超級(jí)用戶)沒(méi)有人可以訪問(wèn)phone_data
表。但因?yàn)?code class="command">GRANT的原因,助理可以在phone_number
視圖上運(yùn)行SELECT
。規(guī)則系統(tǒng)將把phone_number
上的SELECT
重寫為
phone_data
上的SELECT
。因?yàn)樵撚脩羰?code class="literal">phone_number的所有者,因此也是規(guī)則的所有者,對(duì)phone_data
的讀訪問(wèn)現(xiàn)在被根據(jù)該用戶的權(quán)限檢查,并且該查詢被允許。同時(shí)也要檢查訪問(wèn)phone_number
的權(quán)限,但這是針對(duì)調(diào)用用戶進(jìn)行的,所以除了用戶自己和助理外沒(méi)有人可以使用它。
權(quán)限檢查是按規(guī)則逐條進(jìn)行的。所以此時(shí)助理是唯一的一個(gè)可以看到公共電話號(hào)碼的人。 但助理可以建立另一個(gè)視圖并且賦予該視圖公共權(quán)限。這樣,任何人都可以通過(guò)助理的視圖看到phone_number
數(shù)據(jù)。 助理不能做的事情是創(chuàng)建一個(gè)直接訪問(wèn)phone_data
的視圖(實(shí)際上助理是可以的,但沒(méi)有任何作用,因?yàn)槊看卧L問(wèn)都會(huì)因通不過(guò)權(quán)限檢查而被否定)。而且該用戶一旦注意到助理開放了他的
phone_number
視圖,該用戶還可以收回助理的訪問(wèn)權(quán)限。立刻,所有對(duì)助理視圖的訪問(wèn)將會(huì)失敗。
有人可能會(huì)認(rèn)為這種逐條規(guī)則的檢查是一個(gè)安全漏洞,但事實(shí)上不是。 如果這樣做不能奏效,助理將必須建立一個(gè)與phone_number
有相同列的表并且每天拷貝一次數(shù)據(jù)進(jìn)去。 那么這是助理自己的數(shù)據(jù)因而助理可以為每一個(gè)想要訪問(wèn)的人授權(quán)。一個(gè)GRANT
意味著“我信任你”。 如果某個(gè)你信任的人做了上面的事情,那么是時(shí)候認(rèn)為信任已經(jīng)結(jié)束并且要使用
REVOKE
。
需要注意的是,雖然視圖可以用前文展示的技術(shù)來(lái)隱藏特定列的內(nèi)容,它們不能可靠地在不可見(jiàn)行上隱藏?cái)?shù)據(jù),除非標(biāo)志被設(shè)置。 例如,下面的視圖是不安全的:
CREATE VIEW phone_number AS
SELECT person, phone FROM phone_data WHERE phone NOT LIKE '412%';
這個(gè)視圖看起來(lái)是安全的,因?yàn)橐?guī)則系統(tǒng)會(huì)把任何phone_number
上的SELECT
重寫成 phone_data
上的SELECT
,并且增加限制使得只有phone
不以 412 開頭的項(xiàng)才被處理。但是如果用戶可以創(chuàng)建自己的函數(shù),那就不難讓規(guī)劃器在
NOT LIKE
表達(dá)式之前先執(zhí)行用戶自定義函數(shù)。例如:
CREATE FUNCTION tricky(text, text) RETURNS bool AS $$
BEGIN
RAISE NOTICE '% => %', $1, $2;
RETURN true;
END;
$$ LANGUAGE plpgsql COST 0.0000000000000000000001;
SELECT * FROM phone_number WHERE tricky(person, phone);
phone_data
表中的每一個(gè)人和電話號(hào)碼會(huì)被打印成一個(gè)NOTICE
,因?yàn)橐?guī)劃器會(huì)選擇在執(zhí)行NOT LIKE
之前先執(zhí)行tricky
,因?yàn)榍罢叩拈_銷大。 即使禁止用戶自定義一個(gè)新函數(shù),內(nèi)置函數(shù)也可以用在類似的攻擊中(例如,大部分造型函數(shù)會(huì)在它們產(chǎn)生的錯(cuò)誤信息中包含它們的輸入值)。
類似的考慮應(yīng)用于更新規(guī)則。在前一節(jié)的例子中,例子數(shù)據(jù)庫(kù)中表的所有者可以把shoelace
視圖上的SELECT
、INSERT
、UPDATE
和DELETE
權(quán)限授予其他人,但對(duì)shoelace_log
只有
SELECT
權(quán)限。寫日志項(xiàng)的規(guī)則動(dòng)作將仍然可以被成功地執(zhí)行,并且其它用戶可以看到日志項(xiàng)。但他們不能創(chuàng)建偽造的項(xiàng),并且他們也不能操縱或移除現(xiàn)有的項(xiàng)。在這種情況下,不可能通過(guò)讓規(guī)劃器改變操作的順序來(lái)推翻規(guī)則,因?yàn)橐?code class="literal">shoelace_log的唯一規(guī)則是無(wú)限制的INSERT
。在更復(fù)雜的情景中,這可能不正確。
當(dāng)需要對(duì)一個(gè)視圖提供行級(jí)安全時(shí),security_barrier
屬性應(yīng)該被應(yīng)用到該視圖。這會(huì)阻止惡意選擇的函數(shù)和操作符通過(guò)行被傳遞,直到視圖完成其工作。例如,如果前文所示的視圖被創(chuàng)建成這樣,它就是安全的:
CREATE VIEW phone_number WITH (security_barrier) AS
SELECT person, phone FROM phone_data WHERE phone NOT LIKE '412%';
Views created with the 使用security_barrier
創(chuàng)建的視圖的性能會(huì)遠(yuǎn)差于沒(méi)有使用該選項(xiàng)的視圖。通常,沒(méi)有辦法來(lái)避免這種現(xiàn)狀:如果最快的候選計(jì)劃可能在安全性上折衷,它就必須被拒絕。出于該原因,這個(gè)選在在默認(rèn)情況下是沒(méi)有啟用的。
當(dāng)處理沒(méi)有副作用的函數(shù)時(shí),查詢規(guī)劃器有更多的靈活性。這類函數(shù)被稱為LEAKPROOF
,并且包括很多簡(jiǎn)單常用的操作符,例如很多等于操作符。查詢規(guī)劃器可以安全地允許這類函數(shù)在查詢執(zhí)行過(guò)程中的任何點(diǎn)被計(jì)算,因?yàn)樵谟脩舨豢梢?jiàn)的行上調(diào)用它們將不會(huì)泄露關(guān)于不可見(jiàn)行的任何信息。更進(jìn)一步,不接收參數(shù)或者不從安全屏障視圖得到任何參數(shù)的函數(shù)不必被標(biāo)記為LEAKPROOF
以便被下推,因?yàn)樗鼈儚膩?lái)不會(huì)從該視圖接收數(shù)據(jù)。相反,一個(gè)可能會(huì)基于接收到的參數(shù)值拋出錯(cuò)誤的函數(shù)(例如在溢出或被零除事件中拋出錯(cuò)誤的函數(shù))不是防泄漏的,并且如果它被應(yīng)用在安全性視圖的行過(guò)濾器之前,它可能會(huì)提供有關(guān)不可見(jiàn)行的有效信息。
有一點(diǎn)很重要的是理解:即使一個(gè)視圖使用security_barrier
選項(xiàng)創(chuàng)建,它也只在不可見(jiàn)元組不會(huì)被傳遞給可能不安全的函數(shù)的前提下才是安全的。用戶可能也有其他方式來(lái)推斷不可見(jiàn)數(shù)據(jù);例如,他們可以使用EXPLAIN
看到查詢計(jì)劃,或者針對(duì)視圖來(lái)測(cè)量查詢的運(yùn)行時(shí)間。一個(gè)惡意攻擊者可能有能力推斷有關(guān)不可見(jiàn)數(shù)據(jù)的總量,或者甚至得到有關(guān)數(shù)據(jù)分布的某些信息或最常用值(因?yàn)檫@些東西可以影響計(jì)劃的運(yùn)行時(shí)間;或者甚至計(jì)劃的選擇,因?yàn)樗鼈円脖环从吃趦?yōu)化器的統(tǒng)計(jì)數(shù)據(jù)中)。如果這類“隱通道”攻擊很重要,那么授予任何到該數(shù)據(jù)的訪問(wèn)都可能是不明智的。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: