Slither,智能合约静态分析器
加入 Empire Hacking Slack
- 讨论和支持
Slither 是一个用 Python3 编写的 Solidity 和 Vyper 静态分析框架。它运行一套漏洞检测器,打印合约细节的可视化信息,并提供 API 以便轻松编写自定义分析。Slither 使开发者能够发现漏洞、增强代码理解,并快速原型化自定义分析。
特性
- 以低误报率检测易受攻击的 Solidity 代码(参见奖杯列表)
- 在源代码中识别错误条件的发生位置
- 轻松集成到持续集成和 Hardhat/Foundry 构建中
- 内置"打印器"快速报告关键合约信息
- 检测器 API 用于用 Python 编写自定义分析
- 能够分析用 Solidity >= 0.4 编写的合约
- 中间表示(SlithIR)实现简单、高精度的分析
- 正确解析 99.9% 的公开 Solidity 代码
- 平均执行时间每个合约不到 1 秒
- 在 CI 中与 GitHub 的代码扫描集成
- 支持 Vyper 智能合约
使用方法
在 Hardhat/Foundry/Dapp/Brownie 应用程序上运行 Slither:
slither .
如果您的项目有依赖项,这是首选选项,因为 Slither 依赖于底层编译框架来编译源代码。
然而,您可以在不导入依赖项的单个文件上运行 Slither:
slither tests/uninitialized.sol
如何安装
注意
Slither 需要 Python 3.8+。 如果您不打算使用支持的编译框架之一,您需要 solc,Solidity 编译器;我们建议使用 solc-select 方便地在 solc 版本之间切换。
使用 Pip
python3 -m pip install slither-analyzer
使用 Git
git clone https://github.com/crytic/slither.git && cd slither
python3 -m pip install .
如果您更喜欢通过 git 安装 Slither,我们建议使用 Python 虚拟环境,详见开发者安装说明。
使用 Docker
使用 eth-security-toolbox
Docker 镜像。它包含了我们所有的安全工具和每个主要版本的 Solidity,全部集成在一个镜像中。/home/share
将被挂载到容器中的 /share
。
docker pull trailofbits/eth-security-toolbox
要在容器中共享目录:
docker run -it -v /home/share:/share trailofbits/eth-security-toolbox
集成
- 对于 GitHub 操作集成,使用 slither-action。
- 要生成 Markdown 报告,使用
slither [target] --checklist
。 - 要生成带有 GitHub 源代码高亮的 Markdown,使用
slither [target] --checklist --markdown-root https://github.com/ORG/REPO/blob/COMMIT/
(替换ORG
、REPO
、COMMIT
)
检测器
序号 | 检测器 | 检测内容 | 影响 | 置信度 |
---|---|---|---|---|
1 | abiencoderv2-array | 存储 abiencoderv2 数组 | 高 | 高 |
2 | arbitrary-send-erc20 | transferFrom 使用任意 from | 高 | 高 |
3 | array-by-reference | 通过值修改存储数组 | 高 | 高 |
4 | encode-packed-collision | ABI encodePacked 冲突 | 高 | 高 |
5 | incorrect-shift | 移位指令中参数顺序不正确 | 高 | 高 |
6 | multiple-constructors | 多个构造函数方案 | 高 | 高 |
7 | name-reused | 合约名称重复使用 | 高 | 高 |
8 | protected-vars | 检测到未受保护的变量 | 高 | 高 |
9 | public-mappings-nested | 带嵌套变量的公共映射 | 高 | 高 |
10 | rtlo | 使用了从右到左覆盖控制字符 | 高 | 高 |
11 | shadowing-state | 状态变量遮蔽 | 高 | 高 |
12 | suicidal | 允许任何人销毁合约的函数 | 高 | 高 |
13 | uninitialized-state | 未初始化的状态变量 | 高 | 高 |
14 | uninitialized-storage | 未初始化的存储变量 | 高 | 高 |
15 | unprotected-upgrade | 未受保护的可升级合约 | 高 | 高 |
16 | codex | 使用 Codex 查找漏洞 | 高 | 低 |
17 | arbitrary-send-erc20-permit | transferFrom 使用带许可的任意 from | 高 | 中 |
18 | arbitrary-send-eth | 向任意目标发送以太币的函数 | 高 | 中 |
19 | controlled-array-length | 受污染的数组长度赋值 | 高 | 中 |
20 | controlled-delegatecall | 受控的 delegatecall 目标 | 高 | 中 |
21 | delegatecall-loop | 循环内使用 delegatecall 的可支付函数 | 高 | 中 |
22 | incorrect-exp | 不正确的指数运算 | 高 | 中 |
23 | incorrect-return | 在汇编模式下错误使用 return | 高 | 中 |
24 | msg-value-loop | 循环内使用 msg.value | 高 | 中 |
25 | reentrancy-eth | 重入漏洞(以太币盗取) | 高 | 中 |
26 | return-leave | 使用 return 而不是 leave | 高 | 中 |
27 | storage-array | 有符号存储整数数组编译器错误 | 高 | 中 |
28 | unchecked-transfer | 未检查的代币转账 | 高 | 中 |
29 | weak-prng | 弱伪随机数生成器 | 高 | 中 |
30 | domain-separator-collision | 检测具有与 EIP-2612 的 DOMAIN_SEPARATOR() 签名冲突的函数的 ERC20 代币 | 中 | 高 |
31 | enum-conversion | 检测危险的枚举转换 | 中 | 高 |
32 | erc20-interface | 不正确的 ERC20 接口 | 中 | 高 |
33 | erc721-interface | 不正确的 ERC721 接口 | 中 | 高 |
34 | incorrect-equality | 危险的严格相等 | 中 | 高 |
35 | locked-ether | 锁定以太币的合约 | 中 | 高 |
36 | mapping-deletion | 删除包含结构的映射 | 中 | 高 |
37 | shadowing-abstract | 抽象合约中的状态变量遮蔽 | 中 | 高 |
38 | tautological-compare | 将变量与自身比较总是返回真或假,取决于比较方式 | 中 | 高 |
39 | tautology | 同义反复或矛盾 | 中等 | 高 |
40 | write-after-write | 未使用的写入 | 中等 | 高 |
41 | boolean-cst | 布尔常量误用 | 中等 | 中等 |
42 | constant-function-asm | 使用汇编代码的常量函数 | 中等 | 中等 |
43 | constant-function-state | 改变状态的常量函数 | 中等 | 中等 |
44 | divide-before-multiply | 不精确的算术运算顺序 | 中等 | 中等 |
45 | out-of-order-retryable | 乱序可重试交易 | 中等 | 中等 |
46 | reentrancy-no-eth | 重入漏洞(不涉及以太币盗窃) | 中等 | 中等 |
47 | reused-constructor | 重用基础构造函数 | 中等 | 中等 |
48 | tx-origin | 危险使用 tx.origin | 中等 | 中等 |
49 | unchecked-lowlevel | 未检查的低级调用 | 中等 | 中等 |
50 | unchecked-send | 未检查的发送 | 中等 | 中等 |
51 | uninitialized-local | 未初始化的局部变量 | 中等 | 中等 |
52 | unused-return | 未使用的返回值 | 中等 | 中等 |
53 | incorrect-modifier | 可能返回默认值的修饰符 | 低 | 高 |
54 | shadowing-builtin | 内置符号遮蔽 | 低 | 高 |
55 | shadowing-local | 局部变量遮蔽 | 低 | 高 |
56 | uninitialized-fptr-cst | 构造函数中未初始化的函数指针调用 | 低 | 高 |
57 | variable-scope | 在声明前使用的局部变量 | 低 | 高 |
58 | void-cst | 调用未实现的构造函数 | 低 | 高 |
59 | calls-loop | 循环中的多次调用 | 低 | 中等 |
60 | events-access | 缺少事件访问控制 | 低 | 中等 |
61 | events-maths | 缺少事件算术 | 低 | 中等 |
62 | incorrect-unary | 危险的一元表达式 | 低 | 中等 |
63 | missing-zero-check | 缺少零地址验证 | 低 | 中等 |
64 | reentrancy-benign | 良性重入漏洞 | 低 | 中等 |
65 | reentrancy-events | 导致事件顺序错乱的重入漏洞 | 低 | 中等 |
66 | return-bomb | 低级被调用者可能意外消耗调用者所有gas | 低 | 中等 |
67 | timestamp | 危险使用 block.timestamp | 低 | 中等 |
68 | assembly | 汇编使用 | 信息性 | 高 |
69 | assert-state-change | 断言状态改变 | 信息性 | 高 |
70 | boolean-equal | 与布尔常量比较 | 信息性 | 高 |
71 | cyclomatic-complexity | 检测圈复杂度高(> 11)的函数 | 信息性 | 高 |
72 | deprecated-standards | 已弃用的Solidity标准 | 信息性 | 高 |
73 | erc20-indexed | 未索引的ERC20事件参数 | 信息性 | 高 |
74 | function-init-state | 初始化状态变量的函数 | 信息性 | 高 |
75 | incorrect-using-for | 检测when no function from a given library matches a given type时使用using-for语句 | 信息性 | 高 |
76 | low-level-calls | 低级调用 | 信息性 | 高 |
77 | missing-inheritance | 缺少继承 | 信息性 | 高 |
78 | naming-convention | 符合Solidity命名约定 | 信息性 | 高 |
79 | pragma | 使用了不同的 pragma 指令 | 信息性 | 高 |
80 | redundant-statements | 冗余语句 | 信息性 | 高 |
81 | solc-version | 不正确的 Solidity 版本 | 信息性 | 高 |
82 | unimplemented-functions | 未实现的函数 | 信息性 | 高 |
83 | unused-import | 检测未使用的导入 | 信息性 | 高 |
84 | unused-state | 未使用的状态变量 | 信息性 | 高 |
85 | costly-loop | 循环中的高成本操作 | 信息性 | 中 |
86 | dead-code | 未使用的函数 | 信息性 | 中 |
87 | reentrancy-unlimited-gas | 通过 send 和 transfer 的重入漏洞 | 信息性 | 中 |
88 | too-many-digits | 符合数字表示法最佳实践 | 信息性 | 中 |
89 | cache-array-length | 检测在循环条件中使用某些存储数组的 length 成员且不修改它的 for 循环 | 优化 | 高 |
90 | constable-states | 可以声明为常量的状态变量 | 优化 | 高 |
91 | external-function | 可以声明为 external 的 public 函数 | 优化 | 高 |
92 | immutable-states | 可以声明为不可变的状态变量 | 优化 | 高 |
93 | var-read-using-this | 合约使用 this 读取自己的变量 | 优化 | 高 |
欲了解更多信息,请参阅 |
打印器
快速审查打印器
human-summary
: 打印合约的人类可读摘要inheritance-graph
: 将每个合约的继承图导出为dot文件contract-summary
: 打印合约摘要loc
: 统计源文件(SRC)、依赖项(DEP)和测试文件(TEST)中的总代码行数(LOC)、源代码行数(SLOC)和注释行数(CLOC)
深入审查打印器
call-graph
: 将合约的调用图导出为dot文件cfg
: 导出每个函数的CFGfunction-summary
: 打印函数摘要vars-and-auth
: 打印被写入的状态变量和函数的授权not-pausable
: 打印不使用whenNotPaused
修饰符的函数
要运行打印器,请使用--print
和以逗号分隔的打印器列表。
完整列表请参阅打印器文档。
工具
slither-check-upgradeability
: 审查基于delegatecall
的可升级性slither-prop
: 自动单元测试和属性生成slither-flat
: 扁平化代码库slither-check-erc
: 检查ERC合规性slither-format
: 自动补丁生成slither-read-storage
: 从合约中读取存储值slither-interface
: 为合约生成接口
有关其他工具,请参阅工具文档。
联系我们以获取有关构建自定义工具的帮助。
API文档
Slither内部结构的文档可在此处获取。
获取帮助
如果您需要使用或扩展Slither的帮助,欢迎加入我们的Slack频道 (#ethereum)。
常见问题
如何排除模拟或测试?
- 查看我们关于路径过滤的文档。
如何解决"未知文件"或编译问题?
- 由于slither需要solc AST,它必须有所有依赖项可用。如果合约有依赖项,
slither contract.sol
将失败。相反,在contracts/
的父目录中使用slither .
(当你运行ls
时应该看到contracts/
)。如果你有一个node_modules/
文件夹,它必须与contracts/
在同一目录中。要验证这个问题是否与slither有关,请运行你正在使用的框架的编译命令,例如npx hardhat compile
。这必须成功运行;否则,slither的编译引擎crytic-compile无法生成AST。
许可证
Slither根据AGPLv3许可证获得许可和分发。如果你需要例外条款,请联系我们。
出版物
Trail of Bits出版物
- Slither: 智能合约静态分析框架,Josselin Feist, Gustavo Grieco, Alex Groce - WETSEB '19
外部出版物
标题 | 用途 | 作者 | 发表地点 | 代码 |
---|---|---|---|---|
ReJection: 基于AST的重入漏洞检测方法 | 基于Slither构建的AST分析 | Rui Ma, Zefeng Jian, Guangyuan Chen, Ke Ma, Yujia Chen | CTCIS 19 | - |
MPro: 结合静态和符号分析实现智能合约的可扩展测试 | 通过Slither利用数据依赖 | William Zhang, Sebastian Banescu, Leodardo Pasos, Steven Stewart, Vijay Ganesh | ISSRE 2019 | MPro |
ETHPLOIT: 从模糊测试到高效漏洞利用生成智能合约 | 通过Slither利用数据依赖 | Qingzhao Zhang, Yizhuo Wang, Juanru Li, Siqi Ma | SANER 20 | - |
以太坊智能合约验证:模型检查方法 | 基于Slither的CFG构建符号执行 | Tam Bang, Hoang H Nguyen, Dung Nguyen, Toan Trieu, Tho Quan | IJMLC 20 | - |
智能合约修复 | 依赖Slither的漏洞检测器 | Xiao Liang Yu, Omar Al-Bataineh, David Lo, Abhik Roychoudhury | TOSEM 20 | SCRepair |
揭秘智能合约中的循环 | 通过Slither利用数据依赖 | Ben Mariano, Yanju Chen, Yu Feng, Shuvendu Lahiri, Isil Dillig | ASE 20 | - |
基于跟踪的智能合约循环动态gas估算 | 使用Slither的CFG检测循环 | Chunmiao Li, Shijie Nie, Yang Cao, Yijun Yu, Zhenjiang Hu | IEEE Open J. Comput. Soc. 1 (2020) | - |
SAILFISH: 秒级审核智能合约状态不一致错误 | 依赖SlithIR构建存储依赖图 | Priyanka Bose, Dipanjan Das, Yanju Chen, Yu Feng, Christopher Kruegel, and Giovanni Vigna | S&P 22 | Sailfish |
SolType: Solidity中算术溢出的细化类型 | 使用Slither作为前端构建细化类型系统 | Bryan Tan, Benjamin Mariano, Shuvendu K. Lahiri, Isil Dillig, Yu Feng | POPL 22 | - |
别在我身上做局:利用机器学习技术进行自动诈骗检测 | 使用Slither提取代币特征(可铸造、可暂停等) | Mazorra, Bruno, Victor Adan, and Vanesa Daza | Mathematics 10.6 (2022) | - |
MANDO: 多层异构图嵌入用于智能合约漏洞的细粒度检测 | 使用Slither提取CFG和调用图 | Hoang Nguyen, Nhat-Minh Nguyen, Chunyao Xie, Zahra Ahmadi, Daniel Kudendo, Thanh-Nam Doan and Lingxiao Jiang | IEEE 9th International Conference on Data Science and Advanced Analytics (DSAA, 2022) | ge-sc |
智能合约中价格欺诈TOD漏洞的自动审计 | 使用Slither提取CFG和数据依赖 | Sidi Mohamed Beillahi, Eric Keilty, Keerthi Nelaturu, Andreas Veneris, and Fan Long | 2022 IEEE International Conference on Blockchain and Cryptocurrency (ICBC) | Smart-Contract-Repair |
智能合约访问控制策略的建模与执行 | 扩展Slither的数据依赖 | Jan-Philipp Toberg, Jonas Schiffl, Frederik Reiche, Bernhard Beckert, Robert Heinrich, Ralf Reussner | IEEE International Conference on Decentralized Applications and Infrastructures (DAPPS), 2022 | SolidityAccessControlEnforcement |
基于深度学习和多模态决策融合的智能合约漏洞检测 | 使用Slither提取CFG | Weichu Deng, Huanchun Wei, Teng Huang, Cong Cao, Yun Peng, and Xuan Hu | Sensors 2023, 23, 7246 | - |
语义增强代码知识图谱揭示智能合约代码重用中的未知情况 | 使用Slither提取代码特征(CFG、函数、参数类型等) | Qing Huang, Dianshu Liao, Zhenchang Xing, Zhengkang Zuo, Changjing Wang, Xin Xia | ACM Transactions on Software Engineering and Methodology, 2023 | - |
具有细粒度状态访问的智能合约并行执行 | 使用Slither构建状态访问图 | Xiaodong Qi, Jiao Jiao, Yi Li | International Conference on Distributed Computing Systems (ICDCS), 2023 | - |
坏苹果:理解去中心化生态系统中的中心化安全风险 | 在Slither之上实现内部分析 | Kailun Yan , Jilian Zhang , Xiangyu Liu , Wenrui Diao , Shanqing Guo | ACM Web Conference April 2023 | - |
使用区间分析识别智能合约中的漏洞 | 在Slither之上创建4个检测器 | Ştefan-Claudiu Susan, Andrei Arusoaie | FROM 2023 | - |
以太坊区块链智能合约的存储状态分析和提取(无公开PDF) | 依赖Slither的CFG和AST | Maha Ayub , Tania Saleem , Muhammad Janjua , Talha Ahmad | TOSEM 2023 | SmartMuv |
如果你在学术工作中使用Slither,不妨考虑申请Crytic 1万美元研究奖。 |