防拖庫的最佳實踐
“拖庫”,就是資料庫被黑客整個拖下來。臉紅的說,這個事射手也遇到過。
我信奉不能被同樣的招數打敗兩次。所以最近再做專案時,我又仔細研究了一下,如何防止開發人員把資料庫密碼寫在程式碼中,以免資料被拖庫的方案。
先分析華住的拖庫事件,這類安全風險背後的關鍵因素主要來自:
- 開發人員需要在開發過程中進行測試,這些測試會需要連線資料庫
- 開發人員會有連線到生產資料庫進行除錯的需求
- 使用的版本管理工具,會將所有程式碼歷史修改都記錄並保留
與上述因素相對應的,在傳統開發模式下,產生的安全滲透點就會很多:
- 當開發人員需要除錯資料庫時,會將資料庫密碼寫入程式碼,甚至生產環境也是這樣
- 特別是在 PHP 這類很方便修改的指令碼語言中,線上修改生產環境的程式碼,是一些團隊的常見行為
- 當開發人員除錯過程中使用版本管理工具提交,就會將各種密碼在程式碼倉庫中記錄下來。而這些記錄在以 Git 為代表的分散式程式碼倉庫中,不會消失
在這種傳統的開發模式下,唯一的技術性安全措施,只能是通過資料倉儲私有化,來保護程式碼和程式碼中的密碼祕鑰。
但是,墨菲定律說,如果一件事有可能會發生,就一定會發生。我們很難保證在每臺個人開發裝置上都留存了副本的分散式程式碼倉庫永遠不會被洩露。所以,將資料庫等密碼寫在程式碼中,是不可取且安全風險極大的。
近代的開發模式,會通過配置檔案儲存資料庫密碼到配置檔案,再利用 .gitignore 將配置檔案排除在程式碼倉庫之外,避免開發人員將含有密碼的配置檔案提交到程式碼倉庫。
但是,這種模式也有它的問題:
- 開發人員還是可以輕易拿到資料庫密碼
- 密碼以檔案形式儲存在本地和伺服器
- 結構上仍很難避免開發人員將資料庫密碼直接寫到程式碼中以方便除錯
- 如果配置檔案排除在程式碼倉庫管理之外,那麼配置檔案的格式升級,就比較難管理。如果有配置檔案沒被排除在程式碼倉庫之外,那麼安全風險接近將密碼寫入程式碼
而且,現代開發方法中倡導CI/CD(持續整合/持續部署),也會帶來一些不盡方便的地方:
- 配置檔案需要另外設法更新到 CI/CD 配置中
- 配置檔案的修改依賴額外的工作人員管理
- 一些運維人員會習慣性將配置檔案也納入版本管理
開發流程中的祕鑰安全管理就此崩塌。
還有一種方案,是使用環境變數來儲存祕鑰的。這種管理方法,因為敏感密碼不以檔案形式存在,所以安全性略好。但是這也有問題:
- 環境變數對整個操作環境暴露,如果 CI 或生產環境被入侵,獲得祕鑰的門檻很低
- 沒有操作記錄,無法追溯
- 如果專案比較大,涉及多種資料庫密碼、祕鑰,API憑據等等。使用眾多環境變數會變得很難管理
況且,現在的大型專案,不光是資料庫密碼,還有 OSS/S3 祕鑰,各種 API 憑據 Token,TLS證照、公鑰、私鑰等等。對於傳統專案的安全管理挑戰非常大。
那麼,現在已經2018年了,什麼才是開發流程安全的最佳實踐? 正好最近借重寫射手 API 服務端的機會,對一些新方案仔細調研了一番。
先說結論:現代開發專案應該啟用某種專業化的祕鑰管理系統(secret management solution),包括 AWS 的 KMS,谷歌的Cloud KMS,HashiCorp 的 Vault,K8S 的 Secret,swarm 的 secret 等等都可以。不過在這些選擇中,我個人目前會更推薦使用 HashiCorp 的 Vault 。
祕鑰管理服務和 Vault 的優點:
- 祕鑰管理服務簡單的說,可以看做後端領域的 1Password。首先它會保證祕鑰儲存安全。不管用哪個黑客,拿到祕鑰管理服務的落地資料檔案,在沒有祕鑰的情況下還是不可能解密的。以 Vault 為例,一個 Vault 系統啟動時,要使用 5 個 root token 中的至少 3 個對資料進行 Unseal,之後 Vault 才能將祕鑰從儲存層解密出來提供專案使用
- 另外從 Vault 獲取之前配置的密碼、祕鑰等關鍵資料,會需要由管理員分配 Token,對這些分配的 Token,管理員可以制定包括過期、撤銷、更新和許可權管理等等各種安全策略
- Vault 的安全級別可以提供面向公網開放的服務,所以可以為開發環境提供一個開發人員的 Vault ,在家或者異地開發也可以很方便
- 管理員可以隨時通過 Vault 更新各個資料服務的安全密碼或金鑰,也可以隨時收回或修改特定 Token 的許可權。這在 Rolling out 更新時很有用
- 使用 Vault 會強制程式碼通過 Vault 介面來獲取各種資料連線密碼或祕鑰。避免開發人員無意獲得和在程式碼中使用祕鑰密碼。而且因為 Vault 的管理方式允許,雖然程式碼只有一份,我們還是可以將不同開發階段的 Vault 分別管理。甚至可以做到生產環境中只有 1 人有 Vault 管理許可權,也不會覺得維護起來很吃力
- 所有祕鑰存取和修改都有日誌記錄。可以作為事後證據成為被入侵的線索
- 資料庫和API祕鑰不再散落在程式碼各處
- Vault 服務如果部署正確,可以實現高可用 (HA)
使用祕鑰管理方案,為開發帶來一個極大的好處。就是專案程式碼中就只剩一個 Token 是安全敏感的,只要內部開發人員不是懷有惡意的話,是不會接觸到密碼或祕鑰等敏感資訊。而這一個 Token 又是可以定時過期和更換的。這樣即使 Token 被洩露,也可以做到讓黑客沒有足夠的時間拖庫。
相關文章
- 微服務的【資料庫管理】最佳實踐微服務資料庫
- 封裝 uniapp 請求庫的最佳實踐封裝APP
- PHP最佳實踐之資料庫PHP資料庫
- 團隊開發中 Git 最佳實踐,不給隊友拖後腿Git
- Java異常處理最佳實踐及陷阱防範Java
- 資料庫設計的十個最佳實踐資料庫
- 【乾貨】分庫分表最佳實踐
- 資料庫安全最佳實踐:基本指南資料庫
- mysqldump的最佳實踐MySql
- RocketMQ的最佳實踐MQ
- Android 中的升級資料庫最佳方法實踐Android資料庫
- 關於訂單庫存扣減的最佳實踐
- 企業級雲資料庫最佳實踐資料庫
- 漫談 React 元件庫開發(二):元件庫最佳實踐React元件
- 標籤的最佳實踐
- Eggjs 的 Controller 最佳實踐JSController
- swoft 假的最佳實踐
- 拖庫有什麼危害?如何有效防止拖庫?
- TiDB 異構資料庫複製最佳實踐TiDB資料庫
- 客戶服務知識庫最佳實踐指南
- 資料庫伺服器運維最佳實踐資料庫伺服器運維
- AutoMapper 最佳實踐APP
- 《.NET最佳實踐》
- Django 最佳實踐Django
- metaq最佳實踐
- springDataJpa 最佳實踐Spring
- KeyPath 最佳實踐
- Pika最佳實踐
- JavaScript 最佳實踐JavaScript
- SnapKit 最佳實踐APK
- JDBC 最佳實踐JDBC
- Kafka最佳實踐Kafka
- Iptables 最佳實踐 !
- Serilog 最佳實踐
- Flutter 最佳實踐Flutter
- Java最佳實踐Java
- MongoDB 最佳實踐MongoDB
- Gradle最佳實踐Gradle