1. 模式
1.1. 模式分類
-
1.1.1. 設計屬性
-
1.1.2. 暴露最少資訊
-
1.1.3. 冗餘
-
1.1.4. 強力執行
-
1.1.5. 信任與責任
-
1.1.6. 反模式
1.2. 模式可以緩解或者避免很多種類的風險,它們可以形成一個重要的工具箱,幫我們解決潛在的安全威脅
1.3. 不需要為了解決一個問題就把所有設計模式全都使用一遍
-
1.3.1. 如果所有模式都可以使用,就從中選擇最好的一兩種
-
1.3.2. 對於關鍵的安全需求也可以多使用幾種模式
-
1.3.3. 過度使用這些模式反而會帶來反效果
-
1.3.4. 增加複雜性和開銷所造成的損失很快就會超過額外增加的安全性
2. 設計屬性
2.1. 極簡設計
-
2.1.1. 保持簡單
-
2.1.2. 設計方案應該儘可能簡單
-
2.1.3. 極簡設計提高了安全標準,因為設計方案越是簡單,出現錯誤的可能性就越小,沒有檢測出來的漏洞自然也就越少
-
2.1.4. 所有特殊的設計都有可能要求我們有大量備用元件,技術層面的挑戰也更艱鉅
-
2.1.5. 將功能分解成更小的、獨立的元件,讓它們共同執行復雜的操作
-
2.1.6. 極簡設計並沒有強制規定所有元素必須永遠是最簡單的
-
2.1.7. 簡單性給系統帶來的巨大優勢,強調我們只有在複雜性可以帶來巨大價值的情況下才應該擁抱“複雜”
-
2.1.7.1. 各類Linux平臺的許可權更簡單,也更容易正確地使用
-
2.1.8. 並不是說越簡單的方法就一定越好,或者越複雜的方法就一定存在越多的問題
2.2. 透明設計
-
2.2.1. 你不應有所隱瞞
-
2.2.2. 強大的保護方案永遠不應該靠隱瞞資訊來實現
-
2.2.2.1. 透明設計(而不是完全透明)
-
2.2.3. 我們應該把它的強大展現在人們面前,從而起到阻嚇攻擊者的效果,讓攻擊者更不容易入侵這個系統
-
2.2.4. 對於透明設計對應的反模式,知道的人更多,即透過隱匿資訊來實現的安全(security by obscurity,隱晦式安全)
-
2.2.5. 這種模式反對依靠設計中的機密資訊來提升系統的安全性
-
2.2.5.1. 不是說我們必須公開披露設計方案的資訊,也不是說隱藏資訊有什麼不對
-
2.2.6. 如果把設計方案徹底公開,這個設計方案的安全性就會降低,就說明這個設計方案應該進行改進,而不是依賴那些沒有公開的部分來保持系統的安全性
-
2.2.7. 透過隱秘來實現的安全之所以不靠譜,是因為雖然這種方式也可以暫時讓對手知難而退,但這種機制非常脆弱
-
2.2.8. 應該努力建立起一套穩固的安全機制,確保無論設計方案的具體資訊是否公開,這個設計方案都沒有什麼需要刻意隱瞞的
3. 暴露最少資訊
3.1. err on the safe side
- 3.1.1. 這是所有模式組別中模式數量最多的一組,也需要我們格外注意
3.2. 最小許可權
-
3.2.1. 只給予剛好能夠完成工作的許可權,這就是最安全的做法
-
3.2.2. 永遠不要擦一把上膛的槍
-
3.2.3. 在給電鋸更換刀片的時候一定要拔掉電源
-
3.2.4. 最小許可權模式的案例
-
3.2.5. 這種模式的目的就是在執行任務時降低犯錯造成的風險
-
3.2.6. 也是重要系統的管理員不應該在工作中隨便瀏覽網際網路的原因
-
3.2.6.1. 任何一位稱職的管理員都不會輸入sudo再加上命令來意外破壞這個系統
-
3.2.7. 火警警報控制開關上面那一層寫著“在緊急情況下打破玻璃”的玻璃
-
3.2.7.1. 這層玻璃的存在,沒有人可以說自己是無意拉響了火警警報
-
3.2.8. 哪怕攻擊者利用了漏洞,我們也希望他們獲取到的許可權越小越好
-
3.2.9. 只有在確有必要的情況下,才應該使用那些擁有全部許可權的授權(比如超級使用者許可權),而且應該把使用這類許可權的時間視窗減到最小
-
3.2.10. 正確地使用許可權肯定更加安全
-
3.2.10.1. 即使漏洞被攻擊者利用,也可以分成輕微的入侵和整個系統遭到入侵
-
3.2.10.2. 採用最小許可權也可以減少因軟體錯誤或者人為失誤所造成的破壞
-
3.2.11. 最小許可權並不意味著系統永遠都應該賦予使用者最低程度的授權
-
3.2.11.1. 需要控制授權機制的粒度,同時控制調整許可權所產生的成本
-
3.2.11.2. 程式碼應該儘可能在比較低的許可權下執行,只有在必要的情況下才在自然決策點轉換到比較高的許可權
3.3. 最少資訊
-
3.3.1. 任何情況下,我們都應該收集和訪問儘可能少的、完成工作必不可少的個人資訊
-
3.3.2. 最少資訊模式(相當於資料隱私方面的最小許可權模式)可以幫我們把資訊洩露的風險降到最低
-
3.3.2.1. 應該避擴音供不必要的個人資訊,一有機會就減少不必要的資訊流
-
3.3.3. 很多時候,軟體都不滿足這種模式,因為隨著時間的推進,介面設計就會服務於越來越多的目的
-
3.3.4. 在實施層面,最少資訊設計方案也包括清除本地快取的資訊(在這些資訊已經不需要的情況下),只在系統中顯示可用資料的一部分資訊,並只在使用者明確發出請求的情況下才顯示資訊的詳情
-
3.3.4.1. 顯示密碼的一般做法就是把密碼顯示成星號(*),這樣可以降低有人在身邊窺探密碼的風險
-
3.3.5. 可以讓主叫方指定他們需要的資訊,同時也只提供他們指定的欄位,這就可以把私有資訊的資料流減到最低限度
3.4. 預設防禦
-
3.4.1. 軟體永遠應該是“開箱即用”的安全軟體
-
3.4.2. 在設計軟體時,應該堅持預設防禦原則(包括其初始狀態),這樣工作人員不加操作也不會給系統帶來威脅
-
3.4.3. 預設防禦模式適用於整個系統的配置,以及元件和API引數的配置可選項
-
3.4.3.1. 預設防禦適用於一切有可能影響安全性的設定或者配置,絕不僅僅是預設密碼
-
3.4.3.2. 許可權應該預設採用以最嚴格的限制方式進行設定
-
3.4.3.3. 使用者在確有需要且絕對安全的情況下才能手動修改以使用限制更少的許可權
-
3.4.3.4. 預設情況下,應該禁用一切有可能帶來危險的可選項
-
3.4.3.5. 應該預設啟用所有能夠提供安全保護的特性,讓這些特性從一開始就能夠生效
-
3.4.3.6. 需要始終保持軟體更新到最新的版本
> 3.4.3.6.1. 不要使用舊版本且很可能包含已知漏洞的軟體,然後盼著它未來自己就能更新
-
3.4.3.7. 在理想情況下,我們永遠都不應該使用那些不安全的可選項
-
3.4.4. 如果我們希望嚴肅對待系統安全的問題,就永遠不要給系統配置一個不安全的狀態,並指望日後再去提升它的安全性,這樣做不光會製造漏洞,我們事後還常常會把這件事拋諸腦後
-
3.4.4.1. 如果我們使用的裝置有預設的密碼,就應該首先在一個安全的、位於防火牆後面的私有網路中配置好這臺裝置,然後再把它部署到網路當中
-
3.4.5. 預設防禦比配置各個可選項的應用範圍要大得多
-
3.4.5.1. 不指定API引數的預設值是一種比較安全的做法
-
3.4.5.2. 瀏覽器應該預設站點使用的是HTTPS,只有在站點無法連線的時候才切換回HTTP
-
3.4.5.3. 協商建立新的HTTPS連線的兩個對等體裝置應該預設首先接受更安全的密碼套件
3.5. 放行列表與阻塞列表
-
3.5.1. 在設計安全機制的時候,應該優選放行列表(allowlist)而不是阻塞列表(blocklist)
-
3.5.2. 放行列表列舉的是安全的情形,所以這種列表在本質上是一個有限列舉的列表
-
3.5.2.1. 放行列表沒有進行窮舉也不會給有可能造成人們大面積感染的高風險行為開啟大門
-
3.5.2.2. 使用放行列表可以確保我們的安全
-
3.5.3. 阻塞列表則正好相反,這種列表希望列舉出所有不安全的情形,這樣做相當於隱含地放行了其他所有我們希望是安全訪問的情形,這類被放行的訪問在數量上是無限的
-
3.5.3.1. 阻塞列表的問題在於,所有它忽略的情形都是這類列表的缺陷
-
3.5.4. 最安全的阻塞列表是那種包含所有限制情形的列表,但這樣的列表往往也過於嚴格,所以無論如何,阻塞列表都很難滿足設計要求
-
3.5.5. 使用放行列表是一種比較簡單的邏輯,我們一般不會把這種做法視為一種模式
3.6. 避免可預測性
-
3.6.1. 任何可以預測的資料或者行為都沒有機密性可言,因為攻擊者可以透過猜測來學習到這些內容
-
3.6.2. 資料的可預測性可以導致嚴重的缺陷,因為這樣的系統可能會導致資訊洩露
-
3.6.3. 可預測性還可以給攻擊者提供其他機會
-
3.6.4. 可預測性的問題有很多不同的形式,不同的設計方案也可能會導致不同型別的資訊洩露
-
3.6.5. 採用安全的隨機ID
-
3.6.5.1. 偽隨機數生成器或者使用安全隨機數生成器
-
3.6.5.2. 除非我們確定可預測性不會給我們帶來損失,否則應該選擇後者,即使安全隨機數生成器的生成速度會慢一點
3.7. 失效安全
-
3.7.1. 如果發生了問題,我們至少要確保問題最終能夠被妥善解決
-
3.7.2. 在物理世界中,失效安全本身屬於一種常識
-
3.7.2.1. 物理定律就決定了這種電路不可能長時間維持過量的電流,否則其最終會被燒燬
-
3.7.3. 錯誤情形一般很難進行徹底的測試,如果多種錯誤組合在一起,出現在新的程式碼路徑上,就更難測試出來了,出現錯誤的地方就是發起攻擊的沃土
-
3.7.4. 很容易把錯誤處理當成一項可有可無的工作,然後把這項任務拋諸腦後,很多常見漏洞就是這樣產生的