需求
更新時不小心被移除的資安設定,從外面完全看不出來,直到稽核人員或客戶發現為止。
構想
不要靠記性去檢查。讓檢查自己執行,並與監控對象分開,這樣一個故障就永遠不會掩蓋另一個故障。
我打造了什麼
- 一個檢查程式,確認網站應該送出的標準防護:5 個安全標頭、轉向 HTTPS、cookie 設定,以及憑證到期日(提前 3 週警示)。
- 它依照自己的排程在網站之外執行,並把歷史紀錄存在自己的資料庫中。
- 一個不公開的儀表板,必須通過身分驗證才能進入。
成果
- 30 分鐘兩次檢查之間的間隔
- 5每次檢查都會驗證的安全標頭
- 3 週憑證到期前提前警示
- 2026 年 8 月 30 日開始運作
第一次檢查就發現一個會洩漏所用框架版本的標頭,並在 1 小時內修正。接著它還抓到了自己的錯誤:最初的儀表板是公開的,還被列在 sitemap 裡,等於替攻擊者準備好一張地圖。當天就關閉,之後改為必須通過身分驗證才能重新開放。
畫面一覽
我學到了什麼
資安工具必須先通過自己的檢驗。一個公開展示自身監控對象的監控工具,對任何發現它的人來說,都會變成偵察工具。
技術細節 技術堆疊、架構與決策——給技術背景的讀者
技術堆疊
- Node.js(無 npm 相依套件)
- Express
- SQLite (node:sqlite)
- systemd 計時器
- Cloudflare Access
運作方式
- 檢查項目:是否有 CSP、HSTS、X-Frame-Options、X-Content-Type-Options 與 Referrer-Policy;沒有透過 Server 或 X-Powered-By 洩漏資訊;每個 cookie 都設定 Secure 與 HttpOnly;HTTP → HTTPS 重新導向;TLS 憑證在 3 週內不會到期。
- 零 npm 相依套件:只使用 Node 的內建模組。
- 在設計上就彼此解耦:檢查程式是每 30 分鐘觸發一次的 systemd 服務,寫入自己的 SQLite 資料庫;儀表板只讀取這個資料庫,從不自行執行檢查。
- 發生這次自己造成的曝光之後:將儀表板從 sitemap 與 robots.txt 移除,把服務識別碼移出原始碼,接著只在專用子網域上、透過 Cloudflare Access 保護後重新開放。
仍待補強
- 儀表板不公開(刻意的設計)