使用 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 的安全外部密碼儲存功能實現無密碼登入資料庫已全部演示完畢。