?
このドキュメントでは、 php中國語ネットマニュアル リリース
由于PostgreSQL規(guī)則系統(tǒng)對(duì)查詢的重寫,非初始查詢指定的其它表/視圖被訪問。 使用更新規(guī)則的時(shí)候,這可能包括對(duì)表的寫權(quán)限。
重寫規(guī)則并不擁有一個(gè)獨(dú)立的所有者。 關(guān)系(表或視圖)的所有者自動(dòng)成為重寫規(guī)則的缺省所有者。 PostgreSQLL 規(guī)則系統(tǒng)改變?nèi)笔〉脑L問控制系統(tǒng)的特性。 因規(guī)則而使用的關(guān)系在(規(guī)則)重寫時(shí)要對(duì)定義規(guī)則所有者進(jìn)行權(quán)限檢查, 而不是激活規(guī)則的用戶這意味著一個(gè)用戶只需要對(duì)他的查詢里明確指定的表/視圖擁有所需的權(quán)限就可進(jì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 secretary;
除了他以外(還有數(shù)據(jù)庫超級(jí)用戶)沒有人可以訪問phone_data表。 但因?yàn)?tt class="COMMAND">GRANT的原因,秘書可以從phone_number視圖上運(yùn)行SELECT。 規(guī)則系統(tǒng)將把從phone_number里的SELECT重寫為從phone_data里的SELECT并將增加條件。 因?yàn)橛脩羰?phone_number 的所有者,因此也是規(guī)則的所有者, 所以現(xiàn)在要檢查他對(duì)phone_data的讀訪問的權(quán)限,而這個(gè)查詢是被允許的。 同時(shí)也要檢查訪問phone_number的權(quán)限,但這是對(duì)一個(gè)被撤消權(quán)限的用戶進(jìn)行檢查的, 所以除了用戶自己和秘書外沒有人可以使用它。
權(quán)限檢查是按規(guī)則逐條進(jìn)行的。所以此時(shí)的秘書是唯一的一個(gè)可以看到公共電話號(hào)碼的人。 但秘書可以設(shè)立另一個(gè)視圖并且賦予該視圖公共權(quán)限。 這樣,任何人都可以通過秘書的視圖看到phone_number數(shù)據(jù)。 秘書不能做的事情是創(chuàng)建一個(gè)直接訪問phone_data的視圖(實(shí)際上他是可以的, 但沒有任何作用,因?yàn)槊總€(gè)訪問都會(huì)因通不過權(quán)限檢查而被踢出事務(wù))。而且用戶很快會(huì)認(rèn)識(shí)到, 秘書開放了他的phone_number視圖后,他還可以撤消他的訪問權(quán)限。這樣,所有對(duì)秘書視圖的訪問馬上就失效了。
有些人會(huì)認(rèn)為這種逐條規(guī)則的檢查是一個(gè)安全漏洞,但事實(shí)上不是。 如果這樣做不能奏效,秘書將必須建立一個(gè)與phone_data有相同字段的表并且每天拷貝一次數(shù)據(jù)進(jìn)去。 那么這是他自己的數(shù)據(jù)因而可以賦予其它人訪問的權(quán)力。 一個(gè)GRANT意味著"我信任你"。 如果某個(gè)你信任的人做了上面的事情,那你就該想想是否該REVOKE了。
需要注意的是,當(dāng)視圖可以用上面的技術(shù)來隱藏某些列的內(nèi)容時(shí),它們就不能可靠的在不可見的行上隱藏?cái)?shù)據(jù)。 例如,下面的視圖是不安全的:
CREATE VIEW phone_number AS SELECT person, phone FROM phone_data WHERE phone NOT LIKE '412%';
這個(gè)視圖看起來是安全的,因?yàn)橐?guī)則系統(tǒng)會(huì)從phone_number中SELECT,然后重寫入
phone_data的SELECT結(jié)果中,并且增加一個(gè)限制,即只有phone不是以412開頭的條目才可以。
但,如果用戶可以創(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ì)被標(biāo)記為NOTICE,因?yàn)橐?guī)劃器會(huì)選擇在
執(zhí)行NOT LIKE
之前,先執(zhí)行tricky
,因?yàn)榍罢叩拈_銷大。
即使禁止用戶自定義一個(gè)新函數(shù),內(nèi)置函數(shù)也可以用在類似的攻擊中。例如,轉(zhuǎn)換函數(shù)會(huì)包含在它們產(chǎn)生的錯(cuò)誤信息中的輸入。
這個(gè)機(jī)制同樣可以用于更新規(guī)則。 在上一章的例子里,例子數(shù)據(jù)庫里的表的所有者可以把shoelace視圖的SELECT, INSERT,UPDATE,DELETE權(quán)限賦予其他人。 但對(duì)shoelace_log只有SELECT權(quán)限。寫日志記錄的規(guī)則動(dòng)作仍然可以成功的執(zhí)行。 并且其它用戶可以看到日志記錄。但他不能創(chuàng)建偽記錄,而且他也不能對(duì)現(xiàn)有記錄進(jìn)行修改或刪除。 在這種情況下,不可能通過讓規(guī)劃器改變操作的順序來更改規(guī)則,因?yàn)? 只有指向shoelace_log的規(guī)則才是無限制的。