使用 Oracle 的 Security External Password Store 功能实现数据库加密登陆

时间:2022-05-03
本文章向大家介绍使用 Oracle 的 Security External Password Store 功能实现数据库加密登陆,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

编辑手记:让安全成为一种习惯,使用 Oracle 的 Security External Password Store 功能实现加密登录, 不将明文密码暴露在生产环境当中。

本文来自周四大讲堂整理。

作者简介:赵全文

就职于太极计算机股份有限公司,在 中央电化教育馆 做Oracle DBA的驻场运维工作。

在去年国内很多用户的 Oracle 数据库突然遭到比特币勒索,(

知己知彼-关于Oracle安全比特币勒索问题揭秘和防范)分析事件我们发现,根源在于用户缺乏安全意识。生产环境中使用的 Oracle 数据库确实存在着很多安全隐患和安全风险,但Oracle 在数据库安全方面的解决方案也有很多,比如 Oracle 审计与数据库防火墙(AVDF)产品、Oracle 的透明数 据加密功能(KDE)和 Oralce Wallet(也称 Oracle 钱夹)加密用户的密码等等。

接下来我们将会分享如何使用 Oracle 的 Security External Password Store 功能实现加密登录, 不将明文密码暴露在生产环境当中。

如果需要从 SHELL 脚本来连接到 Oracle 数据库,那么这些脚本包含数据库连接详细信息,这可能是一个主 要的安全问题。一个解决方案是使用操作系统身份验证,但 Oracle 10g 第 2 版提供了使用安全外部密码存储的 功能。其中 Oracle 登录证书存储在客户端 Oracle 电子钱包中,这样的话,在 SHELL 脚本里就可以使用“/ @ db_alias”这样的语法来连接。这对于用脚本登录数据库进行操作来说是非常有用的,尤其对于企业安全要求很高,不希望用户名和密码明文存在配置文件中,而且对于密码的维护是极为方便的,比如把 wallet 放在指定路 径下,当修改密码时,只需统一覆盖 wallet 即可。

那么,Oracle 是如何通过安全外部密码存储(Secure External Password Store)来达到无密码登录数据库呢?我们来说,连接到数据库的密码证书是存储在Oracle wallet 里,这个 wallet(钱夹)是一个用来保存认证和签名证书的一种安全软件容器。这种钱包使用可以简化依靠密码凭据连接到数据库的大规模部 署。 配置此功能时,应用程序代码,批处理作业和脚本不再需要嵌入的用户名和密码。 风险降低,因为这样的密码不再以明确的方式暴露,并且当用户 名或密码改变时,密码管理策略更容易实施,而不改变应用程序代码。

因为用“安全外部密码存储”这种方式所存储的密码密文信息是存储在 Oracle wallet 里的,那么我们先介绍一下,什么是 Oracle wallet 以及它里面可 以存储一些什么信息?

请看下面的一段英文描述

中文翻译如下, Oracle 钱夹是一个用于存储不同类型认证和加密密钥的 PKCS#12 容器。因此,这种钱夹可以用于存储以下信息的一个或多个:

  • Oracle 数据库的 PKI 身份验证凭据 网络加密证书(SSL/TLS)
  • Oracle 高级安全透明数据加密(TDE)的主加密密钥
  • Oracle 数据库安全外部密码存储的密码

说的直白一点,Oracle wallet 可以形象的比喻成我们日常生活中的钱包一样,在钱包里,我们可以放银行卡、身份证、信用卡、公司的员工卡、就餐 卡等等。

看了上面的一段英文描述和中文翻译,想必大家对 Oracle wallet 已有所了解。那么什么是 Oracle 的 Secure External Password Store(安全外部密码 存储)呢?

中文翻译如下,

使用安全外部密码存储,Oracle 将数据库凭据(即用户名和密码)安全地存储在 Oracle 电子钱包中。 在启动数据库连接时,Oracle 访问钱包并根据 连接字符串读取凭据。 由于配置了自动登录,因此无需密码即可打开钱包并读取凭据。 只有在电子钱包中添加,更改或删除凭据时才需要密码。 连接字符串在电子钱包中是唯一的。 每个连接字符串只能存储一个凭证。 同一数据库的不同凭据必须由不同的连接字符串区分。 从上面的中文解读,我们可以得知,安全外部密码存储就是 Oracle 把用户名和密码存放在 Oracle wallet 的一种安全加密形式。

下面我们根据 Oracle 10gR2 官方文档中的 Secure External Password Store 功能来演示和操作,最终实现无密码登录数据库。

虽然说,使用 wallet 的图形界面(在 command line interface 下 输入 owm 命令可以打开)可以极大的简化管理密码证书,至于为什么不能用 owm(oracle wallet manager)来创建和管理 wallet 的外部密码存储,而是使用 mkstore 命令?

一般来说,用户(包括应用程序、批处理任务和脚本)都是通过一个标准的数据库连接字符串(database_connect_string)的连接语句(connect statement)来连接到 Oracle 数据库的。这些字符串里包括用户名、密码和网络服务名,或者是在 tnsnames.ora 文件当中列出的 TNS 别名,还有另一种连接字符串的 形式是主机名:端口号:sid(这种形式在应用程序连接到 Oracle 数据库当中随处可见)。

  比如,下面这样的连接形式:

其中 ORASALES 为 TNS 别名,ourhost37:1527:DB17 为主机名:端口号:sid。 然而,如果客户端配置了安全外部密码存储的话,就可以使用下面的连接语法来连接到数据库,而不需要指定用户名和密码。

connect /@db_connect_string

在这种情况下,数据库证书、用户名和密码是安全地存储在创建的 Oracle 钱夹里,由于 wallet 的自动登录特性(auto login)是打开的,也就是说,一 旦创建了 wallet 以后是自动打开的,所以不需要密码去打开 wallet。在这个 wallet 里有证书,而用来连接数据库的用户名和密码的信息就保存在这个证书里。

接下来,我们就开始使用外部密码存储来配置 Oracle 的客户端。

1、先查看一下 Oracle 软件默认的 wallet 目录所在的位置和状态

从上图可以看出,wallet 的类型是以文件形式存在,而且默认的 wallet 就是位于$ORACLE_BASE/admin/$ORACLE_SID/wallet 目录,状态为关闭。那 么,我们再去相应的位置查看一下 wallet 目录是否存在,

从上图可以得知,wallet 目录不存在,因为我们从来没有创建过 wallet,它的状态应该就是 closed,所以我们在用 mkstore 命令(前面在说不能用owm 创建 wallet 时提到过)创建 wallet 之前,必须先创建一个存在的 wallet 目录。

这里为了安全起见,也为了防止将 wallet 目录误删除,我们不把 wallet目录放在刚才用 v$encryption_wallet 视图查出的位置,即$ORACLE_BASE/admin/$ORACLE_SID 下,而是放到$ORACLE_HOME/owm(因为$ORACLE_HOME 是Oracle 软件所在目录,而且我们也不允许去改动这里的目录和文件)。

下面进行创建 wallet 目录

2、在 Oracle 客户端开启 external password store(外部密码存储)。

(1)使用 mkstore 命令先创建一个 wallet,命令语法来自官方文档

wallet_location 参数指定为我们刚才创建的 wallet 目录

上面提示,要给 wallet 输入一个密码(在 wallet 打开时需要输入,在创建完 wallet 以后,Oracle 会自动打开),这里输入 Oracle123(输入的密码不回显 哦),再输入一遍(同样不回显,如果 2 次输入的不一样,Oracle 会提示重新输入的)。

那么,我们到 wallet 目录下面查看一下是生成了什么文件。

其中 cwallet.sso 文件是用于保存 wallet 是否自动登录的信息,ewallet.p12 文件是用来保存相关的证书信息,而我们要使用的用户名和密码的信息就 保存在证书里。

(2)使用 mkstore 命令来给刚才创建的 wallet 创建证书,命令语法来自官方文档

其中带<>的参数,官方文档已经解释的很清楚了,我们再描述一下。

  • wallet_location:wallet 目录所在位
  • db_connect_string:文件 tnsname.ora 中的 TNS 别名
  • tnsnames.ora:存放 Oracle 数据库连接字符串的文件,也是 Oracle 约定俗成的文件,从 Oracle 诞生起一直沿用到今,可见它的重要性不言而喻。在Linux 系统下,位于$ORACLE_HOME/network/admin 目录
  • username:Oracle 数据库要连接的用户名
  • password:Oracle 连接用户要输入的密码

为了不和 Oracle 原先在 tnsnames.ora 文件中创建的 TNS 别名有所关联,我们再单独创建一个。

其中 BASE 是我们刚才新建的 TNS 别名,而 YSYKTEST 是原先存在的 TNS 别名。 现在开始用 mkstore 命令创建 wallet 的证书,见下图

在创建证书时,需要输入 wallet 的密码,就第 1 步创建 wallet 时输入的密码。

其中,base 是刚刚创建的 TNS 别名,而且用户名和密码一定要输入正确,否则即使创建成功,一会儿也连不上 Oracle 数据库。

其实用 mkstore 命令创建 wallet 的证书时,也可以不将用户的密码写在命令行中,而是根据命令提示进行输入(输入的密码不回显),见下图操作:

其中,前两次输入的密码为用户 szd_base_v2 的密码 ysyktest,第三次输入的密码为 wallet 的密码 Oracle123。

上面是创建了 wallet 的证书,为了让 Oracle 能够使用 wallet,还必须在 sqlnet.ora 文件(和 tnsnames.ora 一样,也是位于$ORACLE_HOME/network/admin 目录)中指定 WALLET_LOCATION 参数和 SQLNET.WALLET_OVERRIDE 参数。

下面进入第 3 步,

(3)在 sqlnet.ora 文件中增加 WALLET_LOCATION 参数和 SQLNET.WALLET_OVERRIDE 参数,参考语法来自官方文档

其中,WALLET_LOCATION 参数当中 DIRECTORY 的取值为 wallet 目录。下面在 sqlnet.ora 文件中增加这 2 个参数,

进入$ORACLE_HOME/network/admin 目录,发现没有 sqlnet.ora 文件,可能是没有配置 sqlnet.ora 文件。那么我们在图形界面下,用 netca 命令生成sqlnet.ora 文件,然后再增加那 2 个参数。

选择第 2 个单选按钮,命名方法配置,进入下一步

将上图中的 Local Naming 加到右边空白窗格,最后点 finish。那么,此时在$ORACLE_HOME/network/admin 目录下就会生成 sqlnet.ora 文件。

sqlnet.ora 文件刚创建以后,里面的内容只有下面几行

现在添加 WALLET_LOCATION 和 SQLNET.WALLET_OVERRIDE 这 2 个参数

现在,Oracle 客户端的安全外部密码存储已经配置完毕。

为了简化操作步骤,也可以将操作步骤(1)和(2)合为一步,直接创建 wallet 及其证书,如下图所示:

其中,前两次输入的密码为 wallet 本身的密码,这里输入 Oracle123,后两次输入的密码为用户 szd_base_v2 的密码 ysyktest。 现在,我们尝试去用 base 的连接串去连接 Oracle 数据库,查看其登录用户为 szd_base_v2,这样就达到了不用输密码登录数据库的目的。

那么,用 szd_base_v2 用户去连接 Oracle 数据库,也是一样的效果。

现在我们看一下视图 v$encryption_wallet 的内容有什么变化,

下面是没有使用 Security External Password Store 之前,视图 v$encryption_wallet 的内容(前面在创建 wallet 之前也提到过,呵呵)

通过上面 2 图对比,我们不难发现,Oracle 现在使用了我们刚才创建的 wallet,并且该 wallet 的状态为打开且正在使用。

如果用户 szd_base_v2 的密码进行了更改,也需要把 wallet 里的证书信息进行更改,否则证书里还是存放旧密码的信息,在连接 Oracle 数据库的时 候就会报错。下面将用户 szd_base_v2 的密码改为 ysykbase,再用 sqlplus /@base 登录,看有什么报错。

现在,我们用 mkstore 命令将 wallet 里的证书进行更改,然后再用 sqlplus /@base 登录,就会正常连接。

其中,前两次输入的密码为刚刚更改的用户 szd_base_v2 的密码,第三次输入的密码为 wallet 的密码。

除了用 sqlplus 直接登录 Oracle 数据库以外,在导入导出数据和一些对数据库日常维护的 SHELL 脚本中也可以使用,而且不会暴露明文密码,可以消 除一定的安全隐患。例如,下面的 1 个 expdp 脚本和 1 个 SHELL 脚本。

至此,使用 Oracle 的安全外部密码存储功能实现无密码登录数据库已全部演示完毕。