智能合約里的 “拒絕服務“ 攻擊:讓你的合約變成 “死機的手機“

你有沒有遇到過手機突然卡死,點什么都沒反應的情況?在區塊鏈世界里,智能合約也可能遭遇類似的 "罷工"—— 這就是 "拒絕服務攻擊"(Denial of Service,簡稱 DoS)。今天用大白話講講合約里的 DoS 攻擊是怎么回事,以及如何防范。

先理解:什么是拒絕服務攻擊?

簡單說,拒絕服務攻擊就是通過各種手段,讓合約的核心功能徹底失效,誰都用不了

就像:

  • 你經營一家自助餐廳,有人故意把所有座位占滿卻不消費,真正的顧客進不來
  • 你開了個快遞柜,有人把所有格子都塞一些廢紙條,導致正常包裹放不下

在合約里,DoS 攻擊會讓轉賬、提款、投票等關鍵功能徹底卡住,嚴重的甚至會讓合約里的資產永遠取不出來。

合約里最常見的 3 種 DoS 攻擊手法

1. 利用 "必須成功的批量操作"—— 最容易踩的坑

很多合約會設計批量操作功能(比如批量發工資、批量退款),如果代碼里用了for循環一次性處理所有用戶,就可能被攻擊。

漏洞合約示例(批量退款):
contract BatchRefund {address[] public refundees; // 退款名單mapping(address => uint) public amounts; // 每個人該退的錢// 管理員添加退款名單function addRefundee(address who, uint amount) public {refundees.push(who);amounts[who] = amount;}// 批量退款(有漏洞!)function refundAll() public {// 循環給每個人退款for (uint i = 0; i < refundees.length; i++) {address payable who = payable(refundees[i]);// 只要有一次轉賬失敗,整個函數就會卡住(bool success, ) = who.call{value: amounts[who]}("");require(success, "給某個人退款失敗了");}}
}
攻擊方式:

黑客只需要用一個 "有問題的地址"(比如一個沒有receive函數的合約地址)加入退款名單。當refundAll()執行到這個地址時,轉賬會失敗,require會觸發revert,整個批量退款就會卡住。

結果就是:所有人都拿不到退款,功能徹底報廢

2. 用 "gas 炸彈" 耗盡資源 —— 讓交易永遠失敗

以太坊的每筆交易都有 gas 限制(相當于 "燃料上限"),如果合約里有需要大量計算的功能,黑客可以故意觸發這些功能,讓 gas 消耗超過上限,導致交易失敗。

漏洞合約示例(投票系統):
contract BadVoting {mapping(address => uint) public votes; // 每個人的票數address[] public voters; // 投票人名單// 投票function vote() public {votes[msg.sender]++;voters.push(msg.sender); // 每次投票都記錄地址}// 計算總票數(有漏洞!)function countTotalVotes() public view returns (uint) {uint total = 0;// 遍歷所有投票人計算總數for (uint i = 0; i < voters.length; i++) {total += votes[voters[i]];}return total;}
}
攻擊方式:

黑客可以用大量不同的地址反復調用vote(),讓voters數組變得非常長(比如 10 萬個地址)。當有人想調用countTotalVotes()時,遍歷 10 萬個地址需要的 gas 會遠遠超過區塊上限,導致這個函數永遠無法執行。

結果就是:投票系統的計票功能徹底癱瘓

3. 控制關鍵權限 —— 讓合約變成 "死賬戶"

如果合約的核心功能(比如提款、升級)依賴某個單一地址(比如管理員),而這個地址因為私鑰丟失、被黑等原因失控,就會導致合約 "永久停機"。這也算一種特殊的 DoS。

漏洞場景:
contract AdminControl {address public admin; // 管理員地址mapping(address => uint) public balances;constructor() {admin = msg.sender; // 部署者成為管理員}// 提款必須由管理員觸發function withdraw(address to, uint amount) public {require(msg.sender == admin, "不是管理員");(bool success, ) = payable(to).call{value: amount}("");require(success);}
}
攻擊 / 風險方式:

如果管理員的私鑰丟了,或者管理員地址是個合約且該合約功能已失效,那么withdraw()函數就永遠沒人能調用,合約里的資產就成了 "死錢"。

這種情況在實際中很常見,每年都有大量加密資產因為 "管理員私鑰丟失" 而永久凍結。

如何防范拒絕服務攻擊?

針對不同的 DoS 攻擊,有不同的防御方案,但核心原則是:避免單點依賴,控制操作復雜度

1. 解決批量操作問題:化整為零

把一次性的批量操作,拆分成多次小批量操作,即使某一次失敗,也不影響整體。

修復批量退款合約:

contract SafeBatchRefund {address[] public refundees;mapping(address => uint) public amounts;uint public nextIndex; // 記錄下次開始退款的位置function refundBatch(uint batchSize) public {uint end = nextIndex + batchSize;// 防止數組越界if (end > refundees.length) end = refundees.length;// 本次只退batchSize個人for (uint i = nextIndex; i < end; i++) {address payable who = payable(refundees[i]);(bool success, ) = who.call{value: amounts[who]}("");if (success) {nextIndex++; // 只有成功了才更新索引} else {// 失敗了就跳過,下次再試break;}}}
}

這樣即使某個人退款失敗,也能繼續給其他人退款,不會全軍覆沒。

2. 解決 gas 炸彈:限制計算復雜度

  • 避免在合約里寫需要遍歷超長數組的函數
  • 提前計算并限制單次操作的復雜度
  • 重要功能盡量設計成 "常量級" 或 "線性級" 復雜度

修復投票系統:

contract GoodVoting {mapping(address => uint) public votes;uint public totalVotes; // 直接記錄總票數,不用每次計算function vote() public {votes[msg.sender]++;totalVotes++; // 投票時直接更新總數}// 直接返回已記錄的總數,無需遍歷function countTotalVotes() public view returns (uint) {return totalVotes;}
}

3. 解決權限問題:去中心化治理

  • 避免單一管理員,改用多簽錢包(需要多個管理員同意才能操作)
  • 關鍵功能設計成 "時間鎖"(操作需要等待一段時間才能執行,給社區反應時間)
  • 重要合約可以引入 DAO 治理,讓社區共同決定關鍵操作

示例(多簽簡化版):

contract MultiSig {address[] public admins; // 多個管理員uint public required; // 需要多少個管理員同意constructor(address[] memory _admins, uint _required) {admins = _admins;required = _required;}// 提款需要足夠多管理員同意function withdraw(address to, uint amount) public {// 檢查是否有足夠多管理員授權(實際實現更復雜)require(isApprovedByEnoughAdmins(), "同意人數不足");// ... 執行提款 ...}
}

總結:拒絕服務攻擊的本質是 "卡住關鍵流程"

DoS 攻擊不像重入攻擊那樣直接偷錢,但它能讓你的合約徹底失效,造成的損失可能更大(比如無法提款的資金池)。

防范的核心思路是:

  • 別把所有雞蛋放在一個籃子里(避免單點依賴)
  • 復雜操作要拆分(避免一次性處理太多任務)
  • 給系統留 "后路"(失敗了能重試,權限丟了有備選)

寫合約時多問自己:"如果這個功能卡住了,有沒有備用方案?" 能幫你避開大多數 DoS 陷阱。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/96128.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/96128.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/96128.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

安全設計-防止非法移機

前言我們的設備在實際使用過程中&#xff0c;在我們的巡查機制粒度下&#xff0c;發現依然有設備被非法移動到其他非計劃點位。因此&#xff0c;我們需要設計一套及時預警&#xff0c;但是對客戶無感&#xff0c;不影響業務辦理的防范機制。1.方案設計交互圖2.方案說明 2.1方案…

OpenHarmony之三方庫適配深度實踐:從移植到合規的全鏈路指南

1. 為什么要做三方庫適配?——更深層的價值分析 維度 現狀痛點 預期收益 深度價值 生態 成熟開源庫無法直接運行 復用 10+ 年開源沉淀,提升功能覆蓋率 避免生態碎片化:通過標準化適配流程,確保不同廠商對同一庫的實現一致 性能 JS 層重實現耗 CPU 原生 C/C++ 加速 3~10 倍 …

2025年09月計算機二級MySQL選擇題每日一練——第一期

計算機二級中選擇題是非常重要的&#xff0c;所以開始寫一個每日一題的專欄。 答案及解析將在末尾公布&#xff01; 今日主題&#xff1a;MySQL 基礎概念 1、以下關于數據庫的特點中&#xff0c;描述正確的是&#xff08; &#xff09; A. 數據無冗余 B. 數據不可共享&#xff…

JAVA字符串操作——在藍橋杯的基本應用

我們來系統地梳理一下 Java 中的字符串操作。Java 的字符串操作非常豐富&#xff0c;主要涉及到 String、StringBuilder 和 StringBuffer 這三個核心類。 目錄 一、核心類簡介 二、String 類的常用操作 1. 創建字符串 2. 獲取基本信息 3. 比較字符串 4. 查找與判斷 5. 轉…

【深度學習基礎】PyTorch Tensor生成方式及復制方法詳解

目錄PyTorch Tensor生成方式及復制方法詳解一、Tensor的生成方式&#xff08;一&#xff09;從Python列表/元組創建&#xff08;二&#xff09;從NumPy數組創建&#xff08;三&#xff09;特殊初始化方法&#xff08;四&#xff09;從現有Tensor創建&#xff08;五&#xff09;…

動態規劃:入門思考篇

1. 簡單類比 假如我們要求全國人數&#xff0c;那么我們只要知道各個省的人數&#xff0c;然后將各個省的人數相加即可&#xff0c;要想知道各個省的人數&#xff0c;只要將這個省下面所有的市人數相加即可&#xff0c;同樣&#xff0c;如果想要知道各個市的人數&#xff0c;只…

小楊的 X 字矩陣(舉一反三)-洛谷B3865 [GESP202309 二級]

題目描述 小楊想要構造一個 X 字矩陣&#xff08; 為奇數&#xff09;&#xff0c;這個矩陣的兩條對角線都是半角加號 &#xff0c;其余都是半角減號 - 。例如&#xff0c;一個 55 的 X 字矩陣如下&#xff1a; --- --- ---- --- --- 請你幫小楊根據給定的 打印出對應的“X …

數據組合與合并:Pandas 數據整合全指南 +缺失值處理

數據組合與合并&#xff1a;Pandas 數據整合全指南在進行數據分析之前&#xff0c;數據清洗與整合是關鍵步驟。 遵循“整潔數據”&#xff08;Tidy Data&#xff09;原則&#xff1a; 每個觀測值占一行每個變量占一列每種觀測單元構成一張獨立的表格 整理好數據后&#xff0c;常…

c#聯合halcon的基礎教程(案例:亮度計算、角度計算和缺陷檢測)(含halcon代碼)

目錄 1.環境配置 2.案例一&#xff1a;亮度計算 halcon代碼&#xff1a; 主界面代碼&#xff1a; 3.案例二&#xff1a; 角度計算 halcon代碼&#xff1a; 主界面代碼&#xff1a; 4.案例三&#xff1a;缺陷檢測 halcon代碼&#xff1a; 主界面代碼&#xff1a; 通過…

大數據云原生是什么

"云原生"&#xff08;Cloud Native&#xff09;指的是?利用云計算原生優勢&#xff08;彈性、按需服務、自動化、分布式等&#xff09;來設計、構建、部署和運行大數據應用和工作負載的方法論與技術體系?。它不是簡單地“把大數據平臺搬到云上”&#xff0c;而是從…

Pytest項目_day16(yaml和parametrize結合)

查詢手機號歸屬地 我們首先可以在YAML文件中定義測試數據 方式一&#xff0c;使用- 注意&#xff1a;當我們需要一次傳入兩個參數時&#xff0c;需要定義兩層迭代&#xff0c;即兩層列表不夠直觀&#xff0c;容易寫錯 輸出的結果為&#xff1a; 然后我們可以將測試數據傳入test…

【Nginx指南】從核心原理到生產實踐

目錄Nginx指南&#xff1a;從核心原理到生產實踐引言&#xff1a;Nginx在現代架構中的核心地位一、Nginx核心能力與應用場景1.1 多場景適配的全能型中間件1.2 技術優勢&#xff1a;Nginx成為行業標準的關鍵二、Nginx安裝部署&#xff1a;源碼編譯與包管理方案2.1 源碼編譯&…

物體檢測

目錄 1 目標定位 2 地標檢測 3 目標檢測 4 在卷積網絡上實現滑動窗口 5 邊界框預測 6 交并比 7 非極大值抑制 8 錨框 9 YOLO算法 10 用u-net進行語義分割 11 轉置卷積 12 u-net 結構靈感 1 目標定位 你已經對圖片分類有所了解。例如通過這張圖片可以識…

es7.x es的高亮與solr高亮查詢的對比對比說明

一 solr&es高亮1.1 solr與es高亮功能解釋說明&#xff1a;1)高亮配置&#xff1a;fragmentSize(1000) 設置片段長度numOfFragments(1) 指定返回的片段數量preTags() 和 postTags() 設置高亮標記2)字段處理差異&#xff1a;在 ES 中&#xff0c;使用 matchQuery 而非 termQ…

DSP音頻算法工程師技能2

一、核心知識準備1. 算法原理3A算法&#xff08;AGC自動增益控制/AEC回聲消除/ANS降噪&#xff09;&#xff1a;掌握AEC的NLMS/雙講檢測原理&#xff0c;ANS的譜減法/維納濾波&#xff0c;AGC的壓縮曲線設計。熟悉Speex/WebRTC等開源實現。EQ音效&#xff1a;IIR/FIR濾波器設計…

第4章-04-用WebDriver頁面元素操作

??作者簡介,黑夜開發者,CSDN領軍人物,全棧領域優質創作者?,CSDN博客專家,阿里云社區專家博主,2023年CSDN全站百大博主。 ??數年電商行業從業經驗,歷任核心研發工程師,項目技術負責人。 ??本文已收錄于專欄:Web爬蟲入門與實戰精講,后續完整更新內容如下。 文章…

【計算機視覺與深度學習實戰】04基于K-Means聚類的圖像分割系統設計與實現

摘要 圖像分割作為計算機視覺領域的基礎任務,在目標檢測、醫學影像分析、自動駕駛等眾多應用中發揮著關鍵作用。本文基于K-Means聚類算法設計并實現了一個完整的圖像分割系統,該系統集成了多種顏色空間轉換、自定義初始化策略、空間特征融合等先進技術。通過Python和Tkinter…

Android Studio常用知識總結

一、運行方式1.運行 (Run)當您選擇“運行”時&#xff0c;Android Studio 會編譯您的應用并將其安裝到目標設備或模擬器上。這通常用于&#xff1a;快速部署: 您只想看看應用是否能正常啟動并運行&#xff0c;或者進行一些基礎的用戶界面測試。性能測試: 在正常運行模式下測試應…

設計模式筆記_行為型_訪問者模式

1. 訪問者模式介紹訪問者模式&#xff08;Visitor Pattern&#xff09;是一種行為型設計模式&#xff0c;它允許你在不改變對象結構的前提下&#xff0c;定義作用于這些對象的新操作。訪問者模式將操作的邏輯從對象結構中分離出來&#xff0c;使得你可以在運行時動態地添加新的…

數學建模 14 中心對數比變換

用途&#xff1a;是處理成分數據的核心預處理方法&#xff0c;核心目標是解決成分數據的和為常數100% &#xff0c; 導致的維度冗余&#xff0c;非線性相關問題。使得數據滿足傳統的統計/建模方法&#xff1b;舉例子&#xff1a;食品比例中 面粉(50%),糖(30%),水(20%)原理&…