我们首先从奇虎360技术博客的报告“EOS节点远程代码执行漏洞 — EOS智能合约WASM函数表数组越界”(http://blogs.360.cn/blog/eos%E8%8A%82%E7%82%B9%E8%BF%9C%E7%A8%8B%E4%BB%A3%E7%A0%81%E6%89%A7%E8%A1%8C%E6%BC%8F%E6%B4%9E/ )中来查看本次漏洞的详细技术内容。
根据报告所述,在修复该漏洞的提交ea89dce21d13d41a22b3512a27be97b4be9df755之前的代码版本上,我们可以看到在libraries/chain/webassembly/binaryen.cpp文件的76行,有assert用于检查变量取值情况。但assert一般仅适用于程序编译构建的Debug模式,对于正式发布的Release模式通常并不起作用,因此相当于没有做检查,导致78行对数组的访问存在隐患。
因此在发现该漏洞后,开发团队已将assert改为可正常调用的名为FC_ASSERT的宏定义。
知道了问题所在后,我们再来看一下编写EOSIO所使用的C++程序的内存结构及语言特性。
C++程序的内存区域包括栈区、堆区、自由存储区、静态全局存储区、常量区及代码区等。每个区域均有其独特的作用。同时,C/C++允许程序员通过指针等方式,对内存进行极为自主的控制及使用,并不强制检查数组边界等条件。因为包括内存管理在内的种种极为灵活、可控制底层的语言特性,C/C++凭借其高性能被广泛使用于对程序执行速度有严格要求的工业界。但也正是因为这种灵活性,C/C++程序常会因为内存管理的复杂性而出现内存泄露、宕机或内存越界等问题。这点在大型工程上尤其常见。
图 1 内存问题引起程序崩溃示例
原因在于,C++程序指针访问到相应内存区域,即有可能对其进行相应的操作,所以如果控制不当,访问到原本的“界限”之外,就会产生越界的问题:如果访问到数据区域,则可能会引起程序崩溃或读取、修改到原本不应访问到的信息;如果访问到代码区域,则可能注入或改变原有正常代码。这就是缓冲区溢出的基本原理。
作为计算机及互联网上十分常见且潜在影响巨大的攻击手段,利用缓冲区溢出进行攻击有记录的最早一次是发生在1988年的Morris蠕虫攻击。据估计,它一经出现便影响了互联网上10%的计算机,造成约10万至100万美元的损失。从其首次出现到今天的30年间,很多著名的攻击事件都采取了缓冲区溢出的方式进行,其影响也随着互联网的发展而扩大。
回到本次EOSIO的这个漏洞,根据360的报告我们可以看到:当检查代码失效后,如果offset变量被任意设置一个地址,例如0xfffffff,则会引起segmentation fault的错误而导致程序崩溃;而如果对合约进行精心设计,攻击者可通过对内存越界写入的方式来执行恶意代码,正如360报告中附加的视频所示。
同时,如果能将风险控制在单机范围内,那对全局来说影响还是相对可接受的。但正是由于恶意代码可以是一个
区块链上的合约,因此EOSIO将合约打包成区块后会在整个网络中传播,使得所有节点均可被此恶意代码控制,即整个网络都受到致命影响。
版权申明:本内容来自于互联网,属第三方汇集推荐平台。本文的版权归原作者所有,文章言论不代表链门户的观点,链门户不承担任何法律责任。如有侵权请联系QQ:3341927519进行反馈。