在shell/Perl脚本中保存密码的最佳实践是什么?

11

最近,我不得不重新使用Perl和shell脚本来帮助一些同事。这些同事需要从一个具有大型Oracle数据库后端的内部应用程序提取一些报告,但他们没有相关技能。虽然有些人可能会质疑我是否具备这些技能(grin),但似乎足够多的人认为我有这些技能,使得我不能逃避。

所以我的问题是,为了从数据库中提取报告,我的脚本显然必须连接并运行查询。到目前为止,我还没有想出一个好的解决方案来存储数据库的用户名和密码,因此它目前被存储为明文在脚本中。

是否已经有其他人编写了好的解决方案,例如作为CPAN模块?还是有其他更好的方法——像将用户/密码组合保留在完全分离的文件中,该文件隐藏在文件系统的其他地方?或者我应该将它们保持简单地加密,只是为了避免它们被全局grep从我的脚本中提取出来?

编辑: Oracle数据库位于HP-UX服务器上。
应用程序服务器(运行shell脚本)是Solaris。
将脚本设置为仅由我拥有所有权是不可行的,它们必须由多个支持人员都可以访问的服务帐户拥有。
这些脚本旨在作为cron作业运行。
我很想采用公钥身份验证,但不知道如何使其与Oracle配合使用——如果有这样的方法,请告诉我!

13个回答

7

在我看来,最佳实践是不要在shell / Perl脚本中保存任何密码。这就是公钥身份验证的用途。


使用Oracle(我想是10g)设置容易吗? - GodEater
1
在Oracle网站上搜索了一下,似乎“Oracle Wallet”就是我想要的。现在去烦我的DBA们来实施它。非常感谢 :) - GodEater

5

如果脚本是从服务器远程运行的。

  1. 创建报告视图
  2. 只给登录用户访问报告视图的选择权限
  3. 仅存储密码。

这样,用户所能做的就只有为其报告选择数据。即使有人知道密码,他们也会受到使用范围的限制。


4

个人而言,我将密码保存在配置文件中,这些文件与应用程序独立分发,并且可以更改为特定的机器/环境。在Shell脚本中,您可以在主脚本中引用它们。

然而,在Perl中有多种方法。您可能希望使用Getopt::Long来处理命令行选项(并且还可以使用Getopt::ArgvFile将其存储在简单的配置文件中),或者查看类似于Config::IniFiles这样功能更强大的模块。这是我通常使用的两种类型,但也有其他配置文件模块可用。


1

没有完美的解决方案。你可以稍微混淆密码,但是无法保证它们的安全性。

如果你能控制数据库设置,可以尝试通过命名管道连接(至少mysql支持此功能),不需要密码,并让操作系统处理权限。

你也可以将凭据存储在具有限制权限的文件中。


数据库运行在与执行shell脚本的不同物理服务器上。更糟糕的是,数据库服务器的操作系统是HP-UX,而shell脚本服务器的操作系统是Solaris,因此我不确定命名管道方法是否可行。 - GodEater

1

由于您标记了ksh和bash,我假设您在使用Linux。

问题的大部分在于,如果用户可以阅读脚本并找到您用于隐藏/加密文件的方法,那么他们也可以手动执行相同的操作。

更好的方法可能是:

  1. 使您的脚本只能被您查看/读取/打开。chmod 700它。硬编码密码。
  2. 有一个“启动器”脚本,用户可以执行sudo。

这样,用户可以查看您的启动器脚本,检查它是否只有单个命令行。他们可以运行它并且它可以工作,但他们没有权限读取sudo的脚本源代码。


数据库服务器使用HP-UX,而脚本实际上在执行的服务器上使用Solaris;)这些脚本旨在作为“服务帐户”运行,许多人都可以访问(出于支持原因),并由cron作业启动。在这种情况下,sudo方法仍然有效吗? - GodEater
大多数 cron 任务不会直接在其中加入 sudo,例如 "0 0 0 0 0 sodo myjob.sh" 的 crontab。但是,在 cron 任务中它可以正常工作,因为 cron 任务只是调用启动脚本,而启动脚本将运行 sudo。 - Paul Hargreaves

1

我不确定您正在运行哪个版本的Oracle。在旧版Oracle(9i高级安全性之前),一些DBA会使用CREATE USER OPS$SCOTT IDENTIFIED BY EXTERNALLY并将REMOTE_OS_AUTHENT设置为true。

这意味着您的远程Sun机器可以将您验证为SCOTT,然后您的Oracle DB将接受该身份验证。

这是一个坏主意。

因为您可以想象,任何具有本地用户SCOTT的Windows XP都可以无需密码登录到您的DB中。

不幸的是,这是我所知道的Oracle 9i DB中不存储用户名/密码于脚本或其他客户端可访问位置的唯一选项。

无论您的解决方案是什么,在提交之前浏览一下Oracle的Project Lockdown是值得的。


1

为了存储密码,您可以执行两个步骤的加密程序,首先使用脚本内部硬编码的密钥进行加密,然后再使用存储在文件中的密钥进行第二次加密(该文件使用文件权限设置为仅限受限访问)。

在特定情况下,您可以使用密钥文件(+来自脚本的密钥),或者如果情况要求不那么严格,他只能使用在脚本中硬编码的密钥进行加密。在这两种情况下,密码都将被加密在配置文件中。

没有完美的解决方案,因为您必须有能力解密并获取明文密码...如果您能够做到这一点,其他人也可以,如果他们拥有正确的信息。

特别是在我们提供perl脚本(而不是exe)的情况下,他们可以轻松地看到您如何进行加密(以及硬编码的密钥)...这就是为什么您应该允许使用键文件(可以通过文件系统权限进行保护)的选项。

一些实际的实现示例在 这里


0
在Windows上创建一个文件夹,并在其中创建一个包含明文密码的文件。 将运行定时任务(脚本或批处理)的用户设置为唯一有读/写访问权限的用户,(甚至删除管理员)。 对于所有其他脚本,请添加代码以从此受限制的文件中读取明文密码。 这对于少数人来说应该足够了。
关键词:密码硬编码。

0

很遗憾我以前没有看到这个帖子,它看起来非常有趣。我会为将来遇到这个帖子的任何人提供我的意见。

我建议在数据库服务器本身上使用操作系统认证——REMOTE_OS_AUTHENT仍然为FALSE。

如果您从另一台机器调用脚本,请设置一个无密码SSH密钥并使用SSH进行连接。然后,您可以将SQL结果返回到调用机器,并进一步处理此信息。

这样做避免了在任何地方编写密码。当然,如果恶意管理员劫持了无密码密钥并使用它,他或她也可以访问DB主机上的用户帐户,然后可以执行OS认证的DB用户可以执行的任何操作。为了减轻这种情况,您可以将该OS用户的数据库权限降低到最低限度——比如“只读”。

Ingo


0
在UNIX中,我经常将这些脚本设置为setuid,并将用户和密码信息存储在一个受到严格保护的文件中(整个目录树对普通用户来说都是不可读/不可搜索的,而该文件本身仅可被脚本所有者读取)。

1
我认为将脚本(任何类型)设置为suid是不好的做法?我确定我在某个地方读到过... - GodEater
1
这里有一个很好的参考,解释为什么通常不建议使用suid。 http://www.samag.com/documents/s=1149/sam0106a/0106a.htm - Paul Hargreaves
只要脚本本身不能被欺骗(这是另一个话题),setuid脚本就可以正常工作。 - paxdiablo
Will Deich的超级命令非常适合管理脚本的suid执行:它类似于脚本的sudo。参见http://www.ucolick.org/~will/#super - Charles Stewart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接