在服务器上存储加密的站点范围密码的最佳方法?

信息安全 加密
2021-08-28 06:53:01

我正在为我的公司开发一个 PHP 应用程序 (PHP 7.3),它将托管在我们自己的服务器中。目前它只能从网络内访问,但最终将向网络开放。

IT 部门将给我一个密码不会过期的“服务”用户(因此分配给我的服务器和应用程序本身的所有服务都将永远运行)但他们不想要该用户的密码以纯文本形式存储在服务器的任何位置。为此,每次我们需要对服务器服务等进行更改时,系统管理员都必须通过远程桌面连接输入密码,但我还需要 PHP 不断使用该用户的密码来访问网络上的其他资源( LDAP 服务器、其他 DB、MS SQL DB 等)。

我认为可能有用的是:

  1. 在 PHP 应用程序根文件夹上方的纯文本文件中加密密码
  2. 在我的应用程序的根文件夹上方但在另一个文件夹中拥有另一个纯文本中的密钥
  3. 在另一个文件或我的主要配置 PHP 文件中有一个密码

这有意义吗?或者也许我也可以加密密钥和文件中的另一个密钥来解密第一个密钥?

我对加密非常陌生,因此非常感谢任何解释或链接。

3个回答

我很惊讶在这个网站上似乎没有一个规范的问题和答案,或者至少没有这个问题的副本——但是快速搜索未能找到任何相关的东西。

(这个问题没有独立于操作系统的答案——但我将讨论 Unix/Linux 的各种原因,现在不值得讨论)。

为了使用密码,您的应用程序必须能够以未加密的形式访问它。这意味着运行应用程序的用户帐户和 root 将有权访问明文。它很可能也会出现在系统的备份中,并且肯定会出现在 VM 快照中。

所以不可能完全确定密码不会被泄露。这意味着您(或其他相关系统管理员)应该采取措施来缓解这种情况。显而易见的是:

1)密码轮换这限制了捕获的密码对攻击者有用的窗口。在大多数情况下,要获得无缝更改,您需要在两个帐户之间交替使用 - 因此一个正在使用,而另一个正在更改。令人惊讶的是,很少有人会为此烦恼。

2)基于令牌的身份验证- 密码引导一次性令牌的更改(并立即被客户端忘记)。这种部署更为罕见。

3)机器身份的使用越来越受欢迎(由于服务在 clud 环境中的可用性)。为了避免将明文密码存储在计算机上(或等价的替代品,例如私钥),基础设施为客户端提供担保,例如通过提供可以代替密码呈现的签名证明。这通常需要客户端和服务器上的自定义软件来处理身份验证。

鉴于您当前的限制,那么这些不是非常实用的解决方案 - 您只有一个帐户,使用现成的软件并且无法控制您尝试验证的服务器。进一步的考虑是,使用 PHP,无论您选择何种机制来存储密码,您都需要较低的开销。虽然不理想,但我能想到的最实用的解决方案是:

4)使用Linux内核密钥存储(假设这是linux)。AFAIK,没有一个 PHP 扩展 - 所以你需要运行一个外部程序来每次检索密码。

5)将密码存储在内存驱动器上的文件中(具有适当的权限)。您可以改用共享内存,但与文件及其内容交互的工具更加有限。

6) 将密码存储在 webserver 运行时内存中,并在运行时将其作为环境变量传递给 PHP

7) 将密码存储在加密文件系统中——这里有很多选择,但encfs可能是最不痛苦且最容易与备份集成的。

请注意,前三个要求您提供一种在启动时注入凭据的方法(不确定如何为网络服务器执行此操作),而加密要求您在启动时提供解密密钥。

您当然不应该将系统上的文件保存在任何可公开访问的文件夹中,因为配置错误等可能导致密码泄露。

将密钥保存在服务器上,即使是加密格式,也不起作用,因为您需要对其进行解密以供 PHP 使用,因此它会以解密格式存在于服务器上的某个位置,即使它只是在内存中,这听起来它违反了您管理员的要求。由于还有其他可用资源,您可以要求 IT 在网络上提供一个 API,该 API 将充当您需要访问的其他服务的网关。

对于真实世界的演示,您可以查看它是如何在 AWS 基础设施中的云中实施的(通过他们的“秘密管理器”服务)或 Azure 的“密钥库”

«IT 部门 (...) 不希望该用户的密码以纯文本形式存储在服务器的任何位置,我有点困惑。为此,每次我们需要更改服务器服务时,系统管理员都必须通过远程桌面连接输入密码»,我认为问题的主旨已经存在。

拥有应用程序没有到期的服务帐户是很正常的。此帐户(或多个帐户)应仅限于他们需要访问的资源。

该密码可以以明文形式存储在配置文件中(我认为这不是问题,真的),或者通过一些加密的密钥在其他地方进行混淆(您的建议)稍微隐藏。在这两种情况下,拥有整个系统访问权限(甚至只是 www-data)的攻击者都能够获得密钥。

但是,提到系统管理员每次都会通过 RDP 输入密码,这让我认为这不会满足您 IT 部门的期望。请注意,使用这种方法,无需多次输入密码。

因此,您应该与您的 IT 部门澄清他们希望如何存储和使用密码,然后进行相应的操作。也许他们对这种方法很好。但他们可能坚持认为密码可能永远不会进入磁盘(即使是加密形式),您需要始终保存在内存中。也许他们没有考虑到您需要多次绑定到 AD。他们可能更喜欢生成一个单独的帐户来访问 LDAP 和数据库......

您可以通过让受信任进程仅将凭据存储在内存中来使其工作,并且可能足以将内存中的机密(密码)传递给另一个进程,或者它可能需要执行绑定/代表应用程序登录。也可以使用 kerberos 令牌进行应用程序访问(但请注意,它必须定期更新!)。