两大智能合约签名验证漏洞分析

当前位置:首页 > 币圈百科 > 两大智能合约签名验证漏洞分析

两大智能合约签名验证漏洞分析

2022-12-07币圈百科266

译者出版社:智能合同技术仍然处于非常早期的阶段,各种项目中使用的合同很可能存在漏洞。此前,我们或多或少听说过一些整数溢出契约漏洞,但这并不是智能契约中唯一的漏洞类型。目前,SWC注册表已经收录了27类智能合约漏洞,并用SWC-1XX对这些漏洞类型进行了编号和排序。在本文中,Consensys的安全工程师Gerhard Wagner将重点介绍智能合约中的两种签名验证漏洞。

bug

(图片来自:consensys)

重入性或整数溢出漏洞,这是大多数开发者都知道或至少听说过的,是关于智能合约中容易出现的安全问题。另一方面,在考虑智能合约的安全性时,您可能不会立即想到针对密码签名的攻击方法。它们通常与网络协议相关联。例如,签名重放攻击,恶意用户可以窃听包含有效签名的协议序列,并对目标实施重放攻击,以获取利益。

本文将解释智能合约处理DAPP生成的签名时可能存在的两类漏洞。我们将通过今年早些时候尽职调查小组完成的真实案例审计结果进行分析。此外,我们将讨论如何设计智能合约来避免此类漏洞。

协议层

签名是以太坊网络中的基础,发送到网络的每一笔交易都必须有一个有效的签名。下图显示了这种交易的一个例子。除了交易标准属性(如from、to、gas、value或input)之外,这些属性在全局命名空间中可用,并且经常出现在智能合同代码中,字段v、r和S一起构成交易签名。

p1

以太坊网络确保只有具有有效签名的交易才能包含在新块中。这为交易提供了以下安全属性:

认证:以太坊节点使用签名来验证交易签名者是否拥有与公共地址相关联的私钥。所以开发者可以相信这个msg.sender是真实的;完整性:签名后交易不会改变,否则签名无效;不可否认性:交易是用from字段中公共地址对应的私钥签名的,这是不可否认的,有私钥的签名人做了任何状态更改。

契约层

协议层不是签名发挥作用的唯一地方。智能合约本身也越来越多地使用签名。随着气价的上涨,扩容方案仍在进行中,避免连锁交易变得越来越重要。当涉及到链外交易时,签名也非常有用。EIP-191和EIP-712是关于如何处理智能合同中的签名数据的通用标准。后者旨在提高链外消息签名的可用性。那么,它为什么有用,它如何节省链上事务?

我们来看一个简单的例子。Alice Bob提出了一个建议,并将其编码为一条消息。她还用自己的私钥创建了消息的签名,并通过协商的通道将其发送给Bob。Bob可以验证Alice是否对消息进行了签名,如果Bob认为命题合适,他可以创建一个新的事务,将自己的消息、Alice的消息和签名组合成一个智能契约。通过数据,这份智能合约可以证明:

Bob已经签署了自己的信息(或者在这种情况下,公平更具体)。网络保证认证、完整性和不可否认性。整个过程只需要一次连锁交易,可以提供明显更好的用户体验,还可以节省汽油。需要注蓑衣网小编2022意的是,智能合约需要确保Alice发送给Bob的消息能够保持所有三个安全属性的完整性。

我们来分析现实世界中的两种签名验证漏洞,并讨论如何修复。

缺乏对签名重放攻击的保护(SWC-121)

第一个例子是Consensys的尽职调查部门在审计去中心化新闻应用Civil时发现的一个漏洞。与本案相关的系统的第一部分被Civil称为Newsroom,内容编辑可以向该新闻发布自己的文章。函数的作用是:更新或修改已有的内容。参数散列、内容URI、时间戳和签名,以创建内容的新修订。之后,verifiyRevisionSignature()函数调用提议的修订和最初创建第一个签名修订的内容作者。按照设计,新修订的签署人只能是创建原签署内容版本的作者。

p2

VerifyRevisionSignature()函数将根据DApp生成的内容哈希和新闻编辑室合同的地址创建一个签名的消息哈希。然后,调用recover()函数(来自OpenZeppelin的ECRecovery库)。然后,调用ecrecover()函数,验证作者是否真的签署了消息。已经讨论过的两个功能代码没有问题,因为只有最初创建内容的作者才能为其创建新版本,所以它们实际上不存在安全问题。

问题是契约不会跟踪内容哈希,所以实际上有可能一个提交的内容哈希及其用户签名可以多次提交。恶意内容作者可以利用此漏洞从其他作者那里获取有效的签名和内容哈希,并在他们不知情的情况下为他们创建新的有效修订。

蓑衣网小编2022p3

Civil通过跟踪这些内容的哈希值并拒绝之前修改过的哈希值,解决了这个问题。

缺乏适当的签名验证(SWC-122)

尽职调查在上次对分权协议0x进行审计时发现了此类漏洞的一个例子。以下解释是本审计报告第3-2节所述问题的总结。0x协议有各种不同签名类型的签名验证器,包括Web3和EIP712。另一种现有的验证器称为SignatureType。调用者如果order.makerAddress等于msg.sender(order.makerAddress是创建订单的用户),它允许订单有效。如果签名,请重新输入。调用方,则事务协定不执行实际的签名验证。目前还不清楚为什么会导致该漏洞,因为已经证实msg.sender和order的创建者是相同的,至少在理论上是如此。

除了交易契约之外,在0x体系中还有一部分契约叫做Forwarder。有了这个契约,用户只需发送以太坊和自己想要填写的订单,这个Forwarder契约就会在同一个交易中执行所有订单;

p4

想用泰币交易其他pass卡的用户可以向其他用户发送订单,货代合约会代为交易。这个交易契约验证每个订单,以确保订单签名的有效性,以及其他用户实际上已经签署了订单。我们再看上图,重新评估以下假设:如果order.makerAddress等于msg.sender,那么在这个交易契约中我们不需要做适当的签名验证,因为发送交易的用户也是订单的创建者。如果用户将订单直接发送到交易契约,则此假设成立。但是,如果我们通过Forwarder契约发送此订单,将order.makerAddress设置为Forwarder契约的地址,并使用SignatureType。呼叫者签名验证者?

在交易实例结算单个订单的过程中,货代合同会调用这个交易合同。这个事务契约将验证这个order.makerAddress中的地址,它是msg.sender在这种情况下,它可以被设置为Forwarder地址。因为合同充当交易双方之间的中介,所以order.takerAddress通常被设置为Forwarder地址。 因此,恶意用户可以使用Forwarder来处理订单,其中合同将与自己进行交易,因为它既是接收方,也是制造商。这是因为以下原因:

在Forwarder中,没有阻止契约成为订单制定者的逻辑;ERC20规范transferfrom ((address _ from,address _ to,uint256 _ value))不会阻止用户“空转”。和_from和_to可以是同一个地址;如果用户实际上签署了订单,这个交易契约允许基于msg.sender没有发送订单的事实来处理订单。

订单在交易合同中结算后,这个货代合同会得到完全相同的?平衡,而Forwarder契约将takerAmount转移给自己,将makerAmount转移给恶意用户。恶意用户可以利用这个场景创建一个“恶意订单”,以便以1魏(以太坊的最低单位)的价格从货代合约中换取所有的ZRX通行证;

综上所述,在不验证其签名的情况下,假定消息的发送者也是其创建者可能是不安全的,尤其是当交易是通过代理转发时。每当契约处理消息签名时,都有必要执行正确的签名恢复和验证。0x通过删除SignatureType修复了此问题。呼叫者签名验证者。

总结一下

外链消息签名的方式,确实是一个省油和提升用户体验的好方法。然而,从安全性的角度来看,这无疑增加了复杂性,并且使得智能合约在处理签名的消息时成为更具挑战性的任务。如果你对基于签名的攻击或者其他智能合约漏洞的例子感兴趣,可以查看Github中SWC-注册表的内容,里面有大量易受攻击的合约例子。此外,还有关于智能合约漏洞分类(SWC)计划的更多信息。我们一直在与社会各界合作。如果你想进一步了解SWC或者有其他好的想法,那么欢迎你参与以太坊/EIPs和以太坊魔术师关于EIP-1470的讨论;

也欢迎您随时浏览我们的不和谐,告诉我们您希望通过安全分析工具检测到哪些漏洞……但请不要以偏概全。

两大智能合约签名验证漏洞分析 | 分享给朋友: