简体   繁体   English

在shell / Perl脚本中保存密码的最佳做法?

[英]Best practices for holding passwords in shell / Perl scripts?

I've recently had to dust off my Perl and shell script skills to help out some colleagues. 我最近不得不放弃我的Perl和shell脚本技能来帮助一些同事。 The colleagues in question have been tasked with providing some reports from an internal application with a large Oracle database backend, and they simply don't have the skills to do this. 有问题的同事的任务是从内部应用程序提供一些带有大型Oracle数据库后端的报告,他们根本没有这方面的技能。 While some might question whether I have those skills either (grin), apparently enough people think I do to mean I can't weasel out of it. 虽然有些人可能会质疑我是否具备这些技能(咧嘴笑),显然有足够的人认为我的意思是我无法摆脱它。

So to my question - in order to extract the reports from the database, my script is obviously having to connect and run queries. 所以对我的问题 - 为了从数据库中提取报告,我的脚本显然必须连接并运行查询。 I haven't thus far managed to come up with a good solution for where to store the username and password for the database so it is currently being stored as plaintext in the script. 到目前为止,我还没有设法找到一个很好的解决方案来存储数据库的用户名和密码,因此它目前在脚本中以明文形式存储。

Is there a good solution for this that someone else has already written, perhaps as a CPAN module? 对于其他人已经编写过的,有没有一个很好的解决方案,可能作为CPAN模块? Or is there something else that's better to do - like keep the user / password combo in a completely separate file that's hidden away somewhere else on the filesystem? 或者还有其他更好的事情 - 比如将用户/密码组合保存在一个完全独立的文件中,该文件隐藏在文件系统的其他位置? Or should I be keeping them trivially encrypted to just avoid them being pulled out of my scripts with a system-wide grep? 或者我应该对它们进行简单的加密,以避免它们被系统范围的grep从我的脚本中拉出来?

Edit: The Oracle database sits on an HP-UX server. 编辑:Oracle数据库位于HP-UX服务器上。
The Application server (running the shell scripts) is Solaris. 应用程序服务器(运行shell脚本)是Solaris。
Setting the scripts to be owned by just me is a no-go, they have to be owned by a service account that multiple support personnel have access to. 将脚本设置为仅由我拥有是不行的,它们必须由多个支持人员可以访问的服务帐户拥有。
The scripts are intended to be run as cron jobs. 这些脚本旨在作为cron作业运行。
I'd love to go with public-key authentication, but am unaware of methods to make that work with Oracle - if there is such a method - enlighten me! 我喜欢使用公钥验证,但我不知道如何使用Oracle的方法 - 如果有这样的方法 - 启发我!

Best practice, IMHO, would be to NOT hold any passwords in a shell / Perl script. 恕我直言,最佳做法是不在shell / Perl脚本中保存任何密码。 That is what public key authentication is for. 这就是公钥认证的用途。

If the script is running remotely from the server. 如果脚本是从服务器远程运行的。

  1. Make your reports views 制作报告视图
  2. Give the user you are logging into ONLY access to select on the report views 为您登录的用户提供仅在报表视图上进行选择的权限
  3. Just store the password. 只需存储密码即可。

That way, all that the user can do, is select the data for its report. 这样,用户可以做的就是选择报告的数据。 Even if someone happened to get the password, they would be limited as to what they could do with it. 即使有人碰巧得到了密码,他们也可能会受到限制。

Personally I hold passwords in configuration files which are then distributed independently of the application, and can be changed to the specific machine/environment. 我个人在配置文件中保存密码,然后独立于应用程序分发,并且可以更改为特定的机器/环境。 In shell scripts you can source these within the main script. 在shell脚本中,您可以在主脚本中获取这些脚本。

However, in Perl there are a variety of approaches. 然而,在Perl中有各种各样的方法。 You may wish to investigate Getopt::Long for command line options (and additionally Getopt::ArgvFile to store those in a simple configuration file), or look at something like Config::IniFiles for something with a little more power behind it. 您可能希望调查Getopt :: Long以获取命令行选项(以及另外Getopt :: ArgvFile将这些选项存储在一个简单的配置文件中),或者查看类似Config :: IniFiles的内容 ,以获得更强大的功能。 These are the two types I generally use, but there are other configuration file modules available. 这些是我通常使用的两种类型,但还有其他配置文件模块可用。

There is no good solution. 没有好的解决方案。 You can obfuscate the passwords a bit, but you can't secure them. 您可以对密码进行模糊处理,但无法保护它们。

If you have control over your DB setup, you could try to connect by a named pipe (at least mysql supports that) without a password and let the OS handle the permissions. 如果您可以控制数据库设置,您可以尝试通过命名管道(至少mysql支持)连接而无需密码,并让操作系统处理权限。

You could also store the credentials in a file with restrictive permissions. 您还可以将凭据存储在具有限制权限的文件中。

Since you've tagged ksh & bash I'm going to assume Linux. 既然你已经标记了ksh&bash,我就会假设Linux。

Most of the problem is that if the user can read the script and locate the method you used to hide / encrypt the file then they will also be able to do the same thing manually. 大多数问题是,如果用户可以读取脚本并找到用于隐藏/加密文件的方法,那么他们也可以手动执行相同的操作。

A better way may be do the following: 更好的方法可能是执行以下操作:

  1. Make your script so it can only be seen/read/opened by you. 制作您的脚本,以便您只能看到/阅读/打开它。 chmod 700 it. chmod 700它。 Hardcode passwords away. 硬编码密码。
  2. Have a "launcher" script that is executable by the user and does a sudo . 有一个“启动器”脚本,可由用户执行并执行sudo。

This way the user can see your launcher script, examine it to see it only has the single command line. 这样,用户可以看到您的启动器脚本,检查它以查看它只有单个命令行。 They can run it and it works, but they don't have permissions to read the source for the script that is sudo'd. 他们可以运行它并且它可以工作,但是他们没有权限读取sudo'd脚本的源代码。

I'm not sure what version of Oracle you are running. 我不确定您运行的是哪个版本的Oracle。 On older version of Oracle (pre 9i Advanced Security) some DBA's would CREATE USER OPS$SCOTT IDENTIFIED BY EXTERNALLY and set REMOTE_OS_AUTHENT to true. 在较旧版本的Oracle(pre 9i Advanced Security)上,某些DBA会CREATE USER OPS$SCOTT IDENTIFIED BY EXTERNALLY ,并将REMOTE_OS_AUTHENT设置为true。

This would mean that your remote sun machine could authenticate you as SCOTT and then your Oracle DB would accept that authentication. 这意味着您的远程sun机器可以将您作为SCOTT进行身份验证,然后您的Oracle DB将接受该身份验证。

This is a bad idea. 这是一个坏主意。

As you could image any Windows XP with a local user of SCOTT could then log into your DB without a password. 因为您可以使用SCOTT的本地用户对任何Windows XP进行映像,然后可以在没有密码的情况下登录到您的数据库。

Unfortunately it's the only option that i know of Oracle 9i DBs to not store username/passwords in your script or somewhere else accessible by the client machine. 不幸的是,这是我知道Oracle 9i数据库中唯一没有在您的脚本中存储用户名/密码或客户端计算机可访问的其他地方的选项。

What ever your solution it's worthwhile having a look through Oracle's Project Lockdown before committing. 在提交之前,通过Oracle的项目锁定了解你的解决方案是值得的。

For storing passwords you could do a two step encryption routine, first with a hardcoded key in your script itself, and optionally a 2nd time with a key stored in a file (which is set using file permissons to have restricted access). 对于存储密码,您可以执行两步加密例程,首先在脚本本身使用硬编码密钥,也可以选择第二次使用存储在文件中的密钥(使用文件许可设置以限制访问)。

In a given situation you can then either use a key file (+ key from script), or if the situation requirements aren't that great he can just use the encyrption using the key is hardcoded in the script. 在给定的情况下,您可以使用密钥文件(来自脚本的+键),或者如果情况要求不是那么好,他可以使用密钥在脚本中硬编码使用密钥。 In both cases the password would be encrypted in the config file. 在这两种情况下,密码都将在配置文件中加密。

There is no perfect solution because somehow you have to be able to decrypt and obtain the cleartext password...and if you can do it someone else can too if they have the right info. 没有完美的解决方案,因为不知何故,你必须能够解密并获得明文密码...如果你能做到这一点,如果他们有正确的信息,其他人也可以。

Especially in the situation where we give them a perl script (vs. an exe) they can easily see how you do the encryption (and the hardcoded key)...which is why you should allow the option to use a keyfile (that can be protected by filesystem permissions) as well. 特别是在我们为他们提供perl脚本(相对于exe)的情况下,他们可以很容易地看到你如何进行加密(以及硬编码密钥)...这就是为什么你应该允许选项使用密钥文件(可以也受文件系统权限的保护。

Some practical examples for how to implement is here 对于如何实现一些实际的例子是在这里

On windows create a Folder and a File within it containing the passwords in clear text. 在Windows上创建一个文件夹和一个包含明文密码的文件。 Set the user who would run the scheduled job(script or batch) as the only person with read/write access to this folder and file. 将运行预定作业(脚本或批处理)的用户设置为对此文件夹和文件具有读/写访问权限的唯一人员。 (remove even administrator). (甚至删除管理员)。 To all other scripts, add code to read the clear text password from this restricted file. 对于所有其他脚本,添加代码以从此受限文件中读取明文密码。

This should suffice for few. 这应该足够少了。

Keywords: Password HardCoding 关键字:密码硬编码

There are commercial or more advance solutions such as cyberark AIM can do it better, but doing it for free and out of box, I have been piggy back the SSH public/private key because for one, SSH key pairs most likely already created conform the security policy; 有商业或更先进的解决方案,例如cyberark AIM可以做得更好,但是免费且开箱即用,我一直在捎带SSH公钥/私钥,因为对于一个,很可能已经创建的SSH密钥对符合安全政策; secondly, SSH key pairs are already have a set of standard protocol to protect the keys by the file permission, continuous system hardening (like tripwire), or key rotation. 其次,SSH密钥对已经有一套标准协议,通过文件权限,连续系统强化(如tripwire)或密钥轮换来保护密钥。

This is how I did it: 这就是我做的方式:

  1. Generate the ssh key pairs if not yet. 如果还没有生成ssh密钥对。 The key pairs and directory will be protected by default system protocol/permission. 密钥对和目录将受默认系统协议/权限的保护。 ssh-keygen –t rsa –b 2048 ssh-keygen -t rsa -b 2048

  2. use the ssh public key to encrypt the string and stored in same .ssh directory $ echo "secretword" | 使用ssh公钥加密字符串并存储在同一个.ssh目录$ echo“secretword”|中 openssl rsautl -encrypt -inkey ~/.ssh/id_rsa.pub -pubin -out ~/.ssh/secret.dat openssl rsautl -encrypt -inkey~ / .ssh / id_rsa.pub -pubin -out~ / .ssh / secret.dat

  3. use ssh private key to decrypt the key, and pass the parameters to scripts/AP in the realtime. 使用ssh私钥解密密钥,并将参数实时传递给脚本/ AP。 The script/programe to include the line to decrypt in realtime: string= openssl rsautl -decrypt -inkey ~/.ssh/id_rsa -in ~/.ssh/secret.dat 脚本/程序包括实时解密的行:string = openssl rsautl -decrypt -inkey ~/.ssh/id_rsa -in ~/.ssh/secret.dat

PS - I have been experimenting CYBERARK AIM agentless solution. PS - 我一直在试验CYBERARK AIM无代理解决方案。 it's sort of pain requires significant changes/API changes for the API/script. 这种痛苦需要对API /脚本进行重大更改/ API更改。 will keep you posted how that goes. 会告诉你这是怎么回事。

在UNIX中,我总是将这些脚本设置为setuid,并将用户和密码信息存储在受到严密保护的文件中(整个目录树由常规用户不可读/可搜索,文件本身只能由脚本所有者读取) 。

Keep them in a separate file, trivially encrypted, and make a separate user in the database with read only access to necessary tables. 将它们保存在一个单独的文件中,进行简单加密,并在数据库中创建一个单独的用户,只读访问必要的表。 If you think the file has been read, then you can shut off access to just that user. 如果您认为该文件已被读取,那么您可以关闭对该用户的访问权限。

If you want to get fancy, a SUID program could check the /proc//exe and cmdline (in Linux), and only then release the username. 如果你想获得花哨,SUID程序可以检查/ proc // exe和cmdline(在Linux中),然后才释放用户名。

I have / had a similar issue with developers deploying SQL code to MSSQL (in fact to any database on that MSSQL server, so role had to be SysAdmin) using ANT from a Solaris server. 我有/类似的问题,开发人员使用来自Solaris服务器的ANT将SQL代码部署到MSSQL(实际上是MSSQL服务器上的任何数据库,因此角色必须是SysAdmin)。 Again I did not want to store the username and password in the ANT build.xml files so my solution, which I know is not ideal, is as follows: 我再次不想将用户名和密码存储在ANT build.xml文件中,所以我的解决方案,我知道并不理想,如下所示:

  1. Store name / value pairs for username and password in a plain text file 在纯文本文件中存储用户名和密码的名称/值对
  2. Encrypt file (on Solaris) and use a pass phrase only known to certain admins 加密文件(在Solaris上)并使用仅为某些管理员所知的密码短语
  3. Leave only the encrypted file on the Solaris system 仅保留Solaris系统上的加密文件
  4. ANT build.xml runs a sudo decrypt and prompts for pass phrase, which is entered by admin ANT build.xml运行sudo解密并提示输入密码,由admin输入
  5. ANT sources decrypted file loading username and password as variables for the SQL string ANT源解密文件加载用户名和密码作为SQL字符串的变量
  6. ANT immediately deleted the plaintext file ANT立即删除了明文文件
  7. ANT deploys code and exits ANT部署代码并退出

This all happens in a matter of seconds, and the sql username and password is never visibly accessible on the server. 这一切都在几秒钟内发生,并且sql用户名和密码永远不会在服务器上可见。 As the code is deployed by allowed admins in production, the developers never need to include it in their code. 由于生产中允许的管理员部署代码,开发人员永远不需要将其包含在他们的代码中。

I am sure it could be better, but... 我相信它会更好,但......

JB JB

It's a shame I never saw this thread before -- it looks very interesting. 很遗憾我之前从未见过这个帖子 - 看起来非常有趣。 I'll add my two cents for anyone coming upon the thread in the future. 对于将来遇到这个问题的人,我会加两分钱。

I'd recommend using OS authentication on the db server itself -- REMOTE_OS_AUTHENT is still FALSE. 我建议在数据库服务器本身上使用OS身份验证 - REMOTE_OS_AUTHENT仍为FALSE。

If you're invoking the script from another machine, setup a phrase-less SSH key and use SSH to get there. 如果您从另一台计算机调用该脚本,请设置一个无短语的SSH密钥并使用SSH来实现。 You can then pipe back the SQL results to the calling machine and it can process this information further. 然后,您可以将SQL结果反馈回调用计算机,它可以进一步处理此信息。

Doing this avoids having to code a password anywhere. 这样做可以避免在任何地方编写密码。 Of course, if a malicious administrator were to hijack the phrase-less key and use it, he or she could also access the user account on the DB host and could then do any operations the OS authenticated DB user could. 当然,如果恶意管理员劫持了无短语密钥并使用它,他或她也可以访问数据库主机上的用户帐户,然后可以对经过OS身份验证的数据库用户执行任何操作。 To mitigate this you could reduce the database permissions for that OS user to the bare minimum -- let's say "read only". 为了缓解这种情况,您可以将该操作系统用户的数据库权限降至最低 - 让我们说“只读”。

Ingo 英戈

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM