查询 25 次,耗时 0.2665 秒

把大模型放进智能合约审计流程:用 Slither 做证据、用 AI 做受控复核

xiaobinz08

New member

xiaobinz08 Rep
0
0
0
Rep
0
xiaobinz08 Vouches
Vouches
0
1 MONTH
1 1 MONTH OF SERVICE
xiaobinz08 获得
0
0
0
获得
0
xiaobinz08 凭证
0
0
0
凭证
0
主题
6
点赞
0
HakB
1 月
在社区成长 1 月
LEVEL 1 1 XP
 
## 背景

大模型可以帮助审计人员快速理解陌生合约、整理调用路径、提出边界条件和生成测试思路,但它不是编译器、符号执行器,也不是安全结论的来源。尤其在 Solidity 审计中,模型可能忽略继承关系、代理升级、权限配置、外部调用语义或特定编译器版本,甚至把不存在的函数和漏洞说得很确定。因此,可靠用法不是“把仓库交给 AI,让它找漏洞”,而是先用可重复的静态分析与测试产生证据,再让模型协助解释、归类和补充验证假设,最后由审计人员确认。

本文给出一个仅针对本地代码或明确授权靶场的轻量流程:以 Slither 产生结构化发现,用大模型辅助阅读,再通过人工检查和测试验证。结论应能回到具体代码位置、可复现条件和影响范围。

## 原理与证据分层

建议把审计信息分成三层:

1. **工具事实**:编译器版本、静态分析器告警、测试结果、源码位置。这些信息应保留原始输出,便于复现。
2. **分析假设**:例如“外部调用后仍写入状态,可能存在重入风险”。这是待验证的推断,不等于漏洞成立。
3. **审计结论**:必须说明攻击者能力、必要前置状态、可达调用路径、实际影响,以及修复后测试结果。缺少这些内容时,应标为未确认或信息不足。

大模型适合把工具告警转换成检查清单、追踪跨函数数据流、提出反例和帮助撰写可读说明;不适合独立决定严重等级,也不应把“模型认为安全”当作没有漏洞的证明。

## 前置条件

准备一个本地、已获授权的 Solidity 项目,并确认仓库来源与审计范围。安装 Node.js、项目所需的编译器版本和 Python 环境;以下命令以本地副本为对象,不要对第三方线上合约发起交易或测试。

```bash
git clone <已授权的仓库地址> audit-lab
cd audit-lab
npm ci
python3 -m venv .venv
source .venv/bin/activate
pip install slither-analyzer
```

先查看项目文档、`foundry.toml`、`hardhat.config.*` 或编译配置,核对 Solidity 版本、优化器设置、依赖和 remapping。不要为了让分析器通过而随意升级编译器;版本差异会改变编译行为和告警结果。若仓库含有机密、私钥、客户数据或未公开漏洞细节,未经组织批准不要把源码发给外部模型服务。

## 分步骤实践

### 第一步:建立可复现基线

记录当前分支、提交号和工具版本,然后运行项目原有测试及编译。以 Foundry 项目为例:

```bash
git rev-parse HEAD
forge --version
forge build
forge test -vv
```

测试失败时先区分环境问题、既有失败和本次分析发现,不要将失败一概归因于安全问题。保留命令、输出和环境信息,后续复核才有依据。

### 第二步:运行静态分析并保留原始结果

对项目入口及依赖配置进行检查后运行:

```bash
slither . --json slither-report.json
```

如果仓库不是 Slither 可直接识别的布局,应依据项目实际构建方式配置,而不是盲目跳过编译错误。初始阶段可以先查看报告摘要和每项 detector 的源码位置;告警数量不是风险等级,工具也可能漏报或误报。不要在提交中加入真实密钥或未经处理的完整内部报告。

### 第三步:给模型提供有限、可核验的上下文

不要只问“这个项目安全吗”。把单个告警、相关函数、状态变量、继承关系和编译版本作为输入,并要求模型逐项区分事实与推测。例如:

```text
你是代码审查辅助工具,不可把推测写成已确认漏洞。
编译器版本:<项目实际版本>
静态分析告警:<原始 detector 名称、文件和行号>
相关源码:<仅粘贴必要的本地代码片段>
请输出:
1. 告警对应的代码事实及精确位置;
2. 可能的攻击前置条件和调用路径;
3. 哪些结论仍缺少证据;
4. 两个可验证的反例或测试思路;
5. 不改变业务语义的候选修复方向。
不要声称已执行测试,也不要虚构源码中不存在的函数。
```

审阅模型回答时,逐条对照实际源码。若回答引用了不存在的行号、接口或状态变量,应直接舍弃相应部分,而不是顺着错误假设继续分析。提交给模型的内容应最小化;组织还需确认服务的数据保留、训练使用和访问控制政策。

### 第四步:用具体案例验证,不以告警名称定案

例如静态工具提示某函数存在“外部调用与状态更新顺序”相关风险,先在源码中确认:外部调用是否真的可由不受信任的调用者触发;调用前后是否读写余额、份额或权限状态;是否有重入锁、检查-效果-交互顺序或其他约束;被调用对象是否可能回调当前合约。仅仅看到 `call` 或告警文字,不能直接定为可利用漏洞。

在本地测试中,可以用 Foundry 编写一个受控恶意接收合约,模拟回调并断言资产或内部记账不变量。测试应限定在本地 EVM,不连接主网或真实用户资产。先写出期望的不变量,例如“用户可提取金额不得超过其记账余额”,再构造回调路径;若测试无法复现,也不能直接宣布安全,还需检查是否覆盖了正确权限、状态和调用顺序。修复后重复运行同一测试,并执行全量回归。

### 第五步:形成可审计的结论

每条发现至少记录:文件与行号、影响组件、必要权限、可达路径、影响、复现步骤、证据(测试或工具输出)、修复建议和验证结果。严重等级应依据实际资产影响、可利用性与前置条件评估,而不是照搬模型给出的评级。对无法证明的部分明确写成“待验证”,并列出需要的配置、部署信息或业务规则。

## 风险与注意事项

- **误报与漏报并存**:静态分析和大模型都不能证明不存在漏洞;代理实现、跨合约依赖和部署配置尤其需要单独核查。
- **上下文不完整**:只看单个函数可能漏掉权限初始化、继承覆盖或升级入口。分析前应建立合约清单和关键外部入口图。
- **数据泄露**:私有仓库、审计报告、未公开漏洞和密钥不得未经授权上传到第三方服务。测试私钥应为本地临时值,不要复用生产凭据。
- **不安全的自动修复**:模型生成的补丁可能改变业务语义、权限边界或兼容性。补丁必须由人员审查,并通过编译、单元测试、模糊测试或不变量测试。
- **可复现性**:记录提交号、工具版本、编译配置和测试命令。没有这些信息,告警复核和审计交接会变得困难。
- **范围限制**:只在自有代码、明确授权的靶场或离线副本中测试。不要将审计流程扩展为对未授权线上目标的探测或交易。

## 常见问题

**问:模型说没有发现漏洞,能否作为审计结论?**
答:不能。它只表示模型在给定上下文中没有提出问题,不代表完整覆盖或形式化证明。仍需依赖代码审查、测试和部署配置核验。

**问:Slither 告警是否都要修复?**
答:不一定。先判断告警对应的代码事实、可达性和影响;确认是误报时记录理由,确认风险时再提出符合业务约束的修复。不要为消除告警而机械改代码。

**问:可以让模型直接生成 Foundry 测试吗?**
答:可以把生成结果作为草稿,但要核对测试是否真正触发目标路径、断言是否表达安全不变量,以及测试是否可能因错误设置而恒定通过。测试通过只覆盖该测试场景,不等于证明合约安全。

**问:如何处理模型与工具结论冲突?**
答:回到源码、编译配置和可复现测试。保留冲突记录,逐项检查模型是否缺少上下文、工具是否误报,以及构建是否与目标部署版本一致。不要用“多数意见”代替证据。

## 总结

在智能合约审计中,AI 最可靠的定位是受约束的分析助手:帮助解释告警、提出待验证假设、生成检查清单和改善报告表达。可操作的核心流程是先固定版本与构建基线,再运行静态分析,向模型提供最小且可核验的上下文,随后用源码审查和本地测试验证,最后形成带证据、前置条件和边界说明的结论。任何模型输出都应能追溯到代码与测试;无法验证的内容应明确标注不确定,而不是包装成安全结论。
 
顶部