Security Theater(安全劇場)

讓人感覺安全,但實際上不提供防護。

最常見的版本:有 HTTPS,所以 payload 裡的密碼不需要額外保護;有防火牆,所以內部 service 不用驗證彼此;有 login 頁面,所以 API 本身不需要授權檢查。

安全劇場的問題不只是「沒有用」——它會建立錯誤的安全感,讓團隊在真正需要保護的地方疏於防護。


把安全當 Checkbox

在上線前做一次「安全掃描」,通過了就勾掉,下次再說。這種心態把安全當成一次性的合規作業,而不是持續的工程實踐。

現實是:威脅在進化,依賴在更新,架構在改變。六個月前安全的系統,今天可能因為一個新 CVE 或一個設計改動而暴露。

正確的做法:把安全整合進開發流程——threat modeling 在設計評審、SAST/DAST 在 CI/CD、dependency 掃描在 PR 流程。安全不是最後一關,是每個環節的一部分。


Secret 寫在 config 或 code 裡

# 這個 pattern 在 git history 裡永遠存在,即使你之後刪掉
DATABASE_URL = "postgresql://admin:SuperSecret123@prod-db.company.com/main"
AWS_SECRET_KEY = "wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"

Secret 一旦進入 git history,就永遠在那裡。即使刪除了 commit,fork、clone、backup 裡可能還有。

正確做法:環境變數(最低要求)、Secret Manager(AWS Secrets Manager、GCP Secret Manager、HashiCorp Vault)。動態短期 credential 比靜態長期 credential 更安全——用完即棄,30 分鐘後自動過期。


用 MD5 或 SHA-1 存密碼

MD5 和 SHA-1 是通用 hash 算法,速度快是特性,但用來存密碼反而是缺點。攻擊者可以用 GPU 每秒算出數十億個 hash,配合彩虹表幾秒鐘就能破。

# 錯誤:MD5 或 SHA-256 直接 hash 密碼
password_hash = hashlib.md5(password.encode()).hexdigest()
 
# 正確:bcrypt 或 Argon2,有 salt,有計算成本
import bcrypt
password_hash = bcrypt.hashpw(password.encode(), bcrypt.gensalt(rounds=12))

Argon2(2015 年 Password Hashing Competition 冠軍)是現在的最佳選擇。bcrypt 也可以,已有 30 年歷史沒有被破解。


自己實作加密算法

「我有密碼學背景,我來寫一個自定義的加密方案。」這幾乎必然比使用成熟的加密庫更脆弱。

密碼學實作有大量微小的陷阱:timing attack(根據處理時間推斷資訊)、padding oracle attack、nonce reuse 攻擊。這些不是靠「邏輯正確」就能防的——需要幾十年的密碼學研究和攻防審查。

使用現有的加密庫:Python cryptography、Node.js crypto(內建)、Go crypto/tls、Java Bouncy Castle。不要自己實作,即使你懂數學。


Security by Obscurity(以晦澀作為安全)

「我把 admin panel 放在 /xK9j2mP/admin,沒人知道這個路徑,所以不需要做認證。」

隱藏不等於安全。攻擊者有自動化工具掃常見路徑,DNS 歷史記錄會洩漏子網域,HTTPS 的 SNI 可以被看到。一旦路徑被發現,就沒有任何防護。

Security by obscurity 可以作為防禦的額外一層(defense in depth),但絕對不能作為唯一的防護


只看 OWASP 不追 CVE

OWASP Top 10 是「過去常見問題的統計摘要」,不是「你系統裡現在最危險的漏洞清單」。

你用的 Log4j 版本是不是 2.14 以下?你的 OpenSSL 有沒有 Heartbleed 時代的版本?你的 Spring Boot 版本有沒有 Spring4Shell 的漏洞?

這些都只能靠持續追蹤 CVE 和依賴版本來知道。npm auditpip-audit、Snyk、Dependabot、Grype——選一個整合進 CI,有嚴重 CVE 就告警。


不做 Threat Modeling,等滲透測試再說

「我們上線前會有滲透測試,到時候再修。」

滲透測試發現的是「現在已經存在的漏洞」。威脅建模在設計階段發現的是「如果這樣設計,將來會有什麼漏洞」——在這個時間點修設計是免費的,滲透測試發現後要重構可能要幾週甚至幾個月的工作。

更重要的是:滲透測試的覆蓋範圍有限,通常是幾天到幾週的時間窗口。威脅建模讓整個開發團隊在每次設計決策時都帶著安全思維。


這些 anti-pattern 的共同主題是:把安全當成別人的問題最後一關。安全最有效的形態是從設計到部署、從開發到營運的持續工程實踐——不是一個團隊負責、不是一次性的合規作業。