huichain/smart-contract-security-lab
GitHub: huichain/smart-contract-security-lab
基于 Foundry 的智能合约安全学习实验室,通过复现真实漏洞、编写 PoC 和提出修复方案帮助开发者系统掌握合约安全技术。
Stars: 0 | Forks: 0
# 智能合约安全实验室
一个基于 Foundry 的实验室,旨在通过复现真实漏洞、编写 PoC 和提出修复方案来学习智能合约安全。
本仓库是**日积月累**构建的,而非一蹴而就。
每天添加一个小而完整的片段:一个存在漏洞的合约、一个攻击者、一个修复方案或一份报告。
## 状态
- ✅ **Reentrancy** 模块完成 — 包含漏洞合约、攻击者、修复方案、3 个通过的测试、审计风格报告
- ✅ **Access Control** 模块完成 — 包含漏洞及修复合约、5 个通过的测试、审计风格报告
- ✅ **Signature Replay** 模块完成 — 包含漏洞空投、修复实现、3 个通过的测试、审计风格报告
- ✅ **Oracle Manipulation** 模块完成 — 包含漏洞及修复的借贷、TWAP 预言机、4 个通过的测试、审计风格报告
- ✅ **Upgradeable Proxy** 模块完成 — 包含 initializer PoC + storage-layout 碰撞 PoC、修复实现、9 个通过的测试、审计风格报告
## Reentrancy — 漏洞金库、漏洞利用 PoC、修复及报告
- [x] `src/reentrancy/VulnerableVault.sol`
一个最小化的 ETH 金库,它**在**更新用户余额**之前**将 ETH 发送给用户,这使其容易受到重入攻击。
- [x] `src/reentrancy/ReentrancyAttacker.sol`
攻击者合约,从 `receive()` 重入 `withdraw` 以抽干金库。
- [x] `src/reentrancy/FixedVault.sol`
使用 checks-effects-interactions 模式和 OpenZeppelin 的 `ReentrancyGuard`(深度防御)强化的金库。
- [x] `test/reentrancy/ReentrancyPoC.t.sol`
Foundry PoC 测试套件:
- `testExploit_DrainsVault` — 攻击者利用 1 ETH 的攻击资金抽干了拥有 10 ETH 的金库
- `testFix_BlocksReentrancy` — 同样的攻击者针对 `FixedVault` 发起交易会 revert,受害者的资金保持安全
- `testFix_AllowsHonestWithdraw` — 完整性检查,确认修复方案不会破坏正常用户的使用
- [x] [`reports/01-reentrancy.md`](reports/01-reentrancy.md)
审计风格报告:严重程度、摘要、根本原因、PoC、建议、修复实现和经验教训。
## Access Control — 漏洞金库、漏洞利用 PoC、修复
- [x] `src/access-control/VulnerableTreasury.sol`
一个带有 `owner` 字段的协议金库,但 `withdraw` 和 `setOwner` **没有权限检查** — 这是两个独立的漏洞。
- [x] `src/access-control/FixedTreasury.sol`
使用 OpenZeppelin `Ownable` 和在敏感函数上使用 `onlyOwner` 强化的金库(无需单独的攻击者合约;EOA 即可利用漏洞版本)。
- [x] `test/access-control/AccessControlPoC.t.sol`
Foundry PoC 测试套件:
- `testExploit_AnyoneCanDrainTreasury` — 任何账户都可以调用 `withdraw` 并抽干所有 ETH
- `testExploit_AnyoneCanBecomeOwner` — 任何账户都可以调用 `setOwner` 并夺取所有权
- `testFix_BlocksUnauthorizedWithdraw` — 攻击者调用 `withdraw` 会因 `OwnableUnauthorizedAccount` revert
- `testFix_BlocksUnauthorizedSetOwner` — 攻击者调用 `setOwner` 会 revert;owner 保持不变
- `testFix_AllowsOwnerFunctions` — 合法的 owner 仍然可以提款和转移所有权
- [x] [`reports/02-access-control.md`](reports/02-access-control.md)
审计风格报告:两个发现(`withdraw`、`setOwner`)、严重程度、PoC、建议、修复实现和经验教训。
## Signature Replay — 漏洞空投、重放 PoC、修复及报告
- [x] `src/signature-replay/VulnerableAirdrop.sol`
一个故意留下漏洞的 ETH 空投,接受来自受信任签名者的链下签名,但签名消息仅绑定了 `account` 和 `amount`。
- [x] `test/signature-replay/SignatureReplayPoC.t.sol`
Foundry PoC 测试套件:
- `testExploit_SameSignatureClaimsTwice` — 两次重复使用完全相同的签名,并证明领取者收到了两次空投
- `testFix_BlocksSignatureReplay` — 证明修复后的合约消耗了用户的 nonce 并拒绝了重放的签名
- `testFix_RejectsExpiredSignature` — 证明过期的签名无法被使用
- [x] `src/signature-replay/FixedAirdrop.sol`
修复实现:将签名绑定到 nonce、deadline、chain id 和 `address(this)`。
- [x] [`reports/03-signature-replay.md`](reports/03-signature-replay.md)
审计风格报告:严重程度、重放影响、根本原因、PoC、建议、修复实现和经验教训。
## Oracle Manipulation — AMM 即时价格 PoC
- [x] `src/oracle-manipulation/SimpleAMM.sol`
一个故意简化的恒定乘积 AMM,其即时价格可以通过改变储备金来操纵。
- [x] `src/oracle-manipulation/VulnerableLending.sol`
一个玩具借贷市场,直接信任 AMM 即时价格来计算借款能力。
- [x] `src/oracle-manipulation/TWAPOracle.sol`
记录累积的 AMM 价格,以便借贷可以查询时间加权平均值而不是即时价格。
- [x] `src/oracle-manipulation/FixedLending.sol`
强化的借贷市场,使用 `TWAPOracle.consult()` 而不是 `getSpotPrice()` 对抵押品进行定价。
- [x] `test/oracle-manipulation/OracleManipulationPoC.t.sol`
Foundry PoC 测试套件:
- `testExploit_SpotPriceManipulationInflatesBorrowLimit` — 证明操纵 AMM 即时价格会抬高借款限额并抽干流动性池
- `testNormalPriceOnlyAllowsLimitedBorrow` — 完整性检查,显示正常价格只允许小得多的借款
- `testFix_BlocksSpotPriceManipulation` — 证明使用 TWAP 定价时,相同的操纵无法抽干资金池
- `testFix_AllowsHonestBorrow` — 完整性检查,确认正常用户仍然可以以 TWAP 价格借款
- [x] [`reports/04-oracle-manipulation.md`](reports/04-oracle-manipulation.md)
审计风格报告:严重程度、即时价格预言机风险、根本原因、PoC、TWAP 缓解措施、修复实现和经验教训。
## Upgradeable Proxy — 最小化代理、Initialize PoC、修复
- [x] `src/upgradeable-proxy/SimpleProxy.sol`
最小化的 EIP-1967 风格代理:`fallback` 通过 `delegatecall` 将调用转发给实现合约。
- [x] `src/upgradeable-proxy/ImplementationV1.sol`
带有故意未受保护的 `initialize()` 的逻辑合约 — 任何人都可以设置或覆盖代理存储中的 `owner`。
- [x] `src/upgradeable-proxy/FixedImplementationV1.sol`
使用 OpenZeppelin `Initializable` 强化的逻辑合约:一次性 `initializer` 以及在实现合约上调用 `_disableInitializers()`。
- [x] `test/upgradeable-proxy/ProxyPoC.t.sol`
Foundry PoC 测试套件:
- `testExploit_UnprotectedInitializeLetsAttackerTakeOwnership` — 攻击者通过代理调用 `initialize` 并夺取 `owner`
- `testExploit_AttackerCanReinitializeAndOverwriteOwner` — 攻击者在管理员之后重新初始化并覆盖所有权
- `testFix_BlocksReinitialize` — 证明重放的 `initialize` 调用会 revert,并且所有权仍归管理员所有
- `testFix_AllowsLegitimateInit` — 完整性检查,确认合法的初始化和所有者流程仍然有效
- `testFix_BlocksDirectInitializeOnImplementation` — 证明裸实现合约不能被直接初始化
- [x] [`reports/05-upgradeable-proxy.md`](reports/05-upgradeable-proxy.md)
审计风格报告:未受保护的 initializer 风险、delegatecall 存储模型、PoC、`Initializable` 缓解措施和经验教训。
- [x] `src/upgradeable-proxy/ImplementationV2.sol`
故意不安全的 V2,更改了存储顺序并演示了升级后的 slot 重新解释。
- [x] `src/upgradeable-proxy/FixedImplementationV2.sol`
安全的 V2,保留了 V1 的布局并追加了新变量。
- [x] `test/upgradeable-proxy/StorageLayoutPoC.t.sol`
Foundry PoC 测试套件:
- `testExploit_UpgradeToBadLayoutCorruptsOwnerAndValue` — 证明 slot 重新解释会破坏 owner/value 的语义
- `testExploit_AdminLosesPrivilegesAfterBadUpgrade` — 证明在不兼容的升级后,管理员失去了仅限所有者的访问权限
- `testFix_CompatibleLayoutPreservesOwnerAndValueAcrossUpgrade` — 证明布局安全的 V2 保持状态完好无损
- `testFix_OnlyOwnerCanRunV2Initializer` — 证明 V2 initializer 受到所有者权限控制,并且适用于合法的管理员
- [x] [`reports/06-storage-layout-collision.md`](reports/06-storage-layout-collision.md)
审计风格报告:存储碰撞根本原因、升级 PoC、缓解措施和验证。
## 项目结构
```
smart-contract-security-lab/
├─ foundry.toml # Foundry config + remappings
├─ foundry.lock # Locked dependency versions
├─ .gitmodules # Git submodules (forge-std, openzeppelin-contracts)
├─ .gitignore
├─ remappings.txt # IDE-friendly remappings (mirrors foundry.toml)
├─ README.md
├─ lib/
│ ├─ forge-std/ # Foundry standard testing library (submodule)
│ └─ openzeppelin-contracts/ # OpenZeppelin Solidity library (submodule)
├─ src/
│ ├─ reentrancy/
│ │ ├─ VulnerableVault.sol
│ │ ├─ ReentrancyAttacker.sol
│ │ └─ FixedVault.sol
│ ├─ access-control/
│ │ ├─ VulnerableTreasury.sol
│ │ └─ FixedTreasury.sol
│ ├─ oracle-manipulation/
│ │ ├─ SimpleAMM.sol
│ │ ├─ VulnerableLending.sol
│ │ ├─ TWAPOracle.sol
│ │ └─ FixedLending.sol
│ ├─ signature-replay/
│ │ ├─ VulnerableAirdrop.sol
│ │ └─ FixedAirdrop.sol
│ └─ upgradeable-proxy/
│ ├─ SimpleProxy.sol
│ ├─ ImplementationV1.sol
│ ├─ FixedImplementationV1.sol
│ ├─ ImplementationV2.sol
│ └─ FixedImplementationV2.sol
├─ test/
│ ├─ reentrancy/
│ │ └─ ReentrancyPoC.t.sol
│ ├─ access-control/
│ │ └─ AccessControlPoC.t.sol
│ ├─ oracle-manipulation/
│ │ └─ OracleManipulationPoC.t.sol
│ ├─ signature-replay/
│ │ └─ SignatureReplayPoC.t.sol
│ └─ upgradeable-proxy/
│ ├─ ProxyPoC.t.sol
│ └─ StorageLayoutPoC.t.sol
└─ reports/
├─ 01-reentrancy.md
├─ 02-access-control.md
├─ 03-signature-replay.md
├─ 04-oracle-manipulation.md
├─ 05-upgradeable-proxy.md
└─ 06-storage-layout-collision.md
```
## 依赖项
- [Foundry](https://book.getfoundry.sh)
- [forge-std](https://github.com/foundry-rs/forge-std) `v1.16.1` — Foundry 标准测试库
- [OpenZeppelin Contracts](https://github.com/OpenZeppelin/openzeppelin-contracts) `v5.6.1` — 在修复版本中使用的久经考验的 Solidity 组件(Ownable、ReentrancyGuard、ECDSA 等)
所有依赖项都作为 git submodule 安装在 `lib/` 下,并锁定在 `foundry.lock` 中。
## 快速开始
### 1. 安装 Foundry
请根据您的操作系统遵循官方安装指南:
https://book.getfoundry.sh/getting-started/installation
快速参考:
```
# macOS / Linux / WSL
curl -L https://foundry.paradigm.xyz | bash
foundryup
```
```
# Windows (PowerShell)
powershell -c "irm https://foundry.paradigm.xyz/install.ps1 | iex"
foundryup
```
### 2. 使用 submodule 克隆
```
git clone --recurse-submodules https://github.com/huichain/smart-contract-security-lab.git
cd smart-contract-security-lab
```
如果您已经克隆但没有包含 submodule:
```
git submodule update --init --recursive
```
### 3. 构建
```
forge build
```
### 4. 测试
该实验室目前提供了涵盖五个漏洞模块的 **24 个通过的测试**。
**Reentrancy** (`test/reentrancy/`):
- `testExploit_DrainsVault` — 证明攻击者用 1 ETH 的资金抽干了 10 ETH 的金库。
- `testFix_BlocksReentrancy` — 证明相同的攻击针对 `FixedVault` 会 revert。
- `testFix_AllowsHonestWithdraw` — 完整性检查,确认正常用户仍然可以工作。
**Access Control** (`test/access-control/`):
- `testExploit_AnyoneCanDrainTreasury` — 证明任何人都可以通过 `withdraw` 抽干金库。
- `testExploit_AnyoneCanBecomeOwner` — 证明任何人都可以通过 `setOwner` 夺取所有权。
- `testFix_BlocksUnauthorizedWithdraw` — 证明 `FixedTreasury` 会阻止未经授权的提款。
- `testFix_BlocksUnauthorizedSetOwner` — 证明未经授权的所有权转移会 revert。
- `testFix_AllowsOwnerFunctions` — 完整性检查,确认所有者仍然可以管理金库。
**Signature Replay** (`test/signature-replay/`):
- `testExploit_SameSignatureClaimsTwice` — 证明同一个签名可以被重放以两次认领。
- `testFix_BlocksSignatureReplay` — 证明消耗 nonce 会阻止重放同一个签名。
- `testFix_RejectsExpiredSignature` — 证明签名在截止时间之后无法使用。
**Oracle Manipulation** (`test/oracle-manipulation/`):
- `testExploit_SpotPriceManipulationInflatesBorrowLimit` — 证明操纵 AMM 即时价格会抬高借款能力。
- `testNormalPriceOnlyAllowsLimitedBorrow` — 证明未被操纵的价格会强制执行预期的较低借款限额。
- `testFix_BlocksSpotPriceManipulation` — 证明 TWAP 定价会阻止相同的即时价格操纵攻击。
- `testFix_AllowsHonestBorrow` — 证明正常用户仍然可以以 TWAP 价格借款。
**Upgradeable Proxy** (`test/upgradeable-proxy/`):
- `testExploit_UnprotectedInitializeLetsAttackerTakeOwnership` — 证明未受保护的 `initialize()` 会让攻击者夺取代理所有权。
- `testExploit_AttackerCanReinitializeAndOverwriteOwner` — 证明公开的 initializer 可以覆盖现有的所有者。
- `testFix_BlocksReinitialize` — 证明修复后的实现会阻止重放的初始化。
- `testFix_AllowsitimateInit` — 证明合法的管理员初始化仍然有效。
- `testFix_BlocksDirectInitializeOnImplementation` — 证明逻辑合约地址不能被直接初始化。
- `testExploit_UpgradeToBadLayoutCorruptsOwnerAndValue` — 证明不兼容的 V2 存储布局会重新解释现有的代理状态。
- `testExploit_AdminLosesPrivilegesAfterBadUpgrade` — 证明在错误的升级后管理员会失去仅限所有者的特权。
- `testFix_CompatibleLayoutPreservesOwnerAndValueAcrossUpgrade` — 证明兼容的 V2 在升级后保持 owner/value 不变。
- `testFix_OnlyOwnerCanRunV2Initializer` — 证明只有所有者才能运行 V2 的 reinitializer。
运行所有测试:
```
forge test
```
运行单个模块:
```
forge test --match-path test/access-control/AccessControlPoC.t.sol -vv
```
## 路线图(高层级)
| 漏洞 | 状态 |
| --- | --- |
| Reentrancy | ✅ 完成 — 漏洞合约 + 攻击者 + 修复 + 测试 + 报告 |
| Access Control | ✅ 完成 — 漏洞合约 + 修复 + 测试 + 报告 |
| Signature Replay | ✅ 完成 — 漏洞合约 + 修复空投 + 测试 + 报告 |
| Oracle Manipulation | ✅ 完成 — 漏洞合约 + TWAP 修复 + 测试 + 报告 |
| Upgradeable Proxy | ✅ 完成 — initializer + storage-layout PoC、修复的 V1/V2、9 个测试、2 份报告 |
## 关于作者
具有 C++ / C# 背景的软件工程师,正在向智能合约安全和 Web3 工具领域转型。
- GitHub: [huichain](https://github.com/huichain)
- X: [@vividhui](https://x.com/vividhui)
标签:Foundry, Solidity, 区块链安全, 智能合约, 漏洞复现