對象:人手不多、同時維運多個 Web 應用程式(框架混用),想把相依套件的漏洞(CVE)處置「認真徹底地修一次」的人。這裡不講攻擊手法,只講修好、讓它不會消失、並持續監控為止的實務。容易成為導火線的事故示例,可參考 放任已公開的RCE導致被惡意刷費的經歷。
本站的視角:越小的團隊越能靠『兩個機制』守住
人手少的團隊,真正管用的不是花俏的工具,而是兩條紀律。①自動的變化偵測(只對新增的漏洞報警)②local→push→deploy(正式端只接收,不編輯)。本站也是同樣的思路,把相依套件稽核(pnpm audit)放在每次部署前+每日 cron 裡跑,向正式端則只用 push-to-deploy 來分發。不要把它當成一次性的修復事件,而要倒向放好一個會報警的機制並持續運轉的維運方式,這反而是最便宜、最持久的。
先把完成的「4個定義」固定下來
這是為了不讓人隨便說「搞定了」的剎車。先約定好:在這四點齊備之前都算未完成。
① 掃描
用數字掌握現狀
② 修復
根治非dev的嚴重/高危
③ 隔離/移交
修不了·孤立的要明示
④ 監控
加上每日變化偵測
① 掃描:把現狀變成「數字」
首先,用機器掌握「哪裡有什麼」。手動的不定期檢查一定會中斷。
自動探索鎖定檔並掃描
composer.lock / package-lock.json / pnpm-lock.yaml,每天用 OSS 掃描器(osv-scanner 或 pnpm audit)跑一遍。只是讀鎖定檔,負載極輕。要知道嚴重度不是『一個數字』就能定
雜訊不是『無視』而是『有依據地排除』
② 修復:不要對症療法,要「根治」
止血(對症療法)和根治是兩件不同的工作。兩者都做了才算結束。
只做對症療法(止於圍堵)
- 用反向代理只擋掉「看起來像那樣」的請求
- 因為症狀停了就以為「處置完成」
- 脆弱的相依套件原封不動=RCE等仍然存活
根治(正確)
- 把脆弱的相依套件更新到修復版,堵住窟窿本身
- 更新後,用記錄確認徵兆是否消失
- 把止血和根治當作兩件事都做
跨大版本要『在推上正式環境前先建置驗證』
和打修補程式不同,跨大版本(框架14→15、UI工具4→6 等)會伴隨破壞性變更。盲目升級而導致正式建置失敗是最糟的。把改完的原始碼放到與正式環境相同的執行階段(同樣 Node/PHP 版本的容器)裡,等建置/型別檢查完全通過後再 push。失敗的錯誤訊息要一個一個解決(同步→非同步化的 codemod、CSS 的多行 class、型別命名空間被廢棄 等)。若採用舊容器仍在執行的結構,失敗時也能不停機地回切。
把修復的「持久性」也包含進來才算完成
內容哪怕100分,只要下一次部署就被覆蓋,也是0分。這是最容易踩的坑。
不要在正式環境的工作樹裡直接commit
務必統一為 local→push→deploy 的單向流動
不要把 HTTP 200 當成『正常』
curl | grep)、錯誤記錄裡是否出現新條目、連相依 DB 和帶參數的動態路由都要走一遍。由於快取可能讓生效變慢,要隔一段時間或清快取後再看。③ 隔離/移交:把修不了的東西「明示」出來
不一定所有問題都能馬上修好。訣竅在於:對修不了的、歸屬他人管轄的、已經不用的,不要含糊其辭。
孤立·EOL 程式碼要『在刪除前先隔離』
先確定確實無人引用,再動手
修不了/他人管轄的要明示移交
④ 監控:加上每日「變化偵測」才算完成
走到這一步,最後放上會報警的機制。沒有它,就算辛苦修好了,也察覺不到復發。
不是『把全部每天都報』而是『增加了才報』
把掃描結果與上次取差異(state file)比較,只在出現新增的嚴重/高危時才通知。每天都收到相同內容,很快就會被無視(告警疲勞)。通知彙總成一封郵件(新增·已解決·現狀),用 cron 每日跑。哪怕是共享伺服器,靠一個掃描器二進位檔+cron 也足夠運轉(負載是數毫秒量級·搭配 nice 就更穩妥)。
盤點時會一併冒出來的「秘密」和「金鑰」
在徹底修復 CVE 的過程中,常常會連相依套件以外的窟窿一起被發現。最有代表性的有兩個——遺忘在公開目錄裡的秘密檔案(webroot 裡放著舊 token,若源自共用範本就所有機器都有同一個窟窿)和交給可能被入侵的暫時環境的 root 金鑰。兩者都是會造成「一處洩漏就全盤皆失」的典型,所以要在和 CVE 處置相同的盤點時機一併檢查(這兩個各自都值得單獨深挖)。秘密的基礎可參考 秘密的安全保管 和 最低限度檢查清單。
接下來讀
- 相依套件監控:osv-scanner 的引入與用法 / 不落後於 CVE 的機制
- 事故:放任已公開的RCE導致被惡意刷費的經歷
- 維運:正式端只接收/自架 Git vs GitHub
- 基礎:安全最低限度檢查清單
FAQ
Q漏洞處置做到什麼程度才算『完成』?
四點齊備才算完成。①用掃描把現狀變成數字②修復了非dev的嚴重/高危③對修不了的、歸屬他人管轄的、已孤立的程式碼做了明示的隔離/移交④加上了每日變化偵測(能捕捉復發與新增的監控)。尤其在加上④之前都不算完成,因為相依套件明天又可能變得脆弱。
Q每天掃描不會被告警搞得疲憊嗎?
『把全部內容每天都報一遍』很快就會被無視。要與上次結果取差異,只在出現新增的嚴重/高危時才通知,這就是『變化偵測』。不每天發送相同內容,反而是最能長期堅持下去的設計。
Q明明修好了,為什麼又退回到脆弱狀態?
在正式環境的工作樹裡直接commit,會在下一次部署(pull 或 checkout -f)時被覆蓋,修復就消失了。務必統一為 local→push→deploy 的單向流動,讓正式端『只接收』。修復內容哪怕完美無缺,只要會被覆蓋的維運方式,成果就是零。