什么更安全?硬编码凭证或将它们存储在数据库中?

信息安全 数据库 二进制代码
2021-08-21 18:38:39

我想知道这些东西中哪一个更安全。

想象一下硬编码的凭据,类似于:

if user.Equals("registereduser") && (password.Equals(encryptedpassword))
{
    Give access to the user

我知道这种方法有很大的缺陷,比如每次你想添加一个新用户时都必须修改代码,并且只对少数使用该应用程序的人可用。但是,如果你知道你只会让一群人使用它,而且这几乎不会改变,那就没那么可怕了。

我假设编译后的代码不可能在合理的时间内反编译,并且攻击者首先不会寻找硬编码的密码。

像这样硬编码凭据是否更安全?还是使用在数据库中加密密码的常用方法更安全?

4个回答

几点:

在数据库中加密密码的意思是散列。这是很大很大的不同。

使用数据库而不是硬编码用户数据的第一个原因不是安全性,而是简单性
(添加/修改/删除用户而不重新编译等)

以明文形式存储密码是一个问题,无论它们是在您的程序中还是在数据库中。将它们存储为散列和加盐(数据库和/或程序无关紧要。散列它们)。

依靠攻击者不会期望您的用户数据在您的程序中是“隐蔽的安全性”并且通常不安全

从已编译的程序中获取字符串比您想象的要容易得多。没有像您的示例中那样的任何混淆,甚至不需要一分钟(这包括启动编辑器和手动搜索字符串)。谁说你的程序是编译过的?例如。PHP...

如果您不了解其背后的原因,请不要试图改变既定做法。

请不要硬编码凭据或哈希。

硬编码密码可能会以一种无法轻易修复的方式危及系统安全。[...] 这也使得解决问题变得极其困难。

请参阅有关硬编码密码的 OWASP 页面

[...]许多散列是可逆的(或至少容易受到暴力攻击) - 此外,许多身份验证协议只是简单地请求散列本身 [...]

请参阅有关硬编码加密的 OWASP 页面

不要在您的源代码中包含任何凭据,包括(但不限于)用户名、密码、证书、令牌 ID 或电话号码。

以及他们的认证指南

这实际上远没有那么安全。

在一个理想的世界中,您的数据库不在 DMZ 中,而是只能从您的 Web 服务器直接访问,然后使用有限的帐户权限,为了破坏您的数据库并检索您的哈希密码表,我必须:

  1. 通过以下方式公开您的软件数据库连接变量(帐户/密码)
    • 破坏您的 Web 服务器以获取对其的 shell 访问权限 - 或 -
    • 利用应用程序中的弱点直接公开其数据库连接变量
  2. 连接到您的数据库。我可能需要能够从 SSH 到您的 Web 服务器或通过在其上托管受损代码来执行此操作,除非我设法使用某种形式的 IP 欺骗,成功绕过您的数据库背后的任何路由/防火墙(不太可能)。
  3. 检索表。这对于我通过步骤 1 妥协的帐户可能是不可能的,如果它实际上并没有比较值本身,而是将当前登录尝试的哈希值传递给数据库中的存储过程,该帐户仅限于访问存储的帐户程序。

如果我不能使用您的程序帐户直接读取表格,我基本上已经完成,除非我可以破坏数据库服务器上的管理员帐户或完全破坏数据库服务器的 VM。

这就是在我们讨论您自己的散列方案是否安全之前的全部内容。

就用户名和散列被“隐藏”而言,它们根本不是,即使您使用编译的代码。即使使用十六进制编辑器快速通过,用户名之类的东西也会立即显现出来。


安全性最适用于既服务于实际目的又将原始数据分离为允许将其用作可用信息所需的最小分区的层,同时仅以最小形式传递必要的相关信息,而不是尽可能地传递数据本身


你的方法把所有的鸡蛋放在一个篮子里

我通过网络的必要步骤是:

  1. 找到一种方法来公开您的代码以供下载。

而已。如果我让您的网络服务器出现故障,并且您的代码隐藏文件能够直接被拉下,那么您就完成了。我什至不需要对网络服务器进行更深入的妥协,而不是任何可能导致这种情况的事情(这可能会根据您是否将它们放在其他网络可读目录中而有所不同)。或者,如果我在您的代码中发现一个漏洞,我可能会让它直接吐出存储的用户名和哈希值。当然,仍然有同样的可能性完全破坏您的 Web 服务器。

没有办法减缓这样的攻击向量,假设您在某个给定级别的漏洞达到其他级别之前检测到它:单个漏洞会立即暴露所有内容。即使我们谈论的是已编译的软件,熟练的攻击者现在不仅会知道您的散列算法,而且如果您正在使用一种算法,也会知道您的胡椒,以及有效地访问您的散列和加盐密码表。

更简单地说第二个原则,您的软件本身实际上并不需要直接知道给定用户的存储密码来对其进行身份验证。它只需要知道它提供的密码是否与存储的密码相同,这是数据库可以为其确定的密码,以防止您的软件使用的凭据恶意访问数据库(除了尝试从提供给软件的存储过程中进行暴力破解之外,您可能会根据尝试次数和速度检测到并关闭)。


除非没有其他选择,否则不要推出自己的身份验证,或者您确定您确实知道您尝试做的所有事情背后的所有理由,并且愿意重复可能比您看到更多更好的评论的努力将永远让你的通过。这不值得你花时间,而且它几乎总是会导致一些比已建立的库或包更不安全的东西。

如果您认为自己通过做一些不同于行业标准做法的事情而变得聪明,那么请认真思考这些做法背后是否真的有很好的理由。

一旦用户凭据掌握在其他人手中,即使您对它们进行了哈希处理——即使您知道自己在做什么并且对它们进行了很好的哈希处理(当人们尝试使用自己的安全性时很少出现这种情况),您也必须假设它们受到了损害。这真的只是时间问题您最好的哈希努力最多只是延迟,您有一个窗口通知用户并锁定帐户,直到密码被重置。

我在这里看到的另一个问题也与安全性有关:假设您的一个用户必须更改他们的密码,因为他们感染了键盘记录器或网络钓鱼攻击。你将如何做到这一点?唯一的方法是询问他们的密码,重新散列该密码,然后在代码中替换它,重新编译然后重新发布。这是你必须做的很多“重新”。如果您使用数据库,您只需创建 1 个“更改密码”页面并将其挂接到您的数据库中。完毕。