Good fences make good neighbors.
— Robert Frost, Mending Wall
核心概念#
在第一版中關於程式碼耦合的討論裡,作者大膽但天真地說:「我們不需要像間諜或異議者那樣偏執。」他們錯了。事實上你確實需要那麼偏執——每一天。
新聞中充斥著毀滅性的資料洩露、被劫持的系統和網路詐騙。數億筆記錄被一次竊取,數十億美元的損失——這些數字每年都在快速增長。在絕大多數案例中,不是因為攻擊者特別聰明,而是因為開發者太大意了。
另外的 90%#
當你的程式碼「終於能用了」,你完成了 90%。但現在你還有另外的 90% 要考慮——分析程式碼可能出錯的方式,將這些加入測試套件:傳入錯誤參數、資源洩漏、不可用的資源等。
而且在今天,除了內部錯誤,你還需要考慮外部攻擊者如何故意破壞系統。安全隱藏不等於安全——公開網路上未修補、過時的系統的存活時間以分鐘計。
安全基本原則#
務實的程式設計師有健康的偏執。我們知道自己有缺陷和限制,外部攻擊者會利用我們留下的任何開口。以下是應該永遠牢記的基本原則:
1. 最小化攻擊面#
系統的攻擊面(attack surface)是攻擊者可以進入、提取資料或呼叫服務的所有存取點的總和。
| 攻擊向量 | 說明與對策 |
|---|---|
| 程式碼複雜度 | 簡單、緊湊、少量的程式碼意味著更少的 bug 和更少的安全漏洞 |
| 輸入資料 | 永遠不要信任來自外部實體的資料,在傳遞到資料庫、視圖渲染或其他處理之前必須消毒 |
| 未驗證的服務 | 任何人都可以呼叫,至少會造成阻斷服務攻擊 |
| 已驗證的服務 | 最小化授權使用者數量,清除閒置帳號 |
| 輸出資料 | 不要洩露資訊(如「密碼被其他使用者使用」),截斷或模糊化敏感資訊 |
| 除錯資訊 | 確保「測試窗口」和運行時期異常報告不會外洩 |
Tip 72 - Keep It Simple and Minimize Attack Surfaces(保持簡單,最小化攻擊面)
2. 最小權限原則#
使用你能脫身的最少權限,在最短時間內。不要自動取得最高權限(如 root 或 Administrator)。如果必須使用高權限,完成後立即降回。
每個程式和每個系統的特權使用者都應該使用完成工作所需的最少權限。
— Jerome Saltzer, Communications of the ACM, 1974
這不僅適用於作業系統權限——你的應用程式是否實作了不同的存取層級?考慮更細粒度的權限分類。
3. 安全預設值#
應用程式或網站的預設設定應該是最安全的值。可能不是最方便的,但讓使用者自己決定安全與方便之間的取捨。
4. 加密敏感資料#
不要將個人可識別資訊、財務資料、密碼或其他憑證以明文方式存放——無論是資料庫還是外部檔案。加密提供額外的安全層。
也不要把密鑰、API 金鑰、SSH 金鑰或加密密碼簽入版本控制系統。
5. 維護安全更新#
Tip 73 - Apply Security Patches Quickly(快速套用安全修補程式)
延遲更新是糟糕的主意——你的系統暴露在已知的漏洞中。歷史上最大的資料洩露事件都是因為系統落後更新造成的。這適用於每一個連網裝置:手機、汽車、開發機器、生產伺服器、雲端映像——一切。
常識 vs. 密碼學#
涉及密碼學時,常識可能會誤導你。最重要的規則是:永遠不要自己做加密。即使是簡單如密碼處理,常見做法也往往是錯的。
不要自己實作登入系統——使用第三方認證提供商。這些人整天都在維護系統安全,他們比你更擅長。
相關章節#
- Topic 23,契約式設計
- Topic 24,死程式不會說謊
- Topic 25,斷言式程式設計
- Topic 38,靠巧合寫程式
- Topic 45,需求之坑