這五種漏洞裡,哪一種在現代審計技術下已經比較少見?
重入攻擊跟存取控制疏漏這兩種相對基礎的漏洞類型,現在已經有成熟的自動化靜態分析工具能快速掃描偵測,加上業界累積了大量已知案例形成標準檢查清單,多數有經過正規審計流程的協議,理論上應該能在上線前排除掉這類「教科書等級」的漏洞,實務上這兩類漏洞導致的重大事件近年確實有下降趨勢。
相對地,複雜的邏輯設計缺陷跟跨協議互動造成的問題,即使在審計技術持續進步的情況下,依然是難以完全根除的類型——因為這類問題往往不是單一合約內部的錯誤,而是多個獨立、各自看起來正確的系統組合起來後才浮現的意外行為,這種問題的偵測高度仰賴審計員對整個協議生態系統的理解深度,不是單純的程式碼掃描能解決的,這也是為什麼近年重大攻擊事件,反而更常見到這類複雜互動導致的案例,而不是基礎款漏洞。
如果一個漏洞理論上很基礎、應該很容易被抓到,為什麼還是有協議會因此被攻擊?
幾個實際原因:時間與預算壓力——部分項目為了搶市場先機,審計流程可能被壓縮,或者只審計了核心合約而忽略了周邊模組;升級或修改後沒有重新審計——很多攻擊發生在協議上線後新增功能或修改參數的階段,原始審計報告只涵蓋最初上線的版本,後續變更如果沒有同步進行審計,等於讓新程式碼完全暴露在沒有經過檢驗的狀態下;審計本身的品質差異——不是所有標榜「已審計」的協議都找了同一水準的審計機構,部分審計品質參差不齊,可能連基礎款漏洞都沒有被真正抓出來。
這也是為什麼查驗一份審計報告時,除了確認「有沒有審計」,還需要進一步確認審計涵蓋的程式碼版本是否跟目前上線版本一致、審計機構的過往紀錄與口碑如何,這些細節往往比「有沒有審計標章」這個表面資訊更有參考價值。
普通用戶能不能自己用區塊鏈瀏覽器簡單查一下,一個協議的合約有沒有明顯的存取控制風險?
有一定程度可以,雖然不需要看懂完整程式碼,但能做一些基礎檢查:在區塊鏈瀏覽器上查看合約是否已經「開源並驗證」(verified),這代表合約的原始碼是公開可讀的,而不是只有編譯後的機器碼;如果合約開源,可以搜尋程式碼裡是否有標記為 onlyOwner、onlyAdmin 這類權限修飾詞的函式,並留意這些函式對應的實際功能是什麼(例如是否包含鑄幣、提領資金池、修改關鍵參數等敏感操作);同時查看這個「owner」或「admin」的地址本身是一般外部帳戶還是多簽錢包——如果關鍵權限集中在單一一般帳戶手上,而不是需要多方共同簽署才能執行的多簽機制,代表這個協議存在單點故障或內部人員作惡的風險。
這些檢查不需要看懂邏輯漏洞或重入攻擊這類複雜問題(那確實需要專業能力),但能幫你抓出「權限設計是否過度集中」這個相對容易理解、也相對容易查驗的風險指標。
這些漏洞類型有沒有共通的防範哲學,還是每一種都需要完全不同的解法?
雖然五種漏洞的技術細節不同,但背後有一個共通的防範哲學:不要相信任何單一環節「一定」會按照預期運作,要為「萬一它沒有」的情況預先設計緩衝。重入攻擊的防範是先更新狀態再進行外部呼叫(不管外部呼叫發生什麼意外,狀態已經是正確的);整數溢位的防範是使用會自動檢查邊界、無法繞回的安全數學函式庫;存取控制的防範是把敏感權限交給多簽機制而非單一帳戶(不相信單一持有者一定不會犯錯或作惡);預言機操縱的防範是不依賴單一價格來源(不相信任何一個資料來源一定準確);邏輯缺陷的防範則需要透過模擬各種極端情境的測試,主動假設「使用者可能會用我沒想到的方式組合使用這些功能」。
這個共通哲學可以總結成一句話:好的智能合約設計,不是假設一切都會順利運作,而是假設一定會有某個環節出錯,然後預先設計好出錯時的止損機制。
看到協議公告「因智能合約漏洞遭受攻擊」時,多數非工程背景的用戶只能理解到「合約壞了、錢被偷了」這個層次,很難進一步判斷這次事件反映的是偶發個案,還是這個協議整體工程品質有結構性問題。理解幾種最常見的漏洞類型背後的邏輯,不需要看懂程式碼本身,就能建立起判斷協議安全性的基礎框架。
重入攻擊是 DeFi 史上最早、也最經典的漏洞類型。可以想像成一個提款流程:合約應該先扣掉你的餘額紀錄,再把錢轉給你。但如果程式碼寫反了順序——先把錢轉出去,才更新餘額紀錄——攻擊者就能在「錢已經轉出、但餘額紀錄還沒更新」的這個空檔,趁機再次呼叫提款函式,因為系統還沒把餘額歸零,等於允許攻擊者用同一筆存款反覆提領好幾次。這就像是提款機還沒把交易記錄寫回資料庫之前,你就已經衝進去重複按了好幾次提款鍵。2016 年 The DAO 事件正是這種攻擊模式,導致約 6,000 萬美元的以太幣被抽走。
電腦儲存數字的空間是有限的,如果一個變數只能儲存到某個最大值,運算結果超過這個上限時,系統可能不會顯示「錯誤」,而是直接「繞回」變成一個很小甚至是零的數字(或反過來,一個很小的數字扣過頭變成一個極大的數字)。想像一台只能顯示三位數的計數器,數到 999 之後繼續加 1,畫面顯示的不是 1000,而是繞回顯示 000。如果攻擊者能故意製造出這種「數字繞回」的情況,可能可以讓合約誤判自己還有大量餘額可以動用,實際上這筆餘額根本不存在。
多數合約會設計「只有管理員才能執行」的敏感功能,例如緊急暫停交易、修改關鍵參數、甚至直接鑄造新代幣。存取控制疏漏指的是,這些原本應該限制身分的函式,因為程式碼裡漏寫了身分驗證的檢查,變成任何人呼叫都能執行。這就像一棟大樓裡標示著「員工專用」的門,門把上卻忘了裝鎖,任何路過的人都能直接推門進去。這類漏洞通常源自單純的疏忽,而不是複雜的邏輯設計問題,理論上是相對容易在審查階段被發現的類型,但實務上仍不時發生。
如果合約判斷抵押品是否足額、要不要觸發清算,完全仰賴某個價格來源,而這個價格來源可以被攻擊者透過巨額交易瞬間拉高或壓低,攻擊者就能製造出一個「暫時性但足以觸發連鎖反應」的假價格。這類似於一間商店只用一台可以被輕易調整的體重計來判斷客人買多少東西該付多少錢,只要有人能悄悄調整體重計的指針,就能讓收銀系統依照錯誤的重量結帳。防範方式通常是不要只依賴單一、即時的價格來源,改用多個來源交叉比對,或採用一段時間內的平均價格而非單一時刻的瞬間價格。
這是最難被自動化工具抓到的漏洞類型,因為程式碼本身可能完全沒有語法錯誤,每個函式單獨看都運作正常,問題出在整體商業邏輯的設計——某幾個功能按照特定順序組合使用時,會產生出設計者完全沒預料到的結果。這類似於一套規則手冊裡每一條規則單獨看都合理,但把幾條規則串在一起,卻能推導出一個誰都沒設想過的漏洞路徑,這種問題通常只有透過深入理解協議商業邏輯的人工審查才能發現,是審計工作裡最考驗經驗與想像力的部分。
下次看到某個協議的漏洞事件公告,可以試著判斷這次攻擊比較接近哪一種類型:如果是重入攻擊或整數溢位這類相對基礎的漏洞,可能反映團隊工程審查流程本身有明顯缺失;如果是複雜的邏輯設計缺陷或跨協議互動造成的問題,則說明即使工程實踐相對嚴謹,DeFi 生態系高度可組合的特性依然帶來難以完全消除的風險。這個判斷不會讓你變成資安專家,但能幫助你在閱讀事後檢討報告時,抓到更有意義的資訊,而不只是停留在「這個協議出事了」的表層認知。