1. 智能合约的经典漏洞
  2. 智能合约的审计工具
  3. 智能合约学习资源
  4. 智能合约安全学习路线
  5. 区块链相关学习材料

开源审计工具

建议在 linux 或者 MacOS 下运行。

mythril

Mythril 是 EVM 字节码的安全分析工具。它检测以太坊、Hedera、Quorum、Vechain、Roostock、Tron 和其他与 EVM 兼容的区块链构建的智能合约中的安全漏洞。它使用静态分析的方法,如符号执行、SMT 解决和污点分析来检测各种安全漏洞。另外,他还有收费版本的 MythX。

在我实际使用时,我发现他的漏洞检测只局限在少数几个简单的漏洞,如溢出、重入等。我感觉不是很满意,也许主要精力去做收费版了,这个开源版本维护的很少。

使用示例

安装编译器

1
2
3
pip3 install solc-select
solc-select install 0.8.7
solc-select use 0.8.7

安装 mythril

1
pip3 install mythril

开始

1
myth analyze <solidity-file>

OR

1
myth analyze -a <contract-address>

当我们学习静态分析后,将会再次详细介绍 mythril 的原理。

echidna

Echidna 用 Haskell 语言写的,用于对以太坊智能合约进行模糊测试或者基于属性的测试。它使用基于 ABI 和语法的模糊测试,通过断言判断结果是否与预期相同。

特点:

  • 自动生成适合的输入
  • 可选的语料库、变异库和覆盖率指南,以发现更深层次的错误
  • 在模糊测试之前由 Slither 提取有用信息
  • 能够指出模糊测试覆盖哪些行
  • 自动测试用例最小化以进行快速分类
  • 支持使用Etheno和 Truffle 进行复杂的合约初始化

使用示例

首先需要指定断言函数,它的返回值应该永远为不变量。然后 echida 会生成一系列的测试用例,检查断言函数的返回值是否为真。

断言函数的写法:

  1. 必须使用前缀 echidna_
  2. 参数为空
  3. 返回预期永远为 true 或者 false 的布尔值
1
2
3
function echidna_check_balance() public returns (bool) {
return(balance >= 20);
}

编写好之后直接使用

1
echidna-test myContract.sol --corpus-dir .;

它会在当前文件夹下保留测试用例和程序的终止执行的地方,更加详细的见工具的 repo。

测试范例:

运行时需要使用合适版本的 solc

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract Test {
event Flag(bool);

bool private flag0 = true;
bool private flag1 = true;

function set0(int256 val) public returns (bool) {
if (val % 100 == 0) flag0 = false;
}

function set1(int256 val) public returns (bool) {
if (val % 10 == 0 && !flag0) flag1 = false;
}

function echidna_alwaystrue() public pure returns (bool) {
return (true);
}

function echidna_revert_always() public pure returns (bool) {
revert();
}

function echidna_sometimesfalse() public returns (bool) {
emit Flag(flag0);
emit Flag(flag1);
return (flag1);
}
}

Slither

Slither 是一个用 Python 3 编写的 Solidity 静态分析框架。它运行一套漏洞检测器,打印有关合约细节的可视信息,并提供一个 API 来轻松编写自定义分析。Slither 使开发人员能够发现漏洞,增强他们的代码理解能力,并能够快速自定义分析。

使用示例

在 Truffle/Embark/Dapp/Etherlime/Hardhat 应用程序上运行 Slither:

1
slither .

在单个文件上运行 Slither:

1
slither tests/uninitialized.sol

建议安装 solc-select,他会自动下载、切换编译器版本,然后可以直接从主网拉取合约

1
slither 0x7F37f78cBD74481E593F9C737776F7113d76B315

这个工具比 mythril 强大许多,运行效率也高非常多,很快就能出结果,结果也高亮显示,很舒服。

image-20220208162213888

检测器

slither 集成了许多的检测器,不同的检测器各自可以检测不同类型的漏洞,默认执行所有检测器,当然也可以指定只是用那几个检测器。

打印器

slither 除了能检测合约的漏洞,还提供了许多其他有用的功能。可以直观分析

  • 合约的控制流
  • 调用关系图
  • 函数将会执行的操作码
  • 继承关系图
  • 等等

这些工具对合约审计人员非常有帮助

例如分析调用关系

1
slither 0xC5d105E63711398aF9bbff092d4B6769c82f793d --print call-graph

生成了点图,需要安装查看点图软件

1
2
3
sudo apt install graphviz
sudo apt install gir1.2-gtk-3.0 python3-gi python3-gi-cairo python3-numpy graphviz
pip3 install xdot

然后可以用 xdot 查看流程图,也可以转换成图片

1
dot 0xC5d105E63711398aF9bbff092d4B6769c82f793d.all_contracts.call-graph.dot -Tpng -o call_graph.pn

image-20220322113501266

为了查看函数的操作码,需要安装控制流依赖

1
pip3 install evm-cfg-builder

可以打印出来,这对合约的性能调优很有帮助。

1
slither 0xC5d105E63711398aF9bbff092d4B6769c82f793d --print evm

工具

slither 还附带了一些工具,用于检查可升级合约代理、合约单约测试属性、代码扁平化(避免无意义的嵌套)、ERC 代币是否规范。

manticore

manticore 是基于符号执行方法的合约分析工具,它实际上也是通过断言,来判断是否满足某种属性。

特点:

  • 给定输入,搜索可能的状态。
  • 自动生成输入信息。
  • 检测执行失败或者崩溃的地方。
  • 通过事件或者指令钩子,更精确的控制搜索路径。

安装:

1
pip install "manticore[native]"

分析合约:

1
manticore mcore.sol

代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// Smart contract based on a classic symbolic execution example from slides
// by Michael Hicks, University of Maryland.
// https://www.cs.umd.edu/~mwh/se-tutorial/symbolic-exec.pdf
contract SymExExample {
function test_me(int a, int b, int c) public pure {
int x = 0;
int y = 0;
int z = 0;

if (a != 0) {
x = -2;
}

if (b < 5) {
if (a == 0 && c != 0) {
y = 1;
}
z = 2;
}

// will fail when: a == 0 && b < 5 && c != 0
assert(x + y + z != 3);
}
}

如果运行 manticore 报错,请复制最后一行的提示信息,在谷歌搜索。大概率是依赖包版本问题。

注意:由于遍历或者搜索的效率其实比较慢,可能需要运行很久。

运行后将会生成很多辅助分析的材料,如何分析请见该项目文档。除此之外,也可以高度自定义,编写 python 代码,初始化合约状态,然后再检查不变量

检测漏洞:

类似于断言的方法,判断合约是否满足某个属性,详细操作间见文档

scribble

也是基于断言的审计工具,但是比较特殊的是,他可以很方便的扫描链上的合约,然后寻找漏洞。它自称是“基于属性的运行时验证工具”,我暂时还不清楚它使用的原理。感兴趣可以深入阅读它的文档

Legions

他主要是提供了语法糖,可以简化节点的查询工作,比如不用每次查询余额都要写一串的 web3。

vscode-solidity-auditor

这是一个 vscode 的插件,通过可视化的方式辅助分析合约。建议使用时换成它自定义的主题,可能显示效果会好一些。使用方法请看标题的官方网站,介绍的很清楚,也有动图演示。

安全实践

了解常见的安全漏洞

以上列出了一些合约漏洞,对此需要有一定的了解。

请熟悉 EIP-1470 提出的漏洞分类

学会使用安全工具

首先,有一个很棒的社区的总结《以太坊智能合约 —— 最佳安全开发指南》,强烈建议仔细阅读,虽然有部分内容可能过时了,但是仍然很有参考意义

其次,对合约进行单元测试,truffle 使用Mocha测试框架和Chai进行断言,也要测试前端 DApp 将如何调用合约。

img

从 Trufflev5.1.0开始,您可以中断测试以调试测试流程并启动调试器,允许您设置断点、检查 Solidity 变量等。

然后,使用合约审计工具,如MythrilSlither 等,可以使用 solidity-coverage 检查测试的覆盖性。

使用开源的合约库

开源合约库经过严格的安全审查,很多项目依赖他们,一般而言比较可靠。

openzeppelin/contracts 提供了常见的合约库,实现了一些标准库,如 ERC20、ERC721,仓库中可阅读源码

image-20220311114749585

dappsys 是一个新兴的合约库,用法参见文档文档

image-20220311114632238

参考:

  1. Solidity Security: Comprehensive list of known attack vectors and common anti-patterns
  2. Smart Contract Weakness Classification Registry
  3. 《智能合约安全分析和审计指南》王艺卓等
  4. EIP-1470 提出的 Smart Contract Weakness Classification Registry
  5. 8 Ways of Reducing the Gas Consumption of your Smart Contracts
  6. smart-contract-development-best-practices
  7. https://immunefi.com/learn/
  8. The Encyclopedia of Smart Contract Attacks and Vulnerabilities