Structured Abstract: SmartState

Context

智能合约是运行在区块链上的程序,其程序与状态均持久化保存在区块链上,一经部署无法修改。回滚是智能合约中用于异常处理和权限控制的重要机制,在函数调用中,回滚一经触发,会将区块链重置为函数未被调用时的状态。状态回退漏洞(State Revert Vulnerability)是指合约被攻击者利用回退机制操纵状态变量的可能性。利用状态回退漏洞,攻击者既可通过操纵状态变量获利,亦可发动DoS攻击使合约无法服务正常用户等。

Objectives

文章的目标是自动检测出智能合约中的SRV。

Methods

文章首先识别函数、变量间的依赖关系,随后根据这些依赖造成的影响,识别出 SRV 的存在。

对于第一步,作者的方法是构造足以支撑 SRV 检测的状态依赖图(State Dependency Graph)。状态依赖图中包含 4 种依赖:变量间的读写依赖、控制流依赖、与断言相关的依赖、时序相关的依赖。

作者使用 SmartDagger 从字节码中恢复 IR,因而也自然的得到了控制流图,因此得到了控制流依赖。

对于变量之间的读写依赖,作者使用和 SAILFISH 相似的手段获取。作者完全没有提到如何获取,对 SAILFISH 的阅读显示出,读写依赖通过数据流分析获取。

与断言相关的依赖(Assertion-related State Dependency) 是指与权限控制相关的依赖。Solidity 使用一组保留字进行断言,若断言不成立则触发回滚,由此实现权限控制。若一个状态变量在函数 $f_A$ 中被修改,又在函数 $f_B$ 中作为条件参与断言,则函数 $f_B$ 和 $f_A$ 中存在一个 ASD。作者使用控制流分析和数据流分析提取 ASD。

时序相关的依赖(Temporal-ordered State Dependency) 是由事务进行顺序产生的依赖。在用户的历史事务记录往往是合理的这一假设下,作者利用历史事务记录(迹)来计算时序相关的依赖。计算分为初始化、状态合并、提取三步。迹总是从初始状态开始,因此作者首先不加合并地构建出树形的状态机,其点代表合约的状态,边代表对函数的调用,随后,对后续状态一致的状态,作者将其合并,从而得到紧凑的状态机,最终,状态机上相邻转移边对应的函数之间就存在TSD。

最后,作者将 4 种状态合并得到最终的 SDG。若某函数内存在对状态变量的非确定性修改或状态变量依赖于非确定的其他状态变量,且根据状态依赖图,变量缺乏合适的权限控制,则将此函数标记为一个SRV标志。随后,以对外开放的API为起点,作者进行一次前向污点分析,将函数的参数和从caller传递的参数作为 source,external call 和状态变量作为 sink,从而找出受 SRV 影响的状态变量。

Results

对手动标注的数据集,precision达到87.23%, recall达到89.13%,远远超过sota。在大规模的现实数据集中,SmartState找出了406个新的SRV,其中 11 个存在于热门合约中,并影响了428600美元的资产。

Conclusion

本文提出了SmartState,能够有效的检测智能合约中的状态回退漏洞。SmartState的行为分为两个阶段:首先构建细粒度的状态依赖图,随后结合前向的污点分析和SRV标识符分析,计算受 SRV 影响的状态变量。SmartState 在一个手工标注的数据集和更大规模的数据集上测试,其表现均远超现有工具,表现其能以高精度有效的找出智能合约中的状态回退漏洞。特别的,SmartState找出了热门合约中的 11 个状态回退漏洞,共计影响了428600美元的资产。

Comments

SmartState 依赖 SmartDagger 从字节码中恢复 IR, 一方面,此方法能保护源码隐私,另一方面,SmartDagger 并不能完美地复原。个人认为若此工作基于源代码进行,精度还可进一步提升。另一方面,TSD的提取建立在调用序列是合理的这一假设上,但这一假设并非总是成立,若能有方法过滤掉不合理的调用序列或自动计算出合理的调用序列,则可以帮助这方面的工作,笔者正在做的就与此相关。