Answers:
首先,正如几个人已经说过的,将凭据与脚本分开是至关重要的。(除了提高安全性之外,这还意味着您可以对具有不同凭据的多个系统重复使用同一脚本。)
其次,您不仅应考虑凭据的安全性,而且还应考虑这些凭据被泄露时的影响。对于所有对数据库的访问,您不应该只有一个密码,而对于不同的访问级别,您应该具有不同的凭据。例如,您可能有一个数据库用户,可以在数据库中执行搜索-该用户应具有只读访问权限。另一个用户可能有权插入新记录,但不能删除它们。第三个人可能有权删除记录。
除了限制每个帐户的权限外,还应该限制每个帐户的使用位置。例如,不应允许Web服务器使用的帐户从Web服务器以外的任何其他IP地址进行连接。对于数据库具有完全root权限的帐户,实际上在其连接位置方面应该受到严格限制,并且只能以交互方式使用。还可以考虑使用数据库中的存储过程来严格限制每个帐户可以完成的操作。
这些限制需要在系统的DB服务器端实现,这样即使客户端受到损害,也不能从中更改这些限制。(而且,显然,除了数据库配置外,还需要使用防火墙等保护数据库服务器。)
对于仅允许有限只读访问并且仅来自特定IP地址的数据库帐户,您可能不需要其他凭证,具体取决于数据的敏感性和主机的安全性正在从中运行。一个示例可能是您网站上的搜索表单,该表单可以与仅允许使用存储过程的用户一起运行,该存储过程仅提取将在网页上显示的信息。在这种情况下,添加密码并没有真正赋予任何额外的安全性,因为该信息已经意味着要公开,并且用户无法访问其他任何更敏感的数据。
另外,请确保使用TLS建立与数据库的连接,否则任何在网络上侦听的人都可以获取您的凭据。
第三,考虑使用哪种凭证。密码只是一种形式,并非最安全。您可以改用某种形式的公用/专用密钥对或AD / PAM等。
第四,考虑运行脚本的条件:
如果以交互方式运行,则在运行时,应输入密码或私钥或私钥的密码,或者使用有效的Kerberos票证登录-换句话说,脚本应获取其密码。凭据在运行时直接从您那里获取,而不是从某些文件中读取。
如果它是从Web服务器运行的,请在启动Web服务器时考虑设置凭据。一个很好的例子是SSL证书-它们有一个公共证书和一个私钥,而私钥有一个密码。您可以将私钥存储在Web服务器上,但是在启动Apache时仍需要为其输入密码。您还可以在某些类型的硬件(例如,物理卡或HSM)上拥有凭据,一旦启动服务器即可将其删除或锁定。(当然,此方法的缺点是,如果发生某些情况,服务器将无法自行重启。我宁愿这样做,以免系统受到损害,但您的工作量可能会有所不同...)
如果脚本是从cron运行的,这是困难的部分。您不想让凭据位于系统上任何人都可以访问它们的地方–但是您确实希望让它们放在各处,以便您的脚本可以访问它们,对吗?好吧,不太正确。仔细考虑脚本在做什么。它需要数据库什么权限?可以限制它,以便由错误的人连接这些权限都没有关系吗?您是否可以直接在没有其他人可以访问的数据库服务器上而不是从拥有其他用户的服务器上运行脚本?如果出于某种我无法想到的原因,您绝对必须在不安全的服务器上运行脚本,并且该脚本必须 能够做一些危险/破坏性的事情...现在是重新思考您的体系结构的好时机。
第五,如果您重视数据库的安全性,则不应在其他人可以访问的服务器上运行这些脚本。如果有人登录到您的系统,那么他们将有可能获取您的凭据。例如,在具有SSL证书的Web服务器的情况下,至少从理论上讲,某人能够获得root权限并访问httpd进程的内存区域并提取凭据。最近至少有一种漏洞可以通过SSL进行,甚至不需要攻击者登录。
还可以考虑使用SELinux或apparmor或系统可用的任何工具来限制哪些用户可以执行操作。它们将使您能够禁止用户甚至尝试连接数据库,即使他们确实设法获得了对凭据的访问权限。
如果这一切听起来对您来说都是过大了,而您却负担不起或没有时间这样做-那么,根据我(自大和精英主义者)的观点,您不应在数据库中存储任何重要或敏感的信息。而且,如果您不存储任何重要或敏感的信息,那么存储凭据的位置也不重要-在这种情况下,为什么还要使用密码?
最后,如果你绝对无法避免存储某种证书的,你可以有凭据只读,并通过根和根拥有可以给予一个非常临时的基础上的所有权请求时,通过一个脚本来做到这一点(因为你的脚本应该不会是除非绝对必要,否则以root身份运行,并且连接到数据库没有必要)。但这仍然不是一个好主意。
首先,如果有任何办法可以进行更改,从而避免必须首先在脚本内部或旁边存储密码,则应尽一切努力。珍妮·D(Jenny D)的答案对此有很多好的建议。
否则,将密码放在具有受限权限的单独文件中的想法就差不多了。例如,您可以从主脚本中获取该文件:
. /usr/local/etc/secret-password-here
您还可以限制主脚本的权限,以便只有授权人员才能执行它,但是最好按照您的建议执行,并将密码本身仅存储在受限制的文件中。这样一来,您就可以检查代码本身(没有敏感机密),进行版本控制并更轻松地在脚本周围进行复制等。
/usr/local/etc
可能是到的符号链接/etc/local
”。我错过了。所以您也说对了,但是它是5月,因此是可选的。但是,没关系,个人喜好也没关系。
/etc/
而不是备份/usr/local/
(我认为可以在磁盘崩溃后重建)
其他答案已经解决了如何,但我将考虑是否。根据用户所连接的数据库类型,这些客户端程序可能已经具有合适的机制,在这种情况下,请务必使用它们(我在想~/.mysqlrc
或~/.pgpass
)。
如果您要让多个用户使用共享帐户访问数据库以进行特定查询,那么您可能不应该这样做。相反,请确保它们在数据库上具有帐户,并且这些帐户没有比他们所需更多的权限(可能读取了其中的大部分,并且只有很少的写访问权限)。如果他们需要对原本无法访问的某些表进行特定查询,请提供存储过程SECURTY DEFINER
以允许他们这样做。
如果没有你需要存储凭据上面的避免了,然后在这里阅读其他的答案。
根据情况,将密码隐藏在无法访问的地方的想法可能还可以。
如果信息是分开的,则意味着文件的简单编辑,例如在与同事进行代码审查期间不会显示该文件。但是请注意,任何有权访问您帐户的人都可以轻松找到这样的文件。我~/.ssh
出于此目的使用了一个子目录,原因很简单,即ssh
抱怨对访问权限的~/.ssh
限制不够。
但是,您还可以采取其他措施来防止这样的用户名和/或密码浏览。
混淆:如果在编辑脚本时不希望任何人读取用户名或密码,则可以将其放在文本中,而不是纯文本形式,而是混淆。如果混淆后的版本足够长,以至于无法防止他人看到它,则即使解密方法和密钥清晰可见,也无法得知。当然,可以访问您的帐户的人还是可以轻易规避这一问题。
使用GPG:
较好的方法是对gpg
公共文件中的用户名/密码对进行加密,并让脚本检索文件中的内容(可能会提示您输入密码,但如果不是这样,则可能会略胜一筹,但仍不能完全抵御系统上的root用户的攻击)缓存/过期)。我使用ggp卡,这样当我将笔记本电脑放在身边但拉出卡时,即使仍然可以缓存该引脚,也无法访问。至少如果我在几分钟内运行20次,我只需要提供一次销即可。
安全性似乎总是与便利性(设置和使用)成反比。
有一种方法可以将密码存储在bash脚本中,但是您必须对脚本进行加密和混淆处理,以使没有人可以实际读取它或在其上运行任何类型的调试器以查看其运行情况。要对bash / shell脚本进行加密和混淆并使之实际上是可执行的,请尝试在此处复制并粘贴它:
http://www.kinglazy.com/shell-script-encryption-kinglazy-shieldx.htm
在上面的页面上,您要做的就是提交脚本(您可以先提交示例脚本以省心)。将为您生成一个zip文件。右键单击下载链接,然后复制您提供的URL。然后,转到UNIX框并执行以下步骤。
安装:
wget到zip文件的链接
解压缩新下载的zip文件
cd / tmp / KingLazySHIELD
./install.sh / var / tmp / KINGLAZY / SHIELDX-(您的脚本名称)/ home /(您的用户名称)-force
上面的安装命令将为您执行的操作是:
它将在目录/ var / tmp / KINGLAZY / SHIELDX-(您的脚本名称)中安装脚本的加密版本。
它将在您指定的替换/ home /(您的用户名)的目录中放置指向此加密脚本的链接-这样,它使您无需键入绝对路径即可轻松访问该脚本。
确保没有人可以修改脚本-任何尝试修改加密脚本的操作都将使其无法操作...直到这些尝试被停止或删除。它甚至可以配置为在有人尝试使用脚本而不是运行脚本进行任何操作时通知您,例如黑客或修改尝试。
确保绝对没有人可以复制它。没有人可以将您的脚本复制到一个僻静的位置,然后尝试使用它来查看其工作原理。脚本的所有副本都必须链接到您在安装过程中指定的原始位置(第4步)。
注意:
我认为这不适用于提示用户作出响应的交互式脚本。这些值应硬编码到脚本中。加密可确保没有人真正看到这些值,因此您不必担心。
不考虑安全性的另一种解决方案(我也认为最好将凭据保存在另一个文件或数据库中)是使用gpg加密密码并将其插入脚本中。
我使用保存在USB中的无密码gpg密钥对。(注意:导出此密钥对时,请不要使用--armor,以二进制格式导出)。
首先加密您的密码:
echo -n "pAssw0rd" | gpg --armor --no-default-keyring --keyring /media/usb/key.pub --recipient someone@mail.com --encrypt
这将在标准输出中打印出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)
这样,仅当USB安装在系统中时,密码才能被解密。当然,您也可以将密钥导入系统(不太安全,或者完全没有安全性),也可以用密码保护私钥(因此不能自动进行)。
#!/bin/bash
unset username
unset password
unset dbname
echo -n "username:"
read username
echo -n "dbname:"
read dbname
prompt="password:"
while IFS= read -p "$prompt" -r -s -n 1 char
do
if [[ $char == $'\0' ]]
then
break
fi
prompt='*'
password+="$char"
# read -s -p "Enter Password: " pswd
# echo -e "\nYour password is: " $pswd
done
我不认为您应该存储密码。我想不到一个很好的理由。相反,您应该存储该密码的盐值哈希 -某些字符串,当原始密码作为输入传递时,该字符串是由某些函数可靠生成的,但绝不会是password。