又來勒索,有完沒完-資料庫安全指南

德哥發表於2017-03-02

背景

資料庫在一個企業中通常都處於非常核心的位置,資料庫安全是一個非常嚴肅的話題。

從機房、網路、伺服器、資料交換裝置、作業系統、應用程式、資料庫本身,資料庫所處的環境非常複雜,安全隱患也非常多。

所以本文將從各個層面幫助大家理解和避免一些常見的安全隱患問題。

本文是PostgreSQL使用安全指導性的文章,涉及詳細的用法或原理請參考相關連結。

如何安全的使用PostgreSQL,讓使用者高枕無憂呢?

可以分為如下幾個方面來加固你的資料庫。

一、認證安全

認證前的安全,埠暴露度的把握。

PostgreSQL 認證安全

認證是使用資料庫的第一關,如果認證不安全,你的資料庫將很容易被入侵。

1. pg_hba.conf安全

配置合理的pg_hba.conf,將許可權控制到最小。

任何情況下都不允許trust認證方法;

超級使用者只允許從本地連線,不允許從網路連線;

將dbname+username+ip限制到最小,”授權使用者”只能從”授權IP”過來連線”授權資料庫”;

如果使用資料庫密碼認證,請務必使用md5認證方法,網路傳輸的密碼是md5+隨機字元加密後的密文。

2. 密碼複雜度策略

建立使用者或修改使用者密碼時,強制限制密碼的複雜度,例如密碼長度,包含數字,字母,大小寫,特殊字元等,同時排除暴力破解字典中的字串。

PostgreSQL 認證安全

3. 密碼更換週期

使用合理的密碼更換週期,建立角色時使用VALID UNTIL ‘timestamp`,同時限制密碼不能重複使用,

請注意配合監控使用,及時提醒管理員和使用者密碼快到期了。

4. 密碼儲存策略

如果使用資料庫密碼認證,建立角色時請使用encrypted password,這樣pg_shadow.passwd儲存的是密碼+角色名的MD5碼,否則是明文。

postgres=# create role r_test unencrypted password `hello123` login;  
postgres=# select usename,passwd from pg_shadow where usename=`r_test`;  
 usename |  passwd    
---------+----------  
 r_test  | hello123  
(1 row)  

postgres=# alter role r_test encrypted password `hello123`;  
ALTER ROLE  
postgres=# select usename,passwd from pg_shadow where usename=`r_test`;  
 usename |               passwd                  
---------+-------------------------------------  
 r_test  | md5bb0d7bef45a0530ac529e7b43943a2d1  
(1 row)  

postgres=# select md5(`hello123r_test`);  
               md5                  
----------------------------------  
 bb0d7bef45a0530ac529e7b43943a2d1  
(1 row)  

5. 設定密碼時防止密碼被記錄到資料庫日誌,history,審計日誌,pg_stat_activity, pg_stat_statements中.

(例如使用了readline, 堡壘機, 或者開啟了log_statement)

  ~/.psql_history  
  pg_log/xxx.csv  
  堡壘機日誌  
  pg_stat_activity檢視  
  pg_stat_statements檢視與檔案(與PG版本有關)  

6. 外部表密碼安全

回收pg_user_mappings檢視的public許可權,否則mapping使用者可以看到user mapping下的密碼。

revoke all on view pg_user_mapings from public;    

7. dblink密碼安全

普通使用者使用dblink時,需要提供連線使用者和密碼,不建議使用。如果一定要用,請限制dblink目標使用者在目標資料庫叢集的許可權到最小化。

同時開放DBLINK還有一個問題,請參考

《開放dblink , fdw帶來的安全隱患》

8. 如果使用外部認證,如AD域,請加固對應的認證服務。

9. 應用程式配置檔案中如果需要配置使用者和密碼,請確保應用程式伺服器的安全。防止配置檔案洩露。

10. 資料庫本身的認證方式加固,但是需要客戶端驅動同時來支援,修改認證協議。

參考

《PostgreSQL psql 安全設定資料庫使用者密碼的方法之一》

二、資料傳輸安全

確保資料傳輸過程的安全,即使資料被截獲,也不需要擔心。

1. 資料傳輸加密

如果你的網路是不可靠的,請使用加密傳輸,例如OPENSSL。

參考,

《PostgreSQL 如何實現網路壓縮傳輸或加密傳輸(openssl)》

2. 認證過程加密

認證過程加密,指認證過程中,網路上傳輸的密碼安全,如果使用資料庫認證,請使用MD5方法(配置pg_hba.conf)。確保網路中傳輸的是隨機碼和MD5加密後的MD5。

但是請注意,MD5也不能洩露,洩露是危險的,可以參考以下文件使用MD5進行認證

《PostgreSQL 對比 MySQL – 祕鑰認證》

三、資料安全

你的資料安全嗎?如果你儲存的敏感資料在資料庫中是明文的,一旦資料庫暴露,使用者資料可能洩露,如何儘可能的保證洩露的資料的安全呢?

1. 欄位儲存加密

將敏感資料加密後儲存在資料庫中,即使加密資料洩露,只要加解密方法沒有洩露,也是相對安全的。

加解密方法建議放在應用端實現,如果加解密在資料庫端實現,使用者一旦入侵資料庫,更容易破解。(或者加密在資料庫端實現,解密在應用程式端實現)

《固若金湯 – PostgreSQL pgcrypto加密外掛》

2. 敏感資料,跟蹤並記錄DML,truncate操作的undo

對於非常敏感的資料,我們應該記錄對這些資料操作的UNDO,在必要時刻可以快速的回滾到誤操作前。

這種方法主要是對付SQL隱碼攻擊,人為誤操作(包括delete,update,insert,truncate的回滾)。

請參考,

《PostgreSQL 閃回 – flash back query emulate by trigger》

3. 函式程式碼加密

如果我們將業務邏輯放在資料庫函式中處理的話,肯定不想讓使用者看到函式的內容。

對於先編譯後執行的函式,例如C函式,是不需要加密的,但是,對於解釋性語言函式如plpgsql,建議加密函式的內容。

目前enterprisedb有這個特性,社群版本的PostgreSQL沒有這個特性。

請參考,

《PostgreSQL 函式封裝 – Wrap Function code like Oracle package》

http://www.cybertec.at/en/products/plpgsql_sec-encrypt-your-stored-procedure-codes/

如果不能加密,至少需要控制普通使用者不能檢視函式內容。

《PostgreSQL 函式程式碼隱藏 – How to control who can see PostgreSQL function`s source code》

4. 使用recycle bin外掛,使用者在刪物件時,物件會儲存在recycle bin schema下,而不會被真實刪除。那麼表被誤刪除或惡意刪除後,很容易找回。(使用鉤子實現)

請參考,

《PostgreSQL 回收站功能 – 基於HOOK的recycle bin pgtrashcan》

5. 透明加密,防止資料檔案被拖走後,洩露資料。

手段包括型別透明加密(TDE),檔案透明加密(FDE)

參考

《PostgreSQL 透明加密(TDE,FDE) – 塊級加密》

四、許可權控制

1. 許可權管理

最危險的就是最容易暴露的資料庫使用者,當然是應用連線資料庫的賬號(以下簡稱應用賬號)。

應用賬號許可權越大,應用程式被攻擊後破壞性就越大。

例如使用者有刪資料庫,刪表,刪索引,刪表空間,刪SCHEMA,刪函式等等這樣的許可權的話,危害極大。

安全建議:

1.1 使用超級使用者建立資料庫,SCHEMA,應用所需的物件(如表,索引,函式)。

1.2 建立應用賬號角色。

1.3 回收資料庫,schema,language,應用物件的public許可權。

    revoke all on database dbname from public;   
    revoke all on schema sch_name from public;   
    revoke all on language plpgsql from public;   
    revoke all on table ... from public;  
    revoke all on function ... from public;  
    ......  

1.4 將資料庫,schema的使用許可權賦予給應用賬號。

    grant connect on database dbname to approle;  
    grant usage on schema sch_name to approle;  

1.5 將應用需要訪問的物件的相關許可權賦予給應用賬號。

    例如表的select,insert,update,delete許可權, 函式的execute許可權等.  

這樣,應用賬號只有物件的使用許可權,沒有物件的DROP,TRUNCATE,REPLACE許可權,相對來說是更安全的。

2. 通過事件觸發器禁止應用賬號執行DDL,通過這種方法可以限制使用者執行DDL,防止被攻擊後,使用者執行DROP或TRUNCATE刪除物件或清空資料 (當然delete不帶條件還是能刪除資料的,需要用其他手段)。

請參考,

《PostgreSQL 事件觸發器 – PostgreSQL 9.3 Event Trigger》

3. 防止執行不帶條件的delete,update。

例如,在需要保護的表裡,新增一條dummy記錄,建立行觸發器,當這條記錄被更新或刪除時,丟擲異常。

對於業務上不允許執行刪除操作的表,不要賦予該表的delete許可權給應用賬號,也就不會有這個風險。

4. 函式語言安全

建議回收函式語言的public許可權,以及普通使用者的許可權,使用者不能建立函式。執行online code。

例如:

revoke all on language plpgsql from public;  
revoke all on language plpgsql from app_role;  

5. 行級安全策略

限制普通使用者只能操作表中的指定條件的記錄,用於rewriter改寫重寫規則,普通使用者只能訪問滿足指定條件的行。

請參考,

《PostgreSQL 行安全策略 – PostgreSQL 9.5 new feature – can define row security policy for table》

6. 對於只需要訪問某些行,或某些列的需求,可以通過列許可權或檢視來限制應用賬號的許可權。

五、防惡意攻擊

1. 檢視攻擊

使用者利用PostgreSQL的優化器原理,建立成本極低的函式,在函式中獲取檢視限制外的隱藏內容。

如果使用者沒有建立函式的許可權,使用者就無法利用這個原理。

或者使用安全柵欄來彌補。

請參考,

《PostgreSQL views privilege attack and security with security_barrier(檢視攻擊)》

《PostgreSQL leakproof function in rule rewrite(“attack” security_barrier views)》

或者使用基於安全策略來管理資料可見性。

《PostgreSQL 9.4 patch : Row-Level Security》

《PostgreSQL 行安全策略 – PostgreSQL 9.5 new feature – can define row security policy for table》

2. 防止SQL隱碼攻擊

應用層應該有SQL隱碼攻擊預防手段,例如使用簡單的過濾器,使用繫結變數等手段。

3. 密碼暴力破解

目前可以通過密碼錯誤延遲認證(auth_delay)來增加暴力破解需要的時間。

請參考,

《PostgreSQL 密碼安全指南》

4. 防止普通使用者通過函式呼叫陷阱進行攻擊

《PostgreSQL 安全陷阱 – 利用觸發器或規則,結合security invoker函式製造反噬陷阱》

5. 《Hacking PostgreSQL》

六、備份,容災,恢復測試

再好的安全策略,也需要備份。

基於時間點的,塊級別增量備份,是比較靠譜的。(你可以選擇合適的檔案系統,例如btrfs)

請參考,

《PostgreSQL 最佳實踐 – 塊級增量備份(ZFS篇)方案與實戰》

《PostgreSQL 最佳實踐 – 塊級增量備份(ZFS篇)驗證 – recovery test script for zfs snapshot clone + postgresql stream replication + archive》

另外PostgreSQL的每個資料塊中都有LSN編號,使用這個也能實現塊級別的增量備份,參考

《PostgreSQL 最佳實踐 – 塊級別增量備份(pg_rman baseon LSN)原始碼淺析與使用》

《PostgreSQL 最佳實踐 – pg_rman 以standby為源的備份淺析》

《PostgreSQL 最佳實踐 – pg_rman 資料庫恢復示例 與 軟體限制解說》

七、審計

審計功能,一般是用於排查問題的,當然也是一種舉證的手段,例如你的資料庫遭到暴力破壞了,證據非常重要。

這裡有一些例子:

如何跟蹤postgresql.conf的配置變更?

worker process鉤子程式的妙用.

《PostgreSQL 配置檔案變更審計 – A custom background worker process to log changes to postgresql.conf to a table》

如何跟蹤表中的記錄被哪個使用者修改或插入?

《PostgreSQL 跟蹤誰動了你的記錄 – Use insert_username Tracking Who Changed a Table》

使用pg_log_userqueries外掛, 審計指定使用者,資料庫或超級使用者的所有執行的SQL.

《PostgreSQL 靈活審計外掛 – PostgreSQL per database or per user audit use pg_log_userqueries》

使用hstore外掛和觸發器跟蹤表的行記錄變更.

《USE hstore store table`s trace record》

PostgreSQL中如何跟蹤表的建立時間, 表定義的修改時間

《PostgreSQL 跟蹤DDL時間 – cann`t use pg_class`s trigger trace user_table`s create,modify,delete Time》

PostgreSQL 精細化審計的實施.

1. 審計指定表的INSERT, UPDATE, DELETE, TRUNCATE

2. 審計指定使用者對指定表的INSERT, UPDATE, DELETE, TRUNCATE

3. 審計指定表的指定資料的INSERT, UPDATE, DELETE

4. 如何讓資料庫只審計成功提交的資料, 而不記錄回滾事務.

《PostgreSQL 審計成功事務 – PostgreSQL Fine-Grained Table,Column,Row Level Audit》

PostgreSQL 審計功能配置

《PostgreSQL 審計 – PostgreSQL Audit by Database or Role wide parameter》

PostgreSQL 9.3 規則系統改進, 允許在規則的values中使用多次NEW, OLD.

使用規則跟蹤資料變更, 記錄新老資料.

《PostgreSQL 審計 – PostgreSQL 9.3 Allow OLD and NEW in multi-row VALUES within rules》

如何跟蹤基於欄位值為條件的行的變更,插入和刪除呢?

建立觸發器時when的用法, 或在觸發器函式中處理. 選擇效率高的.

《PostgreSQL 觸發器應用 – (觸發器WHEN)前置條件過濾跟蹤目標記錄》

PostgreSQL資料庫在上市公司重要應用中的SOX審計

《PostgreSQL資料庫在上市公司重要應用中的SOX審計》

審計表的DDL行為, 以及哪個會話在什麼時間點,通過什麼IP乾的.

《PostgreSQL 事件觸發器 – DDL審計 , DDL邏輯複製 , 打造DDL統一管理入》

審計變更的行, 以及被變更的欄位內容; 新增的行, 刪除的行; 以及哪個會話在什麼時間點,通過什麼IP乾的.

《PostgreSQL 觸發器應用 – use trigger audit record which column modified, insert, delete.》

pg_audit模組

《PostgreSQL 審計 – pg_audit module》

八、補丁

PostgreSQL社群的更新速度很快,幾乎每天都會有commit,有些可能是FIX patch,有些可能是feature,有些可能是效能提升patch,

正常情況下,我們只要跟隨小版本的升級就可以了,一般社群遇到比較大的安全漏洞,提交補丁後馬上就會發布小版本,如果沒有釋出小版本,

說明沒有大的安全漏洞,你可以通過 http://git.postgresql.org 實時跟蹤社群的動態,自行打patch。

大版本的更新,通常情況下大版本有大量的feature,如果需要使用的話,也可以更新到大的版本,但是請注意與應用有關的修改,模組的更新等。

九、外界環境安全

1. 應用程式是否安全?

2. 中介軟體是否安全?

3. 資料庫所在作業系統是否安全?

4. 資料庫所在伺服器是否安全?

5. 儲存安全,儲存是否在安全的地方,有沒有硬碟被拔掉的風險?

6. 網路安全,如機架交換機,未插網線的埠是否禁用了,是否做了MAC地址過濾或繫結?

7. 機房安全?

十、資源控制

雖然我們前面已經控制的挺好了,但是資料庫還有一種風險和網路的DDOS攻擊類似,大量的使用者請求可以把資料庫搞慢。

或者大量的運算量或者IO極大的請求,也很容易把資料庫搞慢。

資源控制手段舉例:

控制連線數,控制活動連線數,控制SQL執行時間,控制鎖等待時間,控制事務空閒時間。

另一方面,因為PostgreSQL的併發控制用到了多版本,所以當更新或刪除資料時,老的版本依舊存在於資料庫中,需要vacuum程式回收這些資料,

目前有一個缺陷,當有長事務存在時,事務開啟後產生的垃圾被視為新的垃圾,不會被回收,所以長事務容易導致資料庫膨脹,太長的事務甚至可以導致資料庫的xid耗盡,必須關機做vacuum freeze。

請參考,

《PostgreSQL垃圾回收程式碼分析 – why postgresql cann`t reclaim tuple is HEAPTUPLE_RECENTLY_DEAD》

十一、監控

監控是DBA的眼睛,好的監控可以提前發現問題,將問題排除在發生之前。

參考(zabbix, nagios)

常用監控項請參考,

《PostgreSQL nagios monitor script (archive, vacuum, age, conn, rollback, standby, lock, xact, seq, index…)》

巡檢參考

《PostgreSQL AWR報告》

https://raw.githubusercontent.com/digoal/pgsql_admin_script/master/generate_report.sh

十二、開發規約

《PostgreSQL 資料庫開發規範》


相關文章