在應用程式開發中,「秘密 (Secret)」是指任何用於身份驗證或授權的敏感資訊,例如密碼、API 金鑰、加密金鑰等。若對這些秘密的保護不足,將會對系統安全造成毀滅性的打擊。本文將探討兩種最常見的憑證保護漏洞:硬編碼秘密與使用弱密碼雜湊。
風險一:硬編碼秘密 (Hardcoded Secrets)
什麼是硬編碼秘密?
硬編碼是指將密碼、API 金鑰等敏感資訊,直接以明文或易於還原的格式(如 Base64)寫死在原始碼、設定檔或二進位檔案中。
為何危險?
- 原始碼洩漏即秘密洩漏:一旦原始碼(例如透過 Git 倉庫權限設定不當)被洩漏,所有硬編碼的秘密將一覽無遺。
- 版本控制的永久記錄:即使您在後來的版本中移除了硬編碼的秘密,它們仍可能永久地存在於 Git 的歷史紀錄中。
- 逆向工程風險:即使是編譯後的二進位檔案,也可以透過逆向工程被反編譯,從而提取出其中的秘密。
風險二:使用弱密碼雜湊演算法
當儲存使用者密碼時,絕不能以明文儲存,必須經過「雜湊 (Hashing)」處理。但如果使用了過時或本身不安全的雜湊演算法,攻擊者在竊取到雜湊值後,仍能輕易地還原出原始密碼。
常見的弱雜湊演算法:
- MD5 / SHA-1:這兩種演算法已被證明存在嚴重的碰撞 (Collision) 漏洞,可以被輕易破解。彩虹表 (Rainbow Table) 攻擊對其尤其有效。
- 無鹽雜湊 (Unsalted Hash):即使使用像 SHA-256 這樣的演算法,如果沒有為每個密碼添加一個獨一無二的「鹽 (Salt)」,攻擊者仍然可以使用預先計算好的彩虹表進行快速破解。
程式碼範例 (Django)
錯誤的程式碼:
在 Django 設定中,指定了無鹽的 MD5 作為密碼雜湊器。
1 | # 錯誤範例:使用極度不安全的 Unsalted MD5 |
問題分析:
MD5 本身就是一個過時且不安全的演算法。UnsaltedMD5PasswordHasher
更是雪上加霜,它不使用鹽值,使得密碼雜湊極易受到彩虹表攻擊。如果資料庫中的密碼雜湊值外洩,攻擊者可以秒速破解大量使用者的密碼。
防禦與預防措施
針對硬編碼秘密:
- 使用秘密管理器:採用如 HashiCorp Vault, AWS Secrets Manager, Azure Key Vault 等工具,集中、安全地管理所有秘密。應用程式在執行時動態地從管理器中獲取憑證。
- 使用環境變數:將秘密儲存在環境變數中,是將設定與程式碼分離的標準做法。
- 整合 CI/CD 安全掃描:在 CI/CD 流程中整合靜態程式碼分析 (SAST) 工具,自動掃描並警告任何意外提交的硬編碼秘密。
- 無密碼身份驗證:在可行的情況下(如雲端服務間的溝通),利用雲端供應商提供的無密碼身份驗證機制(如 IAM Roles),從根本上消除管理金鑰的需求。
針對密碼儲存:
- 使用強大的密碼雜湊演算法:
- 首選:Argon2 (2015 年密碼雜湊競賽的冠軍)。
- 備選:PBKDF2 或 bcrypt。這些演算法都內建了加鹽機制,並可以調整計算成本(迭代次數),有效抵禦暴力破解。
- 確保自動加鹽:現代的密碼雜湊函式庫通常會自動為每個密碼生成並儲存一個唯一的鹽值,開發者應確保此功能已啟用。
修正後的程式碼範例 (Django)
1 | # 正確範例:使用強大且預設加鹽的 PBKDF2 |
在此解決方案中,使用了具備動態加鹽功能的強密碼雜湊演算法 PBKDF2PasswordHasher
,能有效保護使用者密碼的安全。
說些什麼吧!