背景
資料庫在一個企業中通常都處于非常核心的位置,資料庫安全是一個非常嚴肅的話題。
從機房、網絡、伺服器、資料交換裝置、作業系統、應用程式、資料庫本身,資料庫所處的環境非常複雜,安全隐患也非常多。
是以本文将從各個層面幫助大家了解和避免一些常見的安全隐患問題。
本文是PostgreSQL使用安全指導性的文章,涉及詳細的用法或原理請參考相關連結。
如何安全的使用PostgreSQL,讓使用者高枕無憂呢?
可以分為如下幾個方面來加強你的資料庫。
一、認證安全
認證前的安全,端口暴露度的把握。
《PostgreSQL認證安全》認證是使用資料庫的第一關,如果認證不安全,你的資料庫将很容易被入侵。
1. pg_hba.conf安全
配置合理的pg_hba.conf,将權限控制到最小。
任何情況下都不允許trust認證方法;
超級使用者隻允許從本地連接配接,不允許從網絡連接配接;
将dbname+username+ip限制到最小,"授權使用者"隻能從"授權IP"過來連接配接"授權資料庫";
如果使用資料庫密碼認證,請務必使用md5認證方法,網絡傳輸的密碼是md5+随機字元加密後的密文。
2. 密碼複雜度政策
建立使用者或修改使用者密碼時,強制限制密碼的複雜度,例如密碼長度,包含數字,字母,大小寫,特殊字元等,同時排除暴力破解字典中的字元串。
3. 密碼更換周期
使用合理的密碼更換周期,建立角色時使用VALID UNTIL ‘timestamp',同時限制密碼不能重複使用,
請注意配合監控使用,及時提醒管理者和使用者密碼快到期了。
4. 密碼存儲政策
如果使用資料庫密碼認證,建立角色時請使用encrypted password,這樣pg_shadow.passwd存儲的是密碼+角色名的MD5碼,否則是明文。
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)
pg_log/xxx.csv
堡壘機日志
pg_stat_activity視圖
pg_stat_statements視圖與檔案(與PG版本有關)
通過修改PG資料庫核心,直接避免在審計日志、pg_stat_activity、psql_history、pg_stat_statements中出現明文密碼或MD5碼。
6. 外部表密碼安全
回收pg_user_mappings視圖的public權限,否則mapping使用者可以看到user mapping下的密碼。
7. dblink密碼安全
普通使用者使用dblink時,需要提供連接配接使用者和密碼,不建議使用。如果一定要用,請限制dblink目标使用者在目标資料庫叢集的權限到最小化。
同時開放DBLINK還有一個問題,請參考
《開放dblink , fdw帶來的安全隐患》8. 如果使用外部認證,如AD域,請加強對應的認證服務。
9. 應用程式配置檔案中如果需要配置使用者和密碼,請確定應用程式伺服器的安全。防止配置檔案洩露。
10. 資料庫本身的認證方式加強,但是需要用戶端驅動同時來支援,修改認證協定。
參考
《PostgreSQL psql 安全設定資料庫使用者密碼的方法之一》8. 認證方法的安全(特别是雲服務)
《PostgreSQL md5 對比MySQL - 秘鑰認證》建議使用scram-sha-256機制。
《PostgreSQL 10.0 preview 安全增強- SASL認證方法之scram-sha-256 安全認證機制》認證方法,絕對不要使用可以捕獲密碼明文的認證方法,例如password方法,在認證過程中傳輸的就是明文密碼,而MD5傳輸的是salt以及salt和md5碼加密後的md5碼。
二、資料傳輸安全
確定資料傳輸過程的安全,即使資料被截獲,也不需要擔心。
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 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 usage on schema sch_name to approle;
1.5 将應用需要通路的對象的相關權限賦予給應用賬号。
這樣,應用賬号隻有對象的使用權限,沒有對象的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 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》2. 防止SQL注入
應用層應該有SQL注入預防手段,例如使用簡單的過濾器,使用綁定變量等手段。
3. 密碼暴力破解
目前可以通過密碼錯誤延遲認證(auth_delay)來增加暴力破解需要的時間。
《PostgreSQL密碼安全指南》4. 防止普通使用者通過函數調用陷阱進行攻擊
《PostgreSQL安全陷阱- 利用觸發器或規則,結合security invoker函數制造反噬陷阱》5.
《Hacking PostgreSQL》6. 防止惡意占用連接配接,即使攻擊者沒有密碼,也能占用SERVER SLOT,即攻擊者連接配接資料庫時,在提示輸入密碼的階段不響應,這個SOLT會被占用,相當于消耗資料庫的一個連接配接。
通過如下參數,可以控制認證過程的時間,但是無法防止惡意的攻擊,因為逾時後攻擊者又可以發起連接配接。
https://www.postgresql.org/docs/9.6/static/runtime-config-connection.html#RUNTIME-CONFIG-CONNECTION-SECURITYMaximum time to complete client authentication, in seconds.
If a would-be client has not completed the authentication protocol in this much time, the server closes the connection.
This prevents hung clients from occupying a connection indefinitely.
The default is one minute (1m). This parameter can only be set in the postgresql.conf file or on the server command line.
是以不要随機的暴露端口。
7. 通過端口嘗試CANCEL使用者QUERY。
《PostgreSQL cancel 安全漏洞》六、備份,容災,恢複測試
再好的安全政策,也需要備份。
基于時間點的,塊級别增量備份,是比較靠譜的。(你可以選擇合适的檔案系統,例如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,如果需要使用的話,也可以更新到大的版本,但是請注意與應用有關的修改,子產品的更新等。
除了資料庫的更新檔,還需要更新作業系統的更新檔,例如之前就有過這樣的問題:OPENSSL的版本問題,低版本可能有漏洞,需要更新到新版本。
九、外界環境安全
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資料庫開發規範》安全合規通常關注哪些點?
1、認證:
· 密碼複雜度
· 修改密碼不可與最近若幹次重複
· 密碼到期修改政策
· 密碼重複錯誤超出次數鎖定
· 密碼錯誤後延遲認證
2、鍊路
· 鍊路加密
· 資料庫防火牆
· 空閑會話逾時
3、資料
· 資料存儲加密
· 資料加密類型
· tde
· wal日志存儲加密
4、審計
· sql審計存儲加密
· sql審計,存儲時長可配置,可下載下傳
· GUI、openapi審計
· 關閉審計的行為被審計
5、容災、備份
· 跨機房、跨地域容災
· 跨機房、跨地域備份
6、外部通路
· 外部通路鍊路加密(dblink, fdw)
· 外部通路認證賬号資訊加密存儲(mapping , dblink , view)
7、鑒權
· 資料庫權限體系、
· GUI權限體系、
· openapi調用權限體系
8、加密算法強度
9、監控、告警
· 錯誤監控
· 性能監控
· 錯誤告警、不可用告警、性能告警
10、授權
- 第三方排錯授權