Skip to main content

dos-attack

Auto-loaded by logic-auditor agent during Phase 2. Provides detection patterns for: gas griefing, unbounded loops, external call failures, block gas limit exploitation, storage DoS, and liveness failures. Core artifact: Liveness Analysis Map.

跳到安装

来源信息

仓库
BitterSecurity/Vigilo
最近来源活动
2026年2月2日 05:07
检测到的 SKILL.md 语言
英语
星标
66
分支
17

安装方式

默认使用会先检查来源的 Prompt;你也可以切换为直接命令,或下载本地副本。

检查来源文件

决定是否安装前,请先阅读 SKILL.md,以及 SkillsMP 当前展示的配套文件。

正在显示 SKILL.md

SKILL.md
来源说明 · 只读预览
name
dos-attack
description
Auto-loaded by logic-auditor agent during Phase 2. Provides detection patterns for: gas griefing, unbounded loops, external call failures, block gas limit exploitation, storage DoS, and liveness failures. Core artifact: Liveness Analysis Map.
user-invocable
false
# Denial of Service (DoS) Attack Patterns **OWASP SC10:2025** - DoS attacks prevent legitimate users from accessing protocol functionality, potentially locking funds permanently. **2025-2026 Statistics**: DoS vulnerabilities caused protocol freezes affecting $180M+ in locked funds, with gas griefing attacks increasing 45% YoY. --- ## Why DoS Happens (Root Causes) ### Root Cause 1: Unbounded Iteration Loops without gas limits become unusable as data grows. ```solidity // VULNERABLE: Unbounded loop function distributeRewards() external { for (uint256 i = 0; i < holders.length; i++) { // @audit holders can grow unbounded token.transfer(holders[i], rewards[holders[i]]); } } ``` **Attacker's view**: "I'll create thousands of tiny positions. Eventually, no one can call this function." ### Root Cause 2: External Call Dependency Function success depends on external call that attacker can make fail. ```solidity // VULNERABLE: Relies on external transfer success function withdrawAll() external { for (uint256 i = 0; i < users.length; i++) { payable(users[i]).transfer(balances[users[i]]); // @audit One revert blocks all } } ``` **Attacker's view**: "If I'm in the array and my receive() reverts, nobody gets paid." ### Root Cause 3: Storage Slot Exhaustion Unlimited storage growth makes operations cost-prohibitive. ```solidity // VULNERABLE: Unlimited storage growth mapping(address => uint256[]) public userDeposits; function deposit() external payable { userDeposits[msg.sender].push(msg.value); // @audit Array grows forever } function getTotalDeposits(address user) external view returns (uint256) { uint256 total; for (uint256 i = 0; i < userDeposits[user].length; i++) { // @audit View can run out of gas total += userDeposits[user][i]; } return total; } ``` ### Root Cause 4: Block Gas Limit Exploitation Transaction exceeds block gas limit, making it impossible to execute. ```solidity // VULNERABLE: Can exceed block gas limit function processAllPending() external { while (pendingQueue.length > 0) { _processSingle(pendingQueue[0]); pendingQueue.pop(); } } ``` --- ## The Liveness Analysis Map (Core Artifact) For each critical function, document: ``` Function: withdrawAll() ├── External Calls: N calls to user addresses ├── Loop Bound: users.length (unbounded) ├── Gas Estimate: O(n) where n = users count ├── Failure Mode: Single revert blocks all withdrawals ├── Recovery: None - funds permanently locked └── Risk: CRITICAL ``` | Function | Dependency | Bound | Failure Impact | Recovery | |----------|------------|-------|----------------|----------| | distributeRewards | N transfers | Unbounded | Protocol freeze | None | | processQueue | Queue size | Bounded (100) | Temporary delay | Retry | | batchLiquidate | M liquidations | User-controlled | Partial failure | Continue | --- ## Detection Patterns ### Pattern 1: Unbounded Loop DoS **Root Cause**: Unbounded Iteration ```solidity // VULNERABLE: Loop over dynamic array function processAll() external { for (uint256 i = 0; i < items.length; i++) { _process(items[i]); } } ``` **Attack Flow**: 1. Attacker adds many small items to array 2. Array grows to thousands of entries 3. Gas cost exceeds block limit 4. Function becomes uncallable 5. Funds/operations permanently stuck **Search Queries**: ``` Grep("for.*\\.length|while.*\\.length", glob="**/*.sol") Grep("for.*i\\+\\+|for.*i < ", glob="**/*.sol") ``` **Mitigation**: ```solidity // SECURE: Pagination pattern function processRange(uint256 start, uint256 end) external { require(end <= items.length && end - start <= MAX_BATCH); for (uint256 i = start; i < end; i++) { _process(items[i]); } } ``` ### Pattern 2: External Call Failure DoS **Root Cause**: External Call Dependency ```solidity // VULNERABLE: One failure blocks all function refundAll() external { for (uint256 i = 0; i < refundees.length; i++) { (bool success,) = refundees[i].call{value: amounts[i]}(""); require(success, "Refund failed"); // @audit Blocks on any failure } } ``` **Attack Flow**: 1. Attacker enters system with contract that reverts on receive 2. Refund function iterates to attacker's address 3. Attacker's receive() reverts 4. Entire function reverts 5. All refunds blocked **Search Queries**: ``` Grep("\\.call\\{value.*require\\(success", glob="**/*.sol") Grep("\\.transfer\\(|send\\(", glob="**/*.sol") ``` **Mitigation**: ```solidity // SECURE: Pull pattern mapping(address => uint256) public pendingRefunds; function withdraw() external { uint256 amount = pendingRefunds[msg.sender]; pendingRefunds[msg.sender] = 0; (bool success,) = msg.sender.call{value: amount}(""); require(success); } ``` ### Pattern 3: Gas Griefing **Root Cause**: Unchecked Gas Forwarding ```solidity // VULNERABLE: Forwards all gas to untrusted call function executeCallback(address target, bytes calldata data) external { (bool success,) = target.call(data); // @audit Attacker can consume all gas require(success); } ``` **Attack Flow**: 1. Attacker creates contract with expensive fallback 2. Callback executes, consuming all forwarded gas 3. Parent transaction fails or behaves unexpectedly 4. Griefing attack succeeds **Search Queries**: ``` Grep("\\.call\\(|\\.delegatecall\\(", glob="**/*.sol") Grep("gasleft\\(\\)", glob="**/*.sol") ``` **Mitigation**: ```solidity // SECURE: Limit gas forwarded (bool success,) = target.call{gas: 50000}(data); // OR use try/catch try ICallback(target).callback{gas: 50000}(data) {} catch {} ``` ### Pattern 4: Block Stuffing **Risk**: Attacker fills blocks to prevent time-sensitive operations ```solidity // VULNERABLE: Time-sensitive operation function claimAuction() external { require(block.timestamp >= auctionEnd, "Auction ongoing"); require(!claimed, "Already claimed"); claimed = true; // Transfer winning bid... } ``` **Attack Flow**: 1. Attacker sees they're losing auction 2. Before auction ends, attacker submits many high-gas transactions 3. Blocks become full, legitimate claimAuction() can't execute 4. Attacker extends effective auction time 5. Eventually claims at manipulated state **Mitigation**: - Add grace periods for time-sensitive operations - Use commit-reveal for auctions - Allow partial execution ### Pattern 5: Storage Collision DoS **Root Cause**: Unlimited Mapping/Array Growth ```solidity // VULNERABLE: Unlimited storage per user function addOrder(uint256 amount) external { userOrders[msg.sender].push(Order(amount, block.timestamp)); } function cancelAllOrders() external { delete userOrders[msg.sender]; // @audit Gas increases with array size } ``` **Attack Flow**: 1. Attacker creates millions of tiny orders 2. Tries to cancel all (or system tries to process) 3. Gas exceeds limits 4. Operations blocked **Search Queries**: ``` Grep("push\\(|delete.*\\[", glob="**/*.sol") Grep("mapping.*\\[\\]|address.*=>.*\\[\\]", glob="**/*.sol") ``` ### Pattern 6: Return Bomb Attack **Root Cause**: Unbounded Return Data ```solidity // VULNERABLE: Copies all return data function executeCall(address target, bytes calldata data) external returns (bytes memory) { (bool success, bytes memory result) = target.call(data); // @audit result can be huge require(success); return result; } ``` **Attack Flow**: 1. Attacker creates contract returning massive data (e.g., 1MB) 2. Memory expansion costs explode 3. Transaction runs out of gas 4. Call fails unexpectedly **Mitigation**: ```solidity // SECURE: Limit return data or use assembly assembly { let success := call(gas(), target, 0, add(data, 32), mload(data), 0, 0) // Only copy limited return data if needed } ``` --- ## DoS Prevention Checklist ### Loop Safety - [ ] All loops have bounded iterations - [ ] Maximum batch size enforced - [ ] Pagination available for large datasets - [ ] Gas estimation includes worst case ### External Call Safety - [ ] Pull pattern over push pattern - [ ] Individual call failures don't block others - [ ] Gas limits on external calls - [ ] Fallback handling for failed transfers ### Storage Safety - [ ] No unbounded arrays per user - [ ] Cleanup mechanisms exist - [ ] View functions handle large data ### Time Safety - [ ] Grace periods for time-sensitive ops - [ ] No strict time windows attackers can exploit - [ ] Block stuffing resistance --- ## Search Query Reference ``` # Find unbounded loops Grep("for.*\\.length|while.*length", glob="**/*.sol") Grep("for.*i\\+\\+.*\\{", glob="**/*.sol") # Find external calls Grep("\\.call\\{|\\.transfer\\(|\\.send\\(", glob="**/*.sol") Grep("require\\(success", glob="**/*.sol") # Find storage patterns Grep("push\\(|pop\\(|delete", glob="**/*.sol") Grep("mapping.*\\[\\]", glob="**/*.sol") # Find time dependencies Grep("block\\.timestamp|block\\.number", glob="**/*.sol") ``` --- ## Severity Classification ### Critical - Funds permanently locked - Core protocol functions uncallable - No recovery mechanism ### High - Temporary protocol freeze possible - Significant gas griefing impact - User funds at risk ### Medium - View functions can fail - Minor operations blockable - Recovery exists but costly --- ## Rationalization Table (Reject These Excuses) | Excuse | Reality | |--------|---------| | "Array won't grow that large" | Attackers WILL grow it. Assume worst case. | | "Users won't create malicious contracts" | Attackers absolutely will. Every address is suspect. | | "Gas is cheap" | Block gas limit is fixed. 30M gas max per block. | | "We can upgrade if needed" | Funds may be locked BEFORE you can upgrade. | | "This is theoretical" | Akropolis, SpankChain, and others lost millions to DoS. | | "View functions don't matter" | External protocols depend on your views. DoS spreads. |
在 GitHub 查看