MilosMicun/solidity-security-patterns
GitHub: MilosMicun/solidity-security-patterns
展示 Solidity 智能合约经典安全模式的漏洞利用、修复方案和不变量验证的实战教学仓库。
Stars: 0 | Forks: 0
# Solidity 安全模式
本仓库模拟了 Solidity 系统中的真实故障模式,并演示了它们是如何被利用、缓解和衡量的。
每个模块遵循相同的准则:
- 破坏系统
- 证明漏洞利用
- 应用修复
- 验证不变量
重点不在于模式本身——而在于 EVM 约束下的决策制定:正确性、安全性和成本。
## 为什么这很重要
这些漏洞并非理论上的:
- 重入攻击 已经耗尽了协议资金
- 访问控制漏洞 已导致全部资金损失
- MEV 漏洞 在生产环境中重新排序执行
- Gas 低效率 直接影响协议的生存能力
理解这些权衡是在链上交付安全系统的必要条件。
## 系统概述
该仓库包含成对的实现:
- 易受攻击的合约(真实攻击面)
- 安全版本(已应用缓解措施)
- 证明可利用性和正确性的测试套件
重点关注领域:
- 重入攻击
- 算术安全
- 访问控制
- 交易排序 (MEV)
- Gas 优化
## 安全案例研究
### 重入攻击
**漏洞**
状态在外部调用之后更新。
**利用**
攻击者在余额清除之前通过 `receive()` 重新进入 `withdraw()`,耗尽资金。
**根本原因**
控制流在状态转换完成之前被转移。
**不变量违规**
用户余额必须在任何外部交互之前减少。
### 重入攻击缓解
**修复策略**
- **Checks-Effects-Interactions (CEI)** (检查-生效-交互模式)
消除根本原因。
- **ReentrancyGuard** (重入守卫)
在运行时阻止嵌套执行。
**验证**
- 漏洞利用在易受攻击的合约上成功
- 漏洞利用在受保护的实现上失败
**洞察**
重入攻击不是竞态条件——它是一个控制流问题。
安全性需要:
- 正确的状态排序
- 运行时强制执行
### 整数算术
**比较的模型**
- Legacy (传统,回绕)
- Checked (已检查,Solidity 0.8+)
- Unchecked (未检查,手动负责)
**根本原因**
EVM 使用模运算 (`mod 2²⁵⁶`)。
安全性由编译器引入,而非执行层。
**故障模式**
无边界检查的算术运算会导致无声的状态损坏。
**不变量**
算术运算必须保持在定义的系统边界内。
**洞察**
溢出并没有被消除——它被抽象在编译器检查之后。
### 访问控制
**漏洞**
缺少授权导致:
- 所有权被夺取
- 无限制的提款
**根本原因**
授权边界未被执行。
**故障模式**
未经授权的行为者可以改变状态并提取资金。
**修复**
- `onlyOwner` 修饰符
- 自定义错误
**不变量**
只有授权实体才能执行特权操作。
### tx.origin 反模式
**漏洞**
基于 `tx.origin` 的授权。
**利用**
恶意合约转发调用:
- `tx.origin` = 受害者
- `msg.sender` = 攻击者
检查通过 → 攻击者获得访问权限。
**修复**
使用 `msg.sender`。
**洞察**
授权必须遵循执行上下文,而非交易来源。
### MEV / 前置交易
**漏洞**
用户输入在执行前在 mempool 中可见。
攻击者可以通过出价更高的 Gas 来重新排序交易。
**根本原因**
执行排序是对抗性的。
**故障模式**
状态转换依赖于公开可观察的输入。
### Commit-Reveal (提交-揭示) 缓解
**方法**
- commit (隐藏意图)
- reveal (验证执行)
```
keccak256(abi.encodePacked(msg.sender, value, salt))
```
**安全属性**
- 隐藏意图
- 将承诺绑定到发送者
- 防止复制攻击
**局限性**
不保证公平性——仅消除了反应性优势。
**不变量**
结果决不能依赖于执行前的可观察输入。
**洞察**
安全性有时需要隐藏信息,而不是验证它。
## Gas 分析
优化不仅仅是编写更简洁的代码——它关乎减少昂贵的 EVM 操作。
### 结果
| Function | Inefficient | Optimized | Δ Gas | Δ % |
|---|---|---|---|---|
| Deployment | 564860 | 462483 | -102377 | -18.1% |
| sumBalanceTimes | 6963 | 3906 | -3057 | -43.9% |
| sumNumbers | 17858 | 15190 | -2668 | -14.9% |
| setNumbers | 158984 | 157450 | -1534 | -1.0% |
| setBalance | 44437 | 44437 | 0 | 0% |
### 解读
**sumBalanceTimes (-44%)**
通过缓存消除重复的 SLOAD。
**sumNumbers (-15%)**
减少循环和内存开销。
**setNumbers (-1%)**
受 SSTORE 主导。写入开销超过了优化。
**Deployment (-18%)**
通过 `immutable` 和自定义错误减少。
### 关键洞察
Gas 成本遵循 EVM 原语:
- 优化 SLOAD → 高影响
- 优化 SSTORE → 有限影响
- 优化语法 → 边际收益
### 局限性
优化无法解决:
- 昂贵的存储写入
- 糟糕的状态建模
- 写入密集型设计
如果模型本身效率低下,优化无法修复它。
## 工程原则
- 状态是主要的攻击面
- 执行顺序定义安全边界
- 外部调用转移控制权
- 授权必须是显式的
- 编译器安全性不是保证
- 存储主导成本
- 优化前先测量
## 项目结构
```
solidity-security-patterns/
├── src/
│ ├── gas/
│ │ ├── GasInefficient.sol
│ │ └── GasOptimized.sol
│ ├── mev/
│ │ ├── VulnerableGame.sol
│ │ └── CommitRevealGame.sol
│ ├── AccessControlVulnerable.sol
│ ├── AccessControlFixed.sol
│ ├── AccessControlBrokenTxOrigin.sol
│ ├── Attacker.sol
│ ├── TxOriginAttacker.sol
│ ├── OverflowLegacy.sol
│ ├── OverflowUnchecked.sol
│ ├── OverflowChecked.sol
│ ├── VulnerableBank.sol
│ ├── GuardedBank.sol
│ └── SafeBank.sol
├── test/
│ ├── gas/
│ │ └── GasOptimization.t.sol
│ ├── mev/
│ │ ├── VulnerableGame.t.sol
│ │ └── CommitRevealGame.t.sol
│ ├── AccessControl.t.sol
│ ├── AccessControlTxOrigin.t.sol
│ ├── Overflow.t.sol
│ └── Reentrancy.t.sol
├── foundry.toml
└── README.md
```
## 运行测试
```
forge test
forge test --match-path test/Reentrancy.t.sol
forge test --match-path test/AccessControl.t.sol
forge test --match-path test/mev/VulnerableGame.t.sol
forge test --match-path test/gas/GasOptimization.t.sol --gas-report
```
## 技术栈
- [Foundry](https://book.getfoundry.sh/)
- Solidity `^0.8.20`
- WSL2 / Ubuntu
标签:CEI 模式, CISA项目, DeFi 安全, EVM, Foundry, Gas 优化, MEV, Solidity, Streamlit, Web3 安全, Web报告查看器, 不变量测试, 以太坊, 区块链安全, 安全模式, 整数溢出, 智能合约审计, 漏洞复现, 访问控制, 重入攻击