?
This document uses PHP Chinese website manual Release
由于PostgreSQL規(guī)則系統(tǒng)對查詢的重寫,非初始查詢指定的其它表/視圖被訪問。 使用更新規(guī)則的時候,這可能包括對表的寫權限。
重寫規(guī)則并不擁有一個獨立的所有者。 關系(表或視圖)的所有者自動成為重寫規(guī)則的缺省所有者。 PostgreSQLL 規(guī)則系統(tǒng)改變缺省的訪問控制系統(tǒng)的特性。 因規(guī)則而使用的關系在(規(guī)則)重寫時要對定義規(guī)則所有者進行權限檢查, 而不是激活規(guī)則的用戶這意味著一個用戶只需要對他的查詢里明確指定的表/視圖擁有所需的權限就可進行操作。
例如:某用戶有一個電話號碼列表,其中一些是私人的,另外的一些是辦公室秘書需要的。 他可以用下面方法構建查詢:
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;
除了他以外(還有數據庫超級用戶)沒有人可以訪問phone_data表。 但因為GRANT的原因,秘書可以從phone_number視圖上運行SELECT。 規(guī)則系統(tǒng)將把從phone_number里的SELECT重寫為從phone_data里的SELECT并將增加條件。 因為用戶是 phone_number 的所有者,因此也是規(guī)則的所有者, 所以現(xiàn)在要檢查他對phone_data的讀訪問的權限,而這個查詢是被允許的。 同時也要檢查訪問phone_number的權限,但這是對一個被撤消權限的用戶進行檢查的, 所以除了用戶自己和秘書外沒有人可以使用它。
權限檢查是按規(guī)則逐條進行的。所以此時的秘書是唯一的一個可以看到公共電話號碼的人。 但秘書可以設立另一個視圖并且賦予該視圖公共權限。 這樣,任何人都可以通過秘書的視圖看到phone_number數據。 秘書不能做的事情是創(chuàng)建一個直接訪問phone_data的視圖(實際上他是可以的, 但沒有任何作用,因為每個訪問都會因通不過權限檢查而被踢出事務)。而且用戶很快會認識到, 秘書開放了他的phone_number視圖后,他還可以撤消他的訪問權限。這樣,所有對秘書視圖的訪問馬上就失效了。
有些人會認為這種逐條規(guī)則的檢查是一個安全漏洞,但事實上不是。 如果這樣做不能奏效,秘書將必須建立一個與phone_data有相同字段的表并且每天拷貝一次數據進去。 那么這是他自己的數據因而可以賦予其它人訪問的權力。 一個GRANT意味著"我信任你"。 如果某個你信任的人做了上面的事情,那你就該想想是否該REVOKE了。
需要注意的是,當視圖可以用上面的技術來隱藏某些列的內容時,它們就不能可靠的在不可見的行上隱藏數據。 例如,下面的視圖是不安全的:
CREATE VIEW phone_number AS SELECT person, phone FROM phone_data WHERE phone NOT LIKE '412%';
這個視圖看起來是安全的,因為規(guī)則系統(tǒng)會從phone_number中SELECT,然后重寫入
phone_data的SELECT結果中,并且增加一個限制,即只有phone不是以412開頭的條目才可以。
但,如果用戶可以創(chuàng)建自己的函數,那不難讓規(guī)劃器在NOT LIKE
表達式之前先執(zhí)行用戶自定義函數。
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表中的每一個人和電話號碼會被標記為NOTICE,因為規(guī)劃器會選擇在
執(zhí)行NOT LIKE
之前,先執(zhí)行tricky
,因為前者的開銷大。
即使禁止用戶自定義一個新函數,內置函數也可以用在類似的攻擊中。例如,轉換函數會包含在它們產生的錯誤信息中的輸入。
這個機制同樣可以用于更新規(guī)則。 在上一章的例子里,例子數據庫里的表的所有者可以把shoelace視圖的SELECT, INSERT,UPDATE,DELETE權限賦予其他人。 但對shoelace_log只有SELECT權限。寫日志記錄的規(guī)則動作仍然可以成功的執(zhí)行。 并且其它用戶可以看到日志記錄。但他不能創(chuàng)建偽記錄,而且他也不能對現(xiàn)有記錄進行修改或刪除。 在這種情況下,不可能通過讓規(guī)劃器改變操作的順序來更改規(guī)則,因為 只有指向shoelace_log的規(guī)則才是無限制的。