Postgres 基于密码的身份验证安全吗?

信息安全 tls 数据库 md5 PostgreSQL
2021-09-03 08:03:50

根据Postgres 的文档,Postgres 的密码认证方法使用 MD5 散列来保护密码:

基于密码的身份验证方法是 md5 和密码。除了通过连接发送密码的方式(即分别为 MD5 散列和明文)之外,这些方法的操作类似。

如果您完全担心密码“嗅探”攻击,那么首选 md5。如果可能,应始终避免使用纯密码。但是,md5 不能与 db_user_namespace 功能一起使用。如果连接受 SSL 加密保护,则可以安全地使用密码(但如果依赖于使用 SSL,则 SSL 证书身份验证可能是更好的选择)。

我从许多来源听说 MD5 散列算法不再被认为是安全的。这是否意味着我应该避免对 Postgres 使用基于密码的身份验证?如果是这样,我应该使用哪种替代方法?

4个回答

如果使用 SSL,那么 PostgreSQL 所做的就很好。如果使用 SSL,但仍然在网络上进行身份验证,那么 PostgreSQL 所做的事情就很糟糕。他们使用 MD5 的游戏一文不值,但不是因为他们使用 MD5。MD5 有其自身的问题,但他们只是在严重滥用它。

使用“明文密码”身份验证,客户端显示用户名和密码,如果它们与服务器存储的内容匹配,则服务器接受它们。

使用“md5”身份验证,客户端显示一个值(恰好是密码和用户名串联的 MD5 哈希),如果它与服务器存储的内容匹配,则服务器接受它。

所以你看到了:在这两种情况下,客户端向服务器显示一堆字节,总是相同的序列。攻击者只需点击网络以观察这些字节,然后连接到服务器并发送相同的字节以获准进入即可。字节是 MD5 哈希的结果在这里完全无关紧要。这个 MD5 散列据说是密码等效的。只要连接完全可以被窃听(即没有 SSL),那么安全性就会付诸东流。

有关MD5 计算的详细信息,请参阅此页面。他们称之为“加密”,它根本不是(散列不是加密)。

我们甚至可以争辩说,使用这种 MD5会降低安全性:当使用明文密码时,它可以被转发到另一个身份验证服务器(使用 Kerberos、LDAP...),然后该身份验证服务器可以使用强存储技术(请参阅密码散列)。对于 PostgreSQL 特定的 MD5 哈希,这不适用。当使用“md5”身份验证方法时,它必须针对数据库中包含所有这些“md5”值的表。攻击者如果能够得到备份磁带或旧磁盘,就会立即获得数据库上的许多免费帐户。

而且,我坚持认为,这一切都与 MD5 加密弱点无关。如果将 MD5 替换为 SHA-512,所有这些仍然适用。

是的,使用 MD5 是安全的。当客户端想要进行身份验证时,服务器会发送一个随机盐值。客户端使用该值以及密码来生成 MD5 哈希。因为使用了随机盐,攻击者不能使用字典攻击。此外,由于每次客户端进行身份验证时盐都会更改,因此无法重播旧的身份验证请求。

细节在这里的AuthenticationMD5Password部分。

TLDR。如果您正确配置它并使用良好的长密码,它可能是安全的。

1.在 postgres 中,md5 auth-method表示客户端散列(讨论:1、2 这使得散列密码等效将数据库中的哈希与从客户端接收到的哈希进行比较。攻击者可以直接使用窃取的 pg_shadow 表中的任何散列,甚至无需花费时间破解 md5。

假设哈希最终会被盗并避免客户端哈希更安全。


您实际上可以只看一下代码,它非常简单:https://github.com/postgres/postgres/blob/master/src/backend/libpq/crypt.c#L141 <- 直接链接到这一行:

 if (strcmp(crypt_client_pass, crypt_pwd) == 0)

看看当port->hba->auth_method == uaMD5. 是的,不能截获散列明文,它再次被加盐和散列。但是当被任何其他攻击窃取时,它可以直接使用而无需破解。


2.不出所料,您可以通过使用password auth-methodand将服务器端 md5 散列与 postgres 一起使用create user whatever with encrypted password

除了通过连接发送密码的方式(即分别为 MD5 散列和明文)之外,这些方法的操作类似。

使用 SSL 保护明文密码。您可能应该知道它的哈希存储方式——盐被重用:

 /* Encrypt user-supplied password to match stored MD5 */
 if (!pg_md5_encrypt(client_pass,          // const char *passwd
                     port->user_name,      // const char *salt
                     strlen(port->user_name),
                     crypt_client_pass))   // char *buf

甚至可以创建随机生成的一次性用户名以将它们用作盐,但我不确定这是否是个好主意,这很容易出错。

虽然一般建议是从 md5 迁移,但它仍然没有被密码散列破坏。相关问题:1996 年以来,如果 MD5 被破解,为什么人们仍然使用/推荐它?

不要使用短密码。长而高质量的随机密码仍然是安全的。

为了快速估计,这些(不幸的是,相当旧的)链接有一些数字: http:
//blog.codinghorror.com/speed-hashing/
https://security.stackexchange.com/a/33684/41687

更新:感谢 irc.freenode.net 上#postgresql 频道的 RhodiumToad 澄清 md5 仍未因密码散列而损坏,良好的长密码将节省时间。

请查看从客户端应用程序(带有 Npgsql 连接器的 C#)到 Postgres 服务器的 TCP 流捕获:

没有 SSL

在那里,您可以看到来自密码、用户名和盐的 md5 哈希(查看黑色小箭头)。

现在,让我们看看使用安全连接 (SSL/TLS) 时的情况:

在此处输入图像描述

如您所见,当使用安全连接时,MD5 结果在连接中是不“可见的”。因此,您可以考虑这种与 PostgreSQL 安全的数据交换方法(类似的事情发生在 Web 服务器、其他数据库服务器等)。使用数据包嗅探器来了解数据的真实情况总是好的;-)