cover

安全開發生命週期 (SDL):把安全內建到開發流程

安全不是最後一關的審查,而是每一步都在做的事。

「事後審查」模式的問題

傳統的安全流程:

需求 → 設計 → 開發 → 測試 → 部署 → 安全審查
                                         ↑
                                    「你這裡有漏洞」
                                    「要改架構」
                                    「上線延後」

問題在於:

  • 發現問題時已經太晚,修復成本極高
  • 安全團隊變成「壞人」,總是在最後一刻擋住上線
  • 開發者不知道為什麼,覺得安全是阻礙而不是幫助
  • 只能找到表面問題,設計層面的安全缺陷已經無法修正

Shift Left — 把安全往左移

需求    設計    開發    測試    部署    運維
 ↑       ↑       ↑       ↑       ↑       ↑
威脅     安全    安全    安全    安全    安全
模型     設計    編碼    測試    部署    監控
                Review  SAST    Config  Logging
                        DAST    Review  Alerting

核心觀念:在每個階段都融入安全考量,而不是集中在最後。 越早發現問題,修復成本越低。


SDL 的六個階段

1. 需求階段:威脅模型

在寫任何 code 之前,先問:「這個功能可以被怎麼濫用?」

最小可行的威脅模型(10 分鐘版):

問題你的回答
這個功能處理什麼敏感資料?(例:使用者的 email、信用卡號)
誰會用這個功能?(例:已登入的使用者、管理員)
如果這個功能被濫用,最壞會怎樣?(例:使用者資料外洩、金額被竄改)
攻擊者最可能從哪裡下手?(例:API 參數竄改、CSRF)
我們需要什麼防禦?(例:input validation、權限檢查、CSRF token)

完整的威脅模型(用於重要功能):

  • 畫出資料流圖(DFD)
  • 在每個信任邊界上套用 STRIDE
  • 為每個威脅評估風險(可能性 × 影響)
  • 決定應對策略:避免、緩解、轉移、接受

2. 設計階段:安全設計原則

原則意思例子
最小權限只給剛好需要的權限DB 帳號只給 SELECT,不給 DROP
縱深防禦不依賴單一安全措施WAF + Input Validation + Parameterized Query
預設安全預設狀態是安全的新建的 API endpoint 預設需要認證
失敗安全出錯時回到安全狀態Token 驗證失敗 → 拒絕存取(不是允許)
簡單原則越簡單越不容易出錯用成熟的 library 而不是自己實作加密

「預設安全」特別重要: 如果你的框架需要開發者「記得加上」安全措施才安全,那一定會有人忘記。好的設計是:如果你什麼都不做,它就是安全的。


3. 開發階段:安全編碼

建立 coding guideline 中的安全規範:

## 安全編碼規範
 
### Input Validation
- 所有外部輸入都必須驗證(type, length, range, format)
- 使用白名單(允許什麼)而非黑名單(禁止什麼)
 
### 資料庫
- 一律使用 Parameterized Query
- 禁止用字串拼接 SQL
 
### 認證與授權
- 密碼一律用 bcrypt(cost factor ≥ 12)
- Session token 使用 crypto-random
- 每個 API endpoint 都要檢查權限
 
### 敏感資料
- 禁止在 log 中輸出密碼、token、信用卡號
- .env 和 secrets 不入版控
- 使用環境變數或 secret manager

Code Review 時的安全 checklist:

  • 有沒有使用者輸入直接進了 SQL / HTML / Shell?
  • 新的 API endpoint 有檢查權限嗎?
  • 有沒有硬編碼的 secret?
  • 錯誤訊息有沒有洩漏內部資訊?
  • 有沒有新的 dependency?有已知漏洞嗎?

4. 測試階段:安全測試工具

工具類型全稱做什麼什麼時候用
SASTStatic Application Security Testing掃描原始碼找漏洞CI pipeline 中,每次 commit
DASTDynamic Application Security Testing對運行中的應用發送攻擊請求部署到 staging 後
SCASoftware Composition Analysis檢查第三方套件的已知漏洞CI pipeline 中,每次 commit
Secret Scanning找 code 中的硬編碼 secretpre-commit hook

常用工具:

# SAST
- Semgrep        # 開源,支援多語言,規則可自訂
- CodeQL         # GitHub 內建,免費
 
# SCA (dependency audit)
- npm audit      # Node.js 內建
- Snyk           # 多語言,有免費版
- Dependabot     # GitHub 內建
 
# Secret Scanning
- gitleaks       # pre-commit hook
- GitHub Secret Scanning  # 免費
 
# DAST
- OWASP ZAP      # 開源,功能完整
- Burp Suite      # 業界標準(付費版功能更多)

務實建議: 不需要全部都用。從這個組合開始:

  1. Semgrep in CI(SAST)
  2. npm audit in CI(SCA)
  3. gitleaks as pre-commit hook(Secret Scanning)

這三個都是免費的,10 分鐘就能設好。


5. 部署階段:安全設定

# 部署 checklist
- [ ] Debug mode 關閉
- [ ] 預設帳號密碼已更改
- [ ] HTTPS 強制開啟
- [ ] Security headers 已設定
- [ ] 不需要的 port 已關閉
- [ ] 最小權限的 service account
- [ ] Container 以 non-root 執行
- [ ] Secret 從 secret manager 讀取,不從環境變數

Infrastructure as Code 的安全掃描:

  • tfsec — Terraform
  • checkov — 多種 IaC 格式
  • kube-bench — Kubernetes

6. 運維階段:持續監控

該監控的安全指標:

指標為什麼重要告警閾值建議
登入失敗次數暴力破解偵測同一 IP 5 分鐘內 > 10 次
權限錯誤 (403)權限繞過嘗試同一使用者 1 分鐘內 > 5 次
異常的 API 呼叫量DDoS 或 data scraping超過 baseline 3 倍
新的 admin 帳號建立可能被提權任何非預期的建立
大量資料匯出Data exfiltration超過正常量的 10 倍

DevSecOps — 把 SDL 自動化

開發者 push code
    │
    ├── pre-commit: gitleaks(掃 secret)
    │
    ├── CI pipeline:
    │   ├── Semgrep(SAST)
    │   ├── npm audit(SCA)
    │   └── Unit tests with security cases
    │
    ├── Deploy to staging:
    │   └── OWASP ZAP scan(DAST)
    │
    └── Production:
        ├── Security headers check
        ├── Runtime monitoring
        └── Alerting

核心思維:安全檢查應該是自動的、快速的、不阻礙開發流程的。 如果安全檢查讓 CI 多跑 30 分鐘,開發者會想辦法繞過它。


一個人怎麼做 SDL

如果你是個人開發者或小團隊,完整的 SDL 太重了。最小可行的安全流程:

  1. 寫新功能前 — 花 5 分鐘回答:「這個功能可以被怎麼濫用?」
  2. 寫 code 時 — 記住三條:input validation、parameterized query、最小權限
  3. commit 前 — 跑 gitleaks 確保沒有 secret
  4. CI 裡 — 加 npm auditsemgrep
  5. 部署後 — 用 securityheaders.com 掃一次

總共增加的時間:每天 15 分鐘。換來的是大幅降低被攻擊的風險。


反思問題

  1. 你的 CI pipeline 裡有安全掃描嗎? 如果沒有,今天就加一個 npm audit
  2. 你的 .git 歷史裡有 secret 嗎? 很多人忘記 git 有歷史記錄——即使你在新 commit 裡刪除了 .env,舊 commit 裡還在。
  3. 你的團隊在 code review 時會看安全嗎? 還是只看功能對不對?
  4. 如果明天你的系統被爆出漏洞,你有應變計畫嗎? 搭配 事故管理 來準備。

延伸閱讀