这些智能合约漏洞,可能会影响你的账户安全!
什么是形式化验证?
维基百科对形式化验证的解释是这样的:在计算机硬件(特别是集成电路)和软件系统的设计过程中,形式化验证的含义是根据某个或某些形式化规范或属性,使用数学的方法证明其正确性或非正确性。传统上在硬件设计领域比较常用。主要原因就是硬件设计周期长,成本高,一旦生产出来就很难改动了。例如一个
区块链智能合约为什么需要形式化验证?
在区块链系统中可以编程且自动运行的程序被称为智能合约。智能合约最早在太坊区块链平台上应用,如Solidity就是一种智能合约编程语言,以使传统应用程序开发人员能够编写智能合约。初期会Solidity语言的全球只有几百人,后来随着太坊与区块链的火热,参与Solidity智能合约的人才开始逐渐增加,但是跟整个IT市场的从业人群比起来,会编写智能合约的人还是太少,大量的IT从业者要想开发智能合约只能去学习Solidity。为了让更多的IT从业者可以参与智能合约的编写与业务规则的实现,智能合约平台在原有Solidity的基础上扩展了对更多主流语言,甚至高级语言的支持,这样可以让多普通It从业人员也有了可以进行智能合约编写的可能性,大量熟悉Java、Go、Php等技术编程的开发人员都可以参与智能合约的开发。
然而,由于区块链交易是不可变的,智能合约代码中的错误会产生毁灭性的后果,破坏了对底层区块链技术的信任。例如,臭名昭著的TheDAO漏洞导致价值近6000万美元的以太损失,奇偶校验钱包漏洞导致价值1.69亿美元的以太永远被锁定。解决这些事件的唯一补救办法是硬分叉区块链,并将其中一个分叉恢复到事件发生前的状态。然而,这种补救办法本身是毁灭性的,因为它摧毁了区块链的核心价值,如不可变性和分散信任。但是智能合约的编写目的是为了行业应用,一旦应用到实际中必须考虑智能合约的安全性,智能合约要达到机器可信,就必须首先排除掉因人为因素而造成的智能合约破坏情形。智能合约形式化验证提供了一种可以证明的安全检验机制,通过形式化语言把合约中的概念、判断、推理转化成智能合约模型,可以消除自然语言的歧义性、不通用性,进而采用形式化工具对智能合约建模、分析和验证,进行一致性测试,最后自动生成验证过的合约代码,形成智能合约生产的可信全生命周期。可以把市场上已经出现的安全风险进行排查与审计,经过审计后的智能合约代码自然安全性就得到增强,同时智能合约形式化验证也是目前对智能合约进行安全保证最可靠的措施。行业应用区块链与智能合约,就需要进行智能合约 的形式化验证,消除安全隐患。
智能合约形式化验证方法分类
业界通常对智能合约进行形式化验证都有一些通用的方法,大体上分为下面几种通用的方法,每种方法都有一些工具和框架进行支撑。
1. 定理证明
定理证明是一种利用演绎推理在符号逻辑中提供证明的形式化方法.在这种方法中,证明的每个步骤都会引入一个公理或一个前提,并提供一个陈述,使用谓词逻辑将其进行推导,最终得到想要验证的结果.在证明系统满足关键期望的过程中,一般使用定理证明器来做辅助验证工作,因为这需要将手工证明的过程变成一系列能够在计算机上运行的符号演算,且可以对正确性进行检查。
其优势是这个方式是使用数学的方法,通过公理或前提进行推导,保证验证的严谨性。其不足是在做数学验证前需要将不同类型的源代码转换为相关框架的验证代码,而目前没有很好地办法保证在源代码与验证代码之间的转换一致性,实现成本高,自动化水平低,正确性也是很难保证的。在区块链智能合约领域一般对于有高隐私性,安全性,功能性,语义一致性等强烈的需求会通过这种法法来保证。
那业界在定理证明还是实现了很多工具和框架支撑这一能力,基本有下面的一些工具:
Solidity* and EVM*,该框架使用函数式语言F*分析验证了Solidity智能合约运行时的正确性,F*是一种函数式编程语言,用于形式化验证程序的正确性。
Corral是Boogie语言的分析工具.默认情况下,Corral会进行有界搜索,直到递归深度和固定数量到达一定限度为止,Boogie是一种中间验证语言,旨在构建其他语言的验证程序的中间层。
Coq是一个交互式定理证明助手,它提供了一种形式化的语言来编写数学定义,可执行 算法和定理
Isabelle/HOL是一个基于高阶逻辑的通用交互式定理证明器.
Raziel是一个编程框架,用于验证智能合约的多方计算的安全问题,为智能合约的隐私 性提供保障.
2. 符号执行
符号执行(英Z:symbolic execution)是一种计算机科学领域的程序分析技术,通过采用抽象的符号代替精确值作为程序输入变量,得出每个路径抽象的输出结果。 这一技术在硬件、底层程序测试中有一定的应用,能够有效的发现程序中的漏洞。这种方式的优点是以符号值作为输入,借助相应工具,可得到具体测试用例,具有很高的代码覆盖率。那这种方式本质上属于测试,不能100%证明智能合约是没有问题的,因为基于测试是很难以100%覆盖所有的场景,一般在做合约的安全性,功能性验证会推荐使用这种方式。
基于符号执行的业界的一些比较有名的架构如下:
- SASC,这个工具被用来发现潜在的逻辑风险,它是一种静态分析的工具,且可以生成调用关系的拓扑图。
- MAIAN,这个工具被用来查询漏洞,被设计成利用符号分析和具体验证器来跟踪智能合约中的属性。
- Securify,这个工具被用来进行安全漏洞分析,它是一个专门针对太坊智能合约的工具。
- Mythril,这个工具被用来进行代码安全分析,是一个针对太坊的智能合约的符号执行的工具。
- Verx是一个可以自动验证太坊智能合约功能性的验证器,太坊相关的问题可以通过上面三个工具组合使用来提高覆盖面。
- Oyente,这个工具被用来检测合约代码潜在的安全漏洞,是一个基于符号执行技术的测试工具。
3. 模型检测
模型检测(model checking),是一种重要的自动验证和分析技术,由Clarke和Emerson以及Quelle和Sifakis提出,主要通过显式状态搜索或隐式不动点计算来验证有穷状态并发系统的模态/命题性质。其基本思想是检验一个结构是否满足一个公式要比证明公式在所有结构下均被满足容易得多,进而面向并发系统创立了在有穷状态模型上检验公式可满足性的验证新形式,这种方法也被用于验证智能合约的正确性。
它的优点是可以使用市面上现有的模型检测工具,并且支持自动化验证,减少人为参与。但是其无法保证所使用的模型检测工具的完备性与正确性,合约复杂度过高会导致状态空间爆炸,进而导致无法完成验证能力。一般情况下需要保证合约的安全性,功能性会使用这种方式。
业界也有不少这种类型的工具和架构如下:
- NuSMV,这个工具被用于用于工业设计的验证,具有极高的可靠性,且被设计成模型检查的开放架构。它是SMV工具的重新实现和扩展,而SMV是第一个基于BDD的模型检查器。
- BIP, 这个框架包含一整套支持建模、模型转换、仿真、验证和代码生成的工具集,还支持层次化结构,被设计成为一个通用的系统级形式化建模框架。
- Prism,这个工具只针对表现出随机或概率行为的系统,被设计成一个概率模型检查器,对概率行为进行形式化建模和分析。
- SMC,这个工具被设计成模型检测器,用于检查在不同公平性假设下并发程序的安全性和活性。
4. 形式化建模
可以通过准确的数学语句和模型组件去定义不同组件的关系,消除系统中存在的二义性,这种设计系统的技术就是形式化建模。基于这种方式的系统的仿真结果是可以复现的,不会存在偶发性事件。这种方法的优点就是使用精确的数学语句或模型组件来设计系统,从而保证其仿真结果可被复现。但是此方法大多使用市面上已有的建模框架,其框架的完备性与正确性无法保证。基于智能合约的隐私性,安全性和功能性可以使用这种方法来检验。Hydra,就是基于形式化建模的一个框架,该框架鼓励开发者和用户诚实地披露智能合约中的错误和漏洞,它的设计是基于漏洞赏金的模式和NNVP编程。
5. 有限状态机
有限状态机是一种用来进行对象行为建模的工具,其作用主要是描述对象在它的生命周期内所经历的状态序列,以及如何响应来自外界的各种事件。智能合约的执行也可以看作从一个状态到下一个状态的变迁。
这个方法的优点是思维导向简单,将智能合约抽象转换为状态机的形式,易于操作,且具有图形界面。但是状态定义的好坏,对智能合约的验证难易程度有很强相关性,合约复杂度过高也会导致状态空间爆炸。对智能合约的安全性,语义一致性校验一般会使用这种方式。
业界一般的工具介绍如下:
- Contract Larva, 这个工具可以验证智能合约运行时的安全状况,它目前只支持太坊的Solidity。
- VeriSol,这个工具支持对智能合约语义的一致性进行形式化检测,具体原理是使用访问控制策略检查状态机工作流。
- FSolidM,这个工具可以自动生成太坊智能合约代码,并且带有图形画界面,界面上支持将智能合约设计为有限状态机的形式并进行验证。
- SPIN,这个工具可以检测一个有限状态系统是否满足PLTL公式以及其他一些性质,包括是否有循环或可达性,它是一种显式模型检测工具。
6.着色Petri网
Petri网是 20世纪 60年代由Carl Adam Petri发 明的,适合于描述异步的、并发的系统模型。所谓的着色Petri网就是在原有Petri网的基础上加入了颜色集和模型声明等元素,借此可以表达更复杂的类型信息。这种方式的优点是基于已有的Petri网模型,进行形式化验证,具有良好的语义描述且具有图形界面。但是当智能合约逻辑较为复杂时,可能会导致可达图生成难度增加,状态空间爆炸等一系列问题。对于智能合约的安全性,功能性验证可以选择此种方式。
当前技术应用的问题与展望
智能合约的形式化验证虽然已经有了一些成果和进展,但是这个领域还只是刚刚开始,离发展完备还有很大的距离,在商用过程中可能还存有下列问题:
- 易用性问题,形式化验证通常需要具备专业知识的人员参与调试,通常参与编写智能合约的人无法掌握这种技术来检验合约的正确性,需要花费大量金钱找专业人士花很长时间来完成检测。自动化的对智能合约进行形式化验证也存在相关局限性,一般情况下自动化程度越高的方法和框架,验证智能合约的性质越局限。那将自动化形式化验证方法扩大其普世性,并且支持非专业人士使用是急需解决的一个问题,从而才能立于形式化智能合约方法的广泛应用。
- 执行验证的计算机的时间和内存的问题,形式化验证通过探索尽可能多的执行状态来发现错误和安全问题的可能性。在这种情况下,计算机运行时内存的上限和执行时间成为复杂程序和协议的基本限制。商用场景中对于用户无法实施检测出结果,需要长时间的等待和分析也会影响相关体验。
- 正确性问题,当我们使用形式化验证工具时,我们将代码、安全目标和操作环境通过工具在不同模型之间转换,将高级语言转换为形式化验证工具支持的语言。工具的执行结果决定了形式化的准确性。但是,我们没有一个好的工具检查语言转换或者模型转换的准确性,缺乏对源代码和目标语言的语义一致性需要进行严格的证明。对于任意的形式化系统,我们需要通过查看人类的形式化代码来检查正确性,因此这就限制了形式化验证的一般适用性。
- 信任性问题,当前形式化验证智能合约的方法不断增加,如何评判这种方式的准确度,其验证的必要性,验证合约的效率,都要靠开发人员凭借其经验,这种方式是不是和不用形式化验证的测试没有区别。而且当解决问题的成本超过问题本身时,我们也会质疑解决该问题是否有意义。