在 Shell 脚本中隐藏密码

aru*_*run 31 security password shell-script

如何在 shell 脚本中隐藏密码?有许多脚本正在访问数据库。如果我们打开脚本,其他人也会知道用户名和密码。所以如果有人知道如何隐藏,请告诉我。

我有一种方法:将密码放在一个文件中并使该文件隐藏并且没有人会访问该文件(更改权限并在访问数据库时在脚本中使用该文件)。

Jen*_*y D 45

首先,正如一些人已经说过的,将凭据与脚本分开是必不可少的。(除了提高安全性之外,这还意味着您可以对具有不同凭据的多个系统重复使用相同的脚本。)

其次,您不仅应该考虑凭证的安全性,还应该考虑这些凭证是否/何时受到损害的影响。您不应该只有一个密码才能访问数据库,您应该拥有具有不同访问级别的不同凭据。例如,您可以拥有一个能够在数据库中执行搜索的数据库用户 - 该用户应该具有只读访问权限。另一个用户可能有权插入新记录,但不能删除它们。第三个可能有权删除记录。

除了限制每个帐户的权限外,您还应该限制每个帐户可以从哪里使用。例如,不应允许您的网络服务器使用的帐户从网络服务器以外的任何其他 IP 地址进行连接。对数据库具有完全 root 权限的帐户在它可以连接的位置方面确实应该受到非常严格的限制,并且除了交互之外不应使用。此外,请考虑使用数据库中的存储过程来精确限制每个帐户可以执行的操作。

这些限制需要在系统的数据库服务器端实施,这样即使客户端受到损害,也无法更改这些限制。(而且,显然,除了数据库配置之外,数据库服务器还需要用防火墙等保护......)

对于仅允许有限只读访问且仅来自特定 IP 地址的数据库帐户的情况,您可能不需要任何其他凭据,具体取决于数据的敏感性和主机脚本的安全性正在运行。一个示例可能是您网站上的搜索表单,该表单可以由只允许使用存储过程的用户运行,该存储过程仅提取将在网页上显示的信息。在这种情况下,添加密码并不会真正赋予任何额外的安全性,因为该信息已经是公开的,并且用户无法访问任何其他更敏感的数据。

此外,请确保使用 TLS 建立到数据库的连接,否则任何在网络上侦听的人都可以获得您的凭据。

第三,考虑使用什么样的凭据。密码只是一种形式,并不是最安全的。您可以改为使用某种形式的公钥/私钥对,或 AD/PAM 等。

第四,考虑脚本运行的条件:

如果它以交互方式运行,那么您应该输入密码,或私钥的密码,或私钥,或者使用有效的 Kerberos 票登录,当您运行它时 - 换句话说,脚本应该得到它的在您运行它时直接从您那里获得凭据,而不是从某个文件中读取它们。

如果它是从网络服务器运行的,请考虑在启动网络服务器时设置凭据。这里的一个很好的例子是 SSL 证书——它们有一个公共证书和一个私钥,而私钥有一个密码。您可以将私钥存储在 Web 服务器上,但在启动 Apache 时仍然需要输入密码。您还可以拥有某种硬件(例如物理卡或 HSM)上的凭据,一旦服务器启动,这些凭据就可以删除或锁定。(当然,这种方法的缺点是,如果发生某些事情,服务器无法自行重启。我更愿意这样做而不是冒着系统受损的风险,但您的里程可能会有所不同......)

如果脚本是从 cron 运行的,这是困难的部分。您不希望将凭证放在系统上任何人可以访问它们的任何地方 - 但您确实希望它们散布在周围以便您的脚本可以访问它们,对吗?嗯,不太对。仔细考虑脚本在做什么。它对数据库需要什么权限?是否可以对其进行限制,以便错误的人与这些权限连接无关紧要?您是否可以直接在其他人无法访问的数据库服务器上运行脚本,而不是在拥有其他用户的服务器上运行?如果出于某种我无法想到的原因,您绝对必须在不安全的服务器上运行脚本,并且它必须 能够做一些危险/破坏性的事情......现在是重新思考你的架构的好时机。

第五,如果您重视数据库的安全性,则不应在其他人可以访问的服务器上运行这些脚本。如果有人记录在您的系统上,那么他们有可能获得在您的凭据。例如,在具有 SSL 证书的 Web 服务器的情况下,至少理论上有人能够获得 root 权限并访问 httpd 进程的内存区域并提取凭据。最近至少有一个漏洞可以通过 SSL 完成,甚至不需要攻击者登录。

此外,请考虑使用 SELinux 或 AppArmor 或任何可用于您的系统来限制哪些用户可以做什么。它们将使您能够禁止用户甚至尝试连接到数据库,即使他们确实设法获得了对凭据的访问权限。

如果这一切听起来对你来说太过分了,而你负担不起或没有时间去做 - 那么,在我(傲慢和精英主义者)看来,你不应该在你的数据库中存储任何重要或敏感的东西。如果您不存储任何重要或敏感的内容,那么您存储凭据的位置也不重要 - 在这种情况下,为什么要使用密码?

最后,如果你绝对无法避免存储某种证书的,你可以有凭据只读和自己的根和根可以给予一个非常临时的基础上的所有权请求时,通过一个脚本来做到这一点(因为你的脚本应该不会是除非绝对必要,否则以 root 身份运行,并且连接到数据库并不需要)。但这仍然不是一个好主意。

  • 一点也不傲慢和精英主义。否则我也是。“如果窃贼闯入,我该如何保护我的珠宝?” “把它放在一个用螺栓固定/焊接到位的保险箱里。” “那太麻烦了,我就弄个手提保险箱,把钥匙挂在挂钩上。” “那就别费心使用保险箱了。” 非常明智的建议。 (13认同)

Cel*_*ada 13

首先,如果有任何方法可以更改内容以避免首先将密码存储在脚本内部或旁边,那么您应该尽一切努力做到这一点。珍妮 D 的回答包含很多关于这方面的好建议。

否则,您将密码放在具有受限权限的单独文件中的想法几乎就是这样。例如,您可以从主脚本中获取该文件:

. /usr/local/etc/secret-password-here
Run Code Online (Sandbox Code Playgroud)

您还可以限制主脚本的权限,以便只有经过授权的人才能执行它,但最好按照您的建议进行操作,并且只将密码本身存储在受限文件中。这样你就可以允许检查代码本身(没有敏感的秘密)、版本控制和更容易地复制脚本等等......

  • 具有上述文件用法的完整示例脚本对于外行来说会很有帮助 (2认同)

Jua*_*anu 5

另一个解决方案,不考虑安全性(我也认为最好将凭据保存在另一个文件或数据库中)是使用 gpg 加密密码并将其插入脚本中。

我使用保存在 USB 中的无密码 gpg 密钥对。(注意:导出此密钥对时不要使用 --armor,以二进制格式导出)。

首先加密您的密码:

echo -n "pAssw0rd" | gpg --armor --no-default-keyring --keyring /media/usb/key.pub --recipient someone@mail.com --encrypt
Run Code Online (Sandbox Code Playgroud)

这将在标准输出中打印出 gpg 加密密码。复制整个消息并将其添加到脚本中:

password=$(gpg --batch --quiet --no-default-keyring --secret-keyring /media/usb/key.priv --decrypt <<EOF 
-----BEGIN PGP MESSAGE-----

hQEMA0CjbyauRLJ8AQgAkZT5gK8TrdH6cZEy+Ufl0PObGZJ1YEbshacZb88RlRB9
h2z+s/Bso5HQxNd5tzkwulvhmoGu6K6hpMXM3mbYl07jHF4qr+oWijDkdjHBVcn5
0mkpYO1riUf0HXIYnvCZq/4k/ajGZRm8EdDy2JIWuwiidQ18irp07UUNO+AB9mq8
5VXUjUN3tLTexg4sLZDKFYGRi4fyVrYKGsi0i5AEHKwn5SmTb3f1pa5yXbv68eYE
lCVfy51rBbG87UTycZ3gFQjf1UkNVbp0WV+RPEM9JR7dgR+9I8bKCuKLFLnGaqvc
beA3A6eMpzXQqsAg6GGo3PW6fMHqe1ZCvidi6e4a/dJDAbHq0XWp93qcwygnWeQW
Ozr1hr5mCa+QkUSymxiUrRncRhyqSP0ok5j4rjwSJu9vmHTEUapiyQMQaEIF2e2S
/NIWGg==
=uriR
-----END PGP MESSAGE-----
EOF)
Run Code Online (Sandbox Code Playgroud)

这样只有当系统中安装了U盘时,密码才能被解密。当然,您也可以将密钥导入系统(安全性较低,或根本没有安全性),或者您可以使用密码保护私钥(因此无法自动化)。