網路現在住在火環帶上了
我以前住在台灣,現在住在日本。在地圖上看起來是兩個很不一樣的地方,但在地質上它們有同一個地址:環太平洋火環帶。從一邊搬到另一邊,有一件事完全沒變:地面還是會晃,而且一年到頭都在晃。這樣過了夠多年,地震就不再是什麼事件,而是生活的背景音。手機警報大響、吊燈開始搖,第一個念頭不是慌張,而是快速盤算一下:這是小地震,還是我該躲到桌子底下了?大多數時候幾秒就過去了,大家繼續做自己的事,但你永遠不會完全忘記,腳下的地板沒有看起來那麼穩。
最近,網路也給我同樣的感覺。自從 AI 輔助的漏洞挖掘起飛以後,每天都有上百個新的 CVE 冒出來,高分的 CVSS 也一個接一個。FIRST 在六月預估 2026 年會有約 66,000 個 CVE,Google 的威脅情報團隊則觀察到每月揭露的數量翻倍,從一月的約 5,000 個增加到七月的超過 10,000 個。默默撐起我們幾乎每一條連線的 TLS 也不例外:OpenSSL 一月修了 12 個 CVE,全部都是 AI 系統找到的,有些從 90 年代末就藏在程式碼裡;六月又修了另外 18 個,其中最嚴重的是一個在 AI 協助下找到的高風險 use-after-free。Mozilla 在 Firefox 150 修了 AI 模型找出的 271 個漏洞。而就在這週,PHP 為兩個嚴重漏洞發布了安全更新,兩者在 CVSS v4 下都是 9.2 分,都能在未經認證的情況下遠端執行程式碼,幾乎所有對外提供網頁的 PHP 都受到影響。Rapid7 建議跳脫平常的更新週期,以緊急方式套用修補。這些 bug 沒有一個是新的。它們就像斷層,一直都在程式碼裡,有些甚至已經存在幾十年;CVE 只是其中一條終於滑動的那一刻。每一則警報都是一次搖晃。大部分都會過去,我們修補、繼續前進,但網路腳下的地面從來沒有這麼不穩過。
火環帶的教訓
台灣和日本都沒辦法搬離斷層。地震不會停,所以過去幾十年來,兩國不再期待地震停下來,而是專注在怎麼撐過去。我認為網路現在也處在同樣的位置。AI 不會停止找 bug,CVE 的數量也回不到從前了。所以與其問怎麼讓搖晃停下來,或許我們該看看住在火環帶上的人已經摸索出了什麼。
第一個教訓是預警和演練,好消息是這兩樣我們都已經有了。日本和台灣都有地震預警系統,偵測到最先抵達的地震波後,就推播警報到受影響地區的手機,在強烈搖晃抵達之前給大家幾秒到幾十秒的時間(不過離震央很近的地方可能會來不及)。兩國也都用震度階級來描述搖晃的程度,日本和台灣都分成十級。
網路也有自己的版本:CVE 編號告訴所有人某個東西壞了,CVSS 分數告訴大家這次有多大。Coordinated disclosure 讓維護者有時間準備修補,負責發行軟體的人也常常會在公開之前先收到通知。以這週的 PHP 漏洞為例,Linux 發行版和 LTS 廠商就事先拿到了修補。演練的部分,多數公司也都有某種流程:有人盯著安全公告,有人決定什麼是緊急的,也有一套推送修補的 playbook。
所以問題不在於這些系統不存在,而在於它們是為比較平靜的年代設計的,現在需要變得更好。預警只有在大家知道那幾秒該做什麼時才有用,這也是為什麼兩國即使平安無事,仍然持續舉辦防災演練:日本在每年 9 月 1 日的「防災日」,台灣則在 9 月 21 日的「國家防災日」,也就是 921 大地震的週年。
預警也只有在大家還信任它時才有用。日本的公開警報只在預估震度達到 5 弱以上時才發布(或長週期地震動階級 3 以上),氣象廳選這個門檻,是因為從這個程度開始會出現顯著的災害。而且警報只會發給預估會強烈搖晃的地區,再加上預估震度 4 的地區,以防預估有誤差或搖晃變大。它看的是震度,不是規模。一支對每個小地震、或對遠方的大地震都大響的手機,很快就會被忽略。
我們的流程也面對同樣的兩種壓力。當每天新增的 CVE 數量在半年內翻倍,triage 就必須更精準,才不會讓真正嚴重的漏洞被淹沒在雜訊裡。問題在於,CVSS 分數比較接近地震的規模,而不是震度。規模描述的是地震本身,對每個人都是同一個數字;震度描述的是你所在的地方晃得多厲害。一個出現在你根本沒用到的元件裡的 CVSS 9.2 bug,就像地球另一端的大地震。震度是這個 bug 對你自己的環境代表什麼:你有沒有用到那個元件?它有沒有對外開放?有沒有人真的在利用它?所以 triage 要看震度,而不只是規模:把 CVSS 分數和你實際使用、對外開放的東西放在一起看,再搭配 FIRST 的 EPSS(預估一個 CVE 在未來 30 天內被利用的機率),以及 CISA 的已知被利用漏洞清單。
回應的部分也必須練到不需要靠英雄式的硬撐。如果升級 PHP 是一件可怕、手動、一年一次的大事,一個嚴重的 RCE 就會變成漫長又煎熬的一週。如果你有自動化建置、信得過的測試,還有一條已經跑過很多次的部署流程,緊急修補也不過就是另一個普通的星期二。
改寫建築法規
但預警和演練只能幫你反應。第二個教訓是關於一開始要怎麼蓋,而在這件事上,兩國都是吃過苦頭才學到:每次重大災難之後,建築法規都得改寫。日本在 1981 年 6 月實施新耐震基準,1995 年阪神淡路大地震襲擊神戶時,大部分的死者是建築物倒塌造成的,而災損集中在 1981 年以前興建、不符合新基準的建築。台灣也從 1999 年的 921 大地震學到了類似的教訓。在那之後的幾年裡,台灣修正了震區劃分、在耐震設計規範中加入近斷層效應,並開始補強公有建築,當時有超過 4,600 棟公有建築在地震中受損。新的規範並不完美,但每一次災難都成了下一版標準的依據。
在軟體上,我喜歡把程式語言想成建材。建築有木造、鋼骨到鋼筋混凝土;語言也有類似的光譜:從 C 和 C++ 這類非記憶體安全的語言,到 Go、Java、C#、Python 這類有垃圾回收的語言,再到像 Rust 這樣不靠垃圾回收也能做到記憶體安全的語言。日本的建築法規並沒有規定所有東西都得用鋼筋混凝土蓋,而是對每一種建材各有結構規定,照規範好好蓋的木造、鋼骨或鋼筋混凝土房子,都能撐過大地震。軟體也是一樣,不是所有東西都得用 Rust。
木造就是一個規範持續進步的好例子。日本在 2000 年又修訂了木造住宅的規定,明確規範了接合部等的做法。2016 年熊本地震發生時,差異非常明顯。在受災最嚴重的城鎮之一益城町的中心區域,1981 年 6 月以前興建的木造住宅有 28.2% 倒塌,1981 年 6 月到 2000 年 5 月之間興建的是 8.7%,而 2000 年 6 月以後興建的只有 2.2%。當地倒塌的 297 棟木造住宅中,有 290 棟是在 2000 年修訂之前蓋的。
C 和 C++ 也經歷著類似的事。每一版新的語言標準,像是 C17、C23 或 C++26,都是木造的新版建築法規:C23 加入了 checked integer arithmetic 和 memset_explicit,C++26 則採納了標準函式庫 hardening,用來抓出像越界存取這類問題。跟得上這些標準的專案,狀況可以比那些還用 90 年代寫法的專案好。而且維護得好的木造,可以撐得驚人地久。法隆寺有部分木造建築從 7 世紀末或 8 世紀初一直屹立至今。有些老的 C 專案也是這樣:幾十年來被細心照顧,到現在依然穩穩站著。
但如果你要蓋的是一棟現代高樓,就該好好想想要用什麼建材。截至 2019 年,Microsoft 指派的 CVE 中約有 70% 來自記憶體安全問題,而前面提到的頭條,OpenSSL 的 use-after-free,以及 PHP 的記憶體損壞和 use-after-free,都是同一種裂縫。事實證明,AI 非常擅長在木造結構裡找出這種裂縫。換成記憶體安全的建材,編譯器或 runtime 就像一位檢查員,不讓大部分這類裂縫出現。而且這確實有效:Android 把新程式碼轉向包括 Rust 在內的記憶體安全語言之後,記憶體安全漏洞的佔比從 2019 年的 76% 降到 2025 年的不到 20%,Google 也保守估計,Android 的 Rust 程式碼的記憶體安全漏洞密度比它的 C 和 C++ 程式碼低了 1000 倍以上。
所以教訓不是「全部用 Rust 重寫」。這跟日本建築法規本來就遵循的原則一樣:依照你要蓋的東西選擇合適的建材,並遵循那種建材的最新規範。小房子可以用木造,只要是照今天的標準蓋,而不是 1980 年的標準。每天有成千上萬人進出的高樓,就值得更仔細檢視它是用什麼蓋的。在軟體裡,高樓就是那些直接面對網路、其他所有東西都依賴它的程式碼:TLS、parser、語言 runtime,以及在任何應用程式碼執行之前就先碰到不受信任輸入的 request handler。對這些程式來說,認真考慮改用記憶體安全的語言是值得的,有些情況甚至值得重寫。語言 runtime 特別值得一提。前面提到的 PHP 漏洞並不在任何人的 PHP 程式碼裡,而是在底下那層用 C 寫的 runtime。蓋在木造地基上的鋼骨建築,強度也就只跟那塊木頭一樣。而且仔細看的話,大多數軟體在某個地方終究還是蓋在木頭上,因為作業系統的 kernel 和系統函式庫大多是用 C 寫的。這不是放棄的理由,而是提醒你要知道自己的地基在哪裡,並且先補強它。
這不代表要把地基整個拆掉。阪神淡路大地震之後,日本並沒有拆光 1981 年以前的建築,而是在 1995 年立法推動耐震補強,並從學校、醫院、百貨公司這類多人使用的大型建築開始。直譯器同樣用 C 寫成的 CPython,現在也在考慮同樣的做法。Rust for CPython 這個提案的動機之一,是 crash 回報從 2021 年的 82 個增加到 2025 年的 222 個。它從小地方開始:替 zlib 模組加一個可選的 Rust 後端,C 程式碼保留作為備援,之後才輪到 json 和 parser 等模組。Rust 最快也要到 2029 年才會成為建置的必要條件,而且就像講者說的,CPython 不應該「為了 Rust 而用 Rust」來寫。這就是軟體版的耐震補強:從一小塊獨立的部分開始,施工期間建築照常使用。至於其他部分,就跟上規範:升級到較新的語言標準、打開工具鏈已經提供的 hardening、採用較新的準則,並先修補最弱的地方。
在日本這裡,我的手機還是會繼續因為地震警報大響,我也還是會繼續快速盤算:這是小地震,還是我該躲到桌子底下了?讓這個盤算成為可能的,是幾十年來的預警、演練和建築法規,由一群接受了地面永遠不會停止搖晃的人一點一點建立起來。網路也需要走到同樣的地方。地震不會停,但下一次地震,不必再震垮同樣的建築。