安全审计 笔记合集

简介 Web3,作为一个以去中心化为核心理念的新一代互联网范式,其基石建立在区块链技术——一个不可篡改、透明公开的分布式账本之上。这个账本通过精密的共识机制确保网络参与者能够在无需相互信任的情况下达成一致,这无疑是革命性的 然而,这种“不可篡改”的特性是一把双刃剑。一旦智能合约部署上链,其代码逻辑便永久固化,任何潜在的错误、漏洞或设计缺陷都将被永恒记录,并可能被恶意利用,造成无法挽回的资产损失。在传统互联网中,一个漏洞可以通过“打补丁”快速修复;在区块链世界,修复往往意味着复杂的迁移、昂贵的社区沟通,乃至彻底的失败。因此,“安全前置” 的理念在这里被提升到了前所未有的高度 安全审计(Security Audit)正是在这种严苛环境下应运而生的核心质量保障手段。它不再是一种可选的成本,而是智能合约开发生命周期中不可或缺的、防御性的关键环节。一个严谨、深入的审计过程,是项目对自身代码负责、对用户资产负责的最重要体现 👉 0907 审计模板仓库 👉 0907 审计报告仓库 高层概述 ( 什么是安全审计/智能合约审计? ) 当人们提到"审计"时,通常指的是安全审查(Security Review)。这是对智能合约代码进行系统性、专业性的安全检查过程,旨在识别潜在的安全漏洞、逻辑错误和设计缺陷。 审计的局限性 There is no silver bullet ( 感兴趣的同学可以去搜一下该词的意思 ) to auditing:需要明确的是,审计并非万能的解决方案。即使经过最严格的审计,智能合约仍可能存在: 未被发现的复杂逻辑漏洞 经济模型的长尾风险 与外部协议集成时的未知交互风险 编译器或区块链底层本身的潜在问题 一次审计只能提供特定时间点的安全快照,无法保证永久的绝对安全。 安全审计的三个阶段 第一阶段:初步审查(Initial Review) 1. 范围界定(Scoping) 确定审计的具体范围:哪些合约、哪些功能 明确审计目标、时间线和交付物 了解协议的业务逻辑和设计意图 2. 侦察(Reconnaissance) 初步代码阅读和理解架构 识别关键组件和依赖关系 梳理权限模型和资金流向 3. 漏洞识别(Vulnerability Identification) 系统性检查各类安全漏洞 结合自动化工具和人工审查 从攻击者角度思考可能的攻击向量 4. 报告(Reporting) 详细记录发现的每个问题 按严重程度分类(危急、高危、中危、低危) 提供具体的修复建议和代码示例 第二阶段:协议修复与验证 1. 修复问题(Protocol Fixes) 开发团队根据审计报告修复漏洞 可能需要重新设计部分逻辑 确保修复方案不引入新的问题 2. 重新测试与添加测试(Retests and Adds Tests) 审计团队验证修复的有效性 为修复的部分添加专门的测试用例 确保修复后的代码仍能满足业务需求 第三阶段:缓解措施审查(Mitigation Review) 1. 侦察(Reconnaissance) 审查所有修复的代码变更 理解修复方案的安全影响 2. 漏洞识别(Vulnerability Identification) 确认原始漏洞已被彻底修复 检查修复是否引入了新的攻击面 3. 报告(Reporting) 提供最终的审计结论 确认所有高风险问题已解决 给出部署前的最终建议 智能合约开发生命周期 1. 规划与设计(Plan & Design) 需求分析和功能规划 架构设计和模式选择 安全考虑融入设计阶段(Security by Design) 经济模型和激励机制的数学验证 2. 开发与测试(Develop & Test) 编写合约代码和单元测试 集成测试和端到端测试 模糊测试(Fuzzing)和差异化测试 测试网部署和模拟攻击 3. 智能合约审计与部署后规划 这不仅仅是一个步骤,而是一个包含多个子阶段的综合过程(类似于传统软件开发生命周期SDLC,但具有区块链特有的安全考量): ...

August 16, 2025 · 3 min · 431 words · Guangyang Zhong

测试级漏洞合集

简介 拒绝服务 ( Dos - Denial of Service ) 简要概述 DoS 攻击在智能合约中常出现于以下场景: 攻击者通过让某个必要操作持续失败,从而阻止整个合约继续执行关键流程(如奖励分发、批量提款、循环遍历列表等)。 典型示例: 合约在循环中向所有参与者发送 ETH,攻击者故意将自己的 fallback/receive 函数设计为 永远 revert,导致程序在遍历到攻击者地址时整个交易回滚,进而导致奖励分发/提款功能长期瘫痪 易受攻击模式: function distribute() external { for (uint256 i = 0; i < participants.length; i++) { address user = participants[i]; uint256 amount = rewards[user]; // 任意一次 transfer 失败,整个分发流程就会 revert payable(user).transfer(amount); } } 攻击者只需在列表中占据一个位置,即可长期阻塞整个流程。 改进方法 使用 Pull Payment 不再向用户“发送奖励”,而是让用户自己来“领取奖励”,这样单个用户的失败不会影响其他用户 function claim() external { uint256 amount = rewards[msg.sender]; require(amount > 0, "no reward"); // Effects(先修改状态) rewards[msg.sender] = 0; // Interactions(再转账) (bool ok, ) = payable(msg.sender).call{value: amount}(""); require(ok, "send failed"); } CEI 说明: Checks:检查 reward 是否大于 0 Effects:先清零 reward 防止重入 Interactions:最后转账,不会阻塞其他用户 在必须 push 的场景中采用“非阻塞式分发” 避免因为某个地址转账失败而导致整个循环回滚 function distribute() external { for (uint256 i = 0; i < participants.length; i++) { address user = participants[i]; uint256 amount = rewards[user]; (bool ok, ) = payable(user).call{value: amount}(""); if (!ok) { // 可记录失败用户,稍后单独处理 // 不阻塞整体流程 } } } 处理 ETH 不当 ( Mishandling of ETH ) 简要概述 在Solidity智能合约中,“mishandling ETH”错误常指对以太币(ETH)接收和处理的不当管理,尤其在使用delegatecall的批量函数(如提供的batch函数)时。该函数允许通过delegatecall执行多个内部调用,并在同一交易上下文中共享msg.value。主要问题是:如果批量调用包括payable函数(如需要特定msg.value的进入抽奖函数),每个子调用都会看到相同的msg.value,导致合约仅接收一次ETH,但执行多次操作(如多次进入)。例如,在Puppy Raffle审计中,攻击者可通过batch调用多次enterRaffle(每个检查msg.value == entranceFee),仅支付一次费用却进入多次,造成资金损失或不公平。此外,依赖address(this).balance计算费用也易被操纵(如通过selfdestruct强制发送ETH) ...

August 20, 2025 · 8 min · 1540 words · Guangyang Zhong

静态分析漏洞合集

简介 整数溢出(Integer Overflow) 简要概述 在Solidity中,无符号整数(如uint256)在加/减/乘除运算时,若超出类型范围(例如uint256最大值为2^256-1),会发生“回绕”(overflow/underflow),导致意外结果,如余额错误计算、资金无限铸币或丢失。在Solidity <0.8.0版本中无内置检查,易被利用 典型示例: // 错误示范(无溢出检查) pragma solidity ^0.7.0; contract VulnerableToken { mapping(address => uint256) public balances; function transfer(address to, uint256 amount) external { require(balances[msg.sender] >= amount); balances[msg.sender] -= amount; // <-- 可能下溢(underflow) balances[to] += amount; // <-- 可能上溢(overflow) } } 攻击者可利用下溢:若余额为0,减去1会回绕成最大值,导致盗取巨额资金 改进方法 升级到Solidity ^0.8.0+(内置溢出检查,会revert),或使用SafeMath库进行安全运算 示例: // 使用内置检查(Solidity ^0.8.0) pragma solidity ^0.8.0; contract SecureToken { mapping(address => uint256) public balances; function transfer(address to, uint256 amount) external { require(balances[msg.sender] >= amount, "insufficient"); balances[msg.sender] -= amount; // 内置检查:下溢会revert balances[to] += amount; // 内置检查:上溢会revert } } 额外建议:对于旧版本,使用OpenZeppelin的SafeMath库(如balances[msg.sender] = balances[msg.sender].sub(amount));始终审计数学运算,并使用有界类型(如uint128)减少风险 不安全类型转换(Unsafe Casting) 简要概述 Solidity中进行类型转换时(如从较大类型uint256到较小类型uint8),若值超出目标类型范围,会发生隐式截断(truncation)或溢出,导致数据丢失、意外行为或安全漏洞,如余额计算错误或权限绕过。Solidity不默认检查转换安全,易被利用。 典型示例: // 错误示范(无安全检查) pragma solidity ^0.8.0; contract VulnerableVault { mapping(address => uint256) public balances; function deposit() external payable { balances[msg.sender] += msg.value; } function withdraw(uint8 amount) external { // uint8 仅0-255 require(balances[msg.sender] >= amount); balances[msg.sender] -= amount; payable(msg.sender).transfer(amount); // <-- 若amount实际>255,转换截断导致少转账 } } 攻击者传入>255的值,转换截断成小值,导致实际提取远超预期(但余额扣除完整值) ...

August 20, 2025 · 5 min · 856 words · Guangyang Zhong

低级漏洞合集

简介 此章节主要整理一些智能合约开发中的低级漏洞,适合初学者了解和防范。这些漏洞虽然"低级",但在实际项目中仍然频繁出现,可能导致严重的安全问题 不正确的 NatSpec 注释 什么是 NatSpec NatSpec(Ethereum Natural Language Specification Format)是 Solidity 的文档格式标准,用于生成用户文档和开发者文档 常见问题 // ❌ 现实审计中高频出现:transferFrom 注释完全错误 /// @title 代币转账函数 /// @notice 将代币从接收者地址转给发送者地址 ← ❌ 完全颠倒 /// @dev 使用用户的授权额度进行转账 /// @param from 接收代币的人 ← ❌ 注释与代码逻辑相反 /// @param to 发送代币的人 ← ❌ 注释与代码逻辑相反 /// @param amount 转账数量 function transferFrom(address from, address to, uint256 amount) external returns (bool); // ✅ 正确的 NatSpec 注释 /// @title 授权转账函数 /// @notice 从 `from` 账户扣除代币并转入 `to` 账户 /// @dev 需要调用者拥有足够的授权额度 /// @param from 代币来源账户(被扣款方) /// @param to 代币接收账户 /// @param amount 转账代币数量 /// @return success 转账是否成功 function transferFrom(address from, address to, uint256 amount) external returns (bool success); NatSpec 标签说明 @title:合约或函数的标题 @author:作者信息 @notice:给最终用户看的说明 @dev:给开发者看的详细说明 @param:参数说明 @return:返回值说明 @inheritdoc:继承父合约的文档 将隐私信息存于链上 问题描述 开发者误以为将变量声明为 private 就能保护数据隐私。 ...

August 16, 2025 · 2 min · 295 words · Guangyang Zhong

审计辅助工具

EtherScan Etherscan 是以太坊区块链浏览器,用于查询交易、合约和账户信息。 在审计过程中可用于: 检查合约部署地址及交易历史 验证合约源代码与链上字节码一致性 查询 ERC-20/ERC-721 代币持有人和转账记录 cloc 统计代码行数的工具,可用于: 了解代码规模 比较不同版本的代码变化 支持多种语言,包括 Solidity notion 可用于汇总和管理审计过程中的资料、笔记和报告: 可以建立审计任务列表 追踪漏洞修复进度 整合团队协作 Documentation ( 需求方提供 ) 审计文档部分通常包含以下内容: Roles:合约中涉及的角色定义,例如 Owner、Admin、User 等 Scope:审计范围,包括智能合约模块、外部依赖、第三方库 Commit Hash (github repository):记录审计所使用的代码版本 Known Issues:已知问题或潜在风险列表 Solidity Metrics ( vscode 扩展 ) Solidity 代码度量工具,用于评估合约复杂度和安全性 Note.md ( 自己撰写 ) 审计笔记记录,可包含: 潜在漏洞说明 安全优化建议 审计过程中发现的异常行为 链上交互测试结果

August 16, 2025 · 1 min · 52 words · Guangyang Zhong

漏洞等级划分标准

简介 在识别代码库中的漏洞时,评估其潜在影响与风险至关重要。漏洞(finding)通常分为三类: High(高危) Medium(中危) Low(低危) 如何评估漏洞严重性 漏洞的严重性可被归类为 High(高)、Medium(中) 或 Low(低),其判定基于多个因素: 对协议的影响(Impact):如果漏洞被利用,会造成多严重的损害? 被利用的可能性(Likelihood):攻击者利用该漏洞的概率有多大? 评审/协议主观性程度(Degree of judge/protocol subjectivity) 下面用矩阵给出一个结构化参考: 可能性 \ 影响 高 (High) 中 (Medium) 低 (Low) 高 (High) 🔴 High 🟠 High / Medium 🟡 Medium 中 (Medium) 🟠 High / Medium 🟡 Medium 🟢 Medium / Low 低 (Low) 🟡 Medium 🟢 Medium / Low 🔵 Low 分类的主观性 虽然“影响 × 可能性”矩阵提供了结构化方法,但分类仍然带有一定主观性,判断者(judge)的裁量权在最终分类中起关键作用 如果被审计的协议有明确的判定标准,则应以协议规定为判定基准 如何评估漏洞的影响(Impact) Impact 指漏洞被利用后对用户或协议造成的潜在损害或后果 High(高影响): 资金直接或几乎直接处于风险中。 协议功能或可用性发生严重中断。 Medium(中影响): ...

August 16, 2025 · 1 min · 127 words · Guangyang Zhong

静态分析工具

简介 静态分析工具是智能合约安全审计的重要辅助手段,能够在代码执行前自动检测潜在的安全漏洞、编码问题和最佳实践违规。这些工具通过分析源代码或字节码的模式来识别风险,极大提高了审计效率和漏洞发现率 主要静态分析工具对比 工具名称 语言支持 分析类型 特点 适用场景 Slither Solidity 源代码分析 快速、检测种类多、可定制规则 常规安全审计、开发中检查 Mythril EVM字节码 符号执行 深度分析、路径覆盖广 复杂逻辑漏洞、重入攻击检测 Aderyn Solidity 源代码分析 专注于Rust实现、速度快 Rust开发者、性能敏感场景 Semgrep 多语言 模式匹配 简单规则、学习曲线低 团队编码规范检查 Slither 概述 Slither 是由 Trail of Bits 开发的 Solidity 静态分析框架,速度快、检测能力强,支持自定义检测规则。 安装 python3 -m pip install slither-analyzer 升级 python3 -m pip install --upgrade slither-analyzer 基本使用 扫描当前目录 slither . 扫描特定文件 slither tests/uninitialized.sol 检测器选择 Slither 默认会运行 所有内置检测器 指定检测器 slither file.sol --detect arbitrary-send,pragma 排除指定检测器 slither file.sol --exclude naming-convention,unused-state,suicidal 排除全部 informational / low 级别的检测器 slither file.sol --exclude-informational slither file.sol --exclude-low 查看所有可用检测器 slither --list-detectors 打印器 默认情况下,所有 printers 都不会运行 ...

August 16, 2025 · 4 min · 668 words · Guangyang Zhong