17

我有一个 PHP 应用程序需要运行 bash 脚本,并提供用户名和密码(用于远程系统)。我需要将这些凭据存储在我的 PHP(Web)应用程序可以访问的地方。逻辑位置是数据库(目前是 MySQL,但将是不可知的)。散列和存储凭据的“标准”方式的问题在于它是不可逆的。我必须能够以未加密的明文形式获取凭据,才能将数据插入 bash 脚本。

有人对解决此问题的安全方法有任何建议吗?

我想也许 PKI'ing 凭据,并将结果存储在数据库中。然后使用私钥解密(PHP 可以做到)。将执行此操作的脚本存储在 Web 根目录之外。

任何想法都非常感谢。

4

12 回答 12

24

首先,要说明(希望)显而易见,如果您可以以任何方式避免存储用户名和密码,请这样做;这是一项重大责任,如果您的凭据存储遭到破坏,它可能会为同一用户提供对许多其他地方的访问权限(由于密码共享)。

其次,如果您必须存储凭证而不是使用不可逆的加盐加密哈希存储密码,因此如果您的数据被泄露,则密码不能轻易被逆向工程,并且根本不需要存储解密密钥。

如果您必须存储可解密的凭据:

  1. 选择一个好的加密算法——AES-256、3DES(过时的)或公钥密码(尽管我认为这对于这种用途来说是不必要的)。使用来自信誉良好的可信赖来源的加密软件 - 不要试图自己动手,你可能会弄错。
  2. 使用安全的随机生成器来生成您的密钥。弱随机性是与加密相关的安全失败的第一大原因,而不是密码算法。
  3. 将加密/解密密钥与您的数据库分开存储在一个操作系统安全文件中,该文件只能由您的应用程序运行时配置文件访问。这样,如果您的数据库被破坏(例如通过 SQL 注入),您的密钥不会自动受到攻击,因为这通常需要访问 HDD。如果您的操作系统支持与配置文件绑定的文件加密,请使用它——它只会提供帮助,而且通常是透明的(例如 NTFS 加密)。
  4. 如果可行,请存储使用主密码加密的密钥本身。这通常意味着您的应用程序。将需要在启动时键入该密码 - 在脚本的参数中提供它没有好处,因为如果您的 HDD 被破坏,您必须假设可以查看密钥文件和脚本。
  5. 对于每个凭证集,将(未加密)与加密数据一起存储;这用于“启动”加密密码,以使两个相同的密码不会产生相同的密文——因为这表明密码是相同的。
  6. 如果用户名不是查找帐户记录所必需的(在您的情况下不是),请加密用户名和密码。如果您同时加密两者,请将它们加密为一次加密运行,例如

    userAndPass=(user+":"+pass);
    加密初始化();
    加密(盐);
    加密(用户和密码);
    密文=加密最终();

    并存储单数blob,这样短密文的出现较少,更容易破解,用户名进一步加盐密码。

PS:我不使用 PHP 编程,因此无法评论该环境中合适的加密软件。

于 2008-11-04T03:53:43.653 回答
15

您需要研究好的 2 路加密方法,我的一般经验法则是:

如果您实现自己的加密代码,您将失败。

因此,找到一个经过充分验证的良好实现,并加以利用。

这里可能有一些很好的信息:

http://phpsec.org/library/

于 2008-11-04T02:49:58.117 回答
3

检查这个库:PECL gnupg它为您提供与 gnupg 交互的方法。您可以使用安全的公钥加密算法轻松加密和解密数据。

于 2008-11-04T02:50:52.547 回答
2

我建议您不要存储密码,而是通过生成 ssh 密钥并将您的公钥存储在远程系统的 authorized_keys 文件中来使用从主机到远程系统的无密码 ssh 连接。然后您只需要在配置期间建立连接。诚然,不能完全回答您的问题,但是以可逆的形式存储密码是安全漏洞恕我直言的滑坡,尽管我确信比我更聪明的大脑可以保证它的安全。

于 2008-11-04T03:43:32.347 回答
1

一种简单的入门方法是使用 mysql 的 ENCODE() 和 DECODE() 函数。我不知道下面使用的是什么算法,但它很容易使用:

INSERT INTO tbl_passwords SET encoded_pw = ENCODE('r00t', 'my-salt-string');

SELECT DECODE(encoded_pw, 'my-salt-string') FROM tbl_passwords;
于 2008-11-04T02:59:39.517 回答
0

正如许多人所说,您的场景要求您加密用户名和密码。我建议您查看 php 的mcrypt扩展以进行加密/解密。

于 2008-11-04T07:57:00.370 回答
0

只是为了跟进使用 MySQL 编码和解码功能的建议,该手册对这些功能的工作方式含糊不清:

加密的强度取决于随机发生器的好坏。对于短字符串应该足够了。

但我建议您可以改用内置的 MySQL 5.0 AES 函数AES_ENCRYPT()AES_DECRYPT()

SELECT AES_ENCRYPT('secret squirrel', '12345678') AS encoded

=> ØA;J×ÍfOU»] É8

SELECT AES_DECRYPT('ØA;J×ÍfOU»] É8', '12345678') AS decoded

=> secret squirrel

这些使用 128 位 AES,对于大多数用途来说应该足够强大。正如其他人评论的那样,使用盐值和具有高熵的键是一种很好的做法。

于 2008-11-24T00:46:19.647 回答
0

如果你去 PKI,我会,确保你保护好你的私钥!PKI 提供的强加密仅与您的密钥一样安全。

于 2008-11-04T02:53:33.383 回答
0

我认为你的目标。查看GPG以获得良好的开放加密库

于 2008-11-04T02:55:44.267 回答
0

看起来你几乎有两种方法可以做到这一点:

1)就像你建议的那样,使用一种或多种加密算法,然后可以在你的脚本中解密并用于身份验证。您可以使用 PHP 中的 MCrypt 库来完成此操作。

2) 根据所需的安全级别和脚本的漏洞级别,您可以使用安全哈希、密钥或其他一些难以猜测的唯一标识符,您可以使用这些标识符在脚本范围内劫持每个用户的帐户。

于 2008-11-04T02:56:44.423 回答
0

我想我将研究从 Web 应用程序中即时编译嵌入凭据的 PHP 脚本。

我会要求提供凭据(用于给定用途),然后创建并编译一个新的 PHP 脚本,仅用于此用途。这样,脚本只会做我需要的,不应该是“可读的”。我认为这听起来是最安全的方法。

将尝试使用 Roadsend。http://www.roadsend.com/

于 2008-11-16T23:49:46.113 回答
0

对于 PHP,重要的是要注意 AES 加密通过 MCRYPT_RIJNDAEL 函数实现的。当 PHP 提供非开放实现时,不要为它们付费。

有关更多信息,请参阅讨论可用密码的 PHP 页面

于 2009-08-04T04:34:55.663 回答