针对Proof-of-Authority的克隆攻击

 

0x01 POA

现在,许多区块链公司都在向具有拜占庭容错功能的权威证明(PoA)发展,它由一组n个许可seale节点和不超过t个的拜占庭sealer节点对包含用户交易的区块进行封装。尽管被广泛采用,但这些协议并没有证明是安全的。

在本文针对以太坊中两种最广泛部署的PoA算法Aura和Clique,提出了两种克隆攻击(Cloning Attack)。克隆攻击包含一个sealer,将其键-值对克隆到两个不同的以太坊实例中,这些实例将与不同sealer组进行通信。

这些称为Aura和Clique的共识协议使用权威证明,因为它们将区块的创建限制为固定n个授权节点(称为sealer)的固定集合,其中可以作恶或成为拜占庭节点的最多可以有t<n/2个。 他们的目标是解决众所周知的拜占庭共识问题。在n个节点中尽管存在t<n/2个拜占庭节点,但诚实的节点会产生唯一的区块。

PoA赋予sealer封装区块的权限,该流程包括对区块进行密码签名。 如果参与者的子集允许的话,这组sealer器可能会随时间而变化,因此非常适合参与者的动态加入。 对于有安全要求的关键行业,PoA是一种有吸引力的解决方案。

【责任披露】

出于道德原因,先前已将此漏洞上交:

(i)Parity Technology的安全团队,

(ii)以太坊漏洞赏金团队,网址为bounty@ethereum.org

(iii)在未发表的以太坊开发会议上演讲中(为了匿名起见,此处未公开)。

最终两个安全团队都承认了攻击的可能性。

 

0x02 Algorithms

在本节将描述PoA的两个主要算法Aura和Clique,分别在以太坊客户端软件parity和geth中实现。首先将Aura算法的两个不同版本形式化,这两个版本均可在线公开获得。然后对Clique算法进行形式化。

2.1 Aura

Aura算法的两个不同版本,一个对应于以太坊协议的parity实现,另一个使用回合(round)来决定是否达成共识决策。

(1)parity Aura

算法1描绘了Aura保证参与节点在给定区块链索引处就区块唯一性达成共识的方式,如Parity-Ethereum-v2.0.8中所实现(v2.0.8是当前最新版本)。每个参与节点都维护着一个状态,该状态包括一组sealer,表示其当前区块链ci的有向无环图<Bi,Pi>,链接到父块的parent字段的块b,以及表示将该块添加到区块链所需时间的步骤(step)和签名一个块的sealer。最初它们是⊥即“未定义”。

调用函数propose( )以便为区块链的特定索引提出一个块。一旦确定了块,就达成了共识,这可以在以后发生,正如将在下面的函数is-decided( ) (line 28)中说明的那样。该算法将时间离散化为若干步骤,这些步骤对应step-duration的持续时间,如配置文件中所指定。每个sealer执行一个无限循环,该循环周期性地检查clock-time( )是否指示该轮到它提议一个块了 (line 13)。轮到它时 (line 14)sealer将块的父块设置为其视野中的最后一个块并对其进行签名 (line 36)

propose( )函数调用的每个broadcast( )都将块发送到所有其他参与的诚实节点(实际上,除非某些sealer不知道更多块,否则仅广播最后一个块)。因此在接收到广播消息后,无论在哪个诚实参与节点上,无论它是否是sealer,都将调用deliver( )函数(line 24)。一旦将区块链视野交给pi,节点将其维护的区块链视野的分值与其收到的区块链视图的分值进行比较(line 21)。最长的区块链具有最高的分值,但是,如果两个区块链具有相同的高度,那么就其非空的slot(slot是形成一个区块所需的时间,即区块被提议及证明其正确性所需的时间)数量而言,更密集的区块链将获得最高分值 。这由两个函数heightstep-num表示,它们代表区块链的高度以及区块链中存在一个区块的slot数。

(2)Round-based Aura

算法2提出了Aura的不同决策技术,其余伪代码与算法1相同。
为了知道是否在成功达成共识后确定了区块b(Algo 2, line 1),参与者只需检查区块b之后是否存在两个连续的回合round1和round2,在每个回合中区块被大多数sealer封装。

2.2 Clique

算法3描述了Clique共识算法的伪代码。它是当前在geth-1.8.20-stable中使用的一种。

每个参与节点共享相同的初始块,即创世块,其中也包含块周期,即连续块创建之间的时间段。类似于Aura协议,每个节点都将自己对增长中的区块链ci的视野保持为有向无环图<Bi,Pi>。块b包含一个数字(作为该块在链中的索引),一个权重(作为该块的权重),链接到其父块的父字段以及一个对区块签名的sealer。

propose()函数运行一个无限循环,以便在满足某些条件时向区块链提议块。第一个条件(line 26)要求程序等待来自其他sealer的块,直到最后一个sealer-limit块都不包含其签名为止。在当前实施中,sealer-limit必须为⌊|sealers|/ 2⌋ +1,这是最小的大多数参与者要求。由于第一个条件,sealer需要轮流签名块。第二个条件(line 28)是等待block-period。 当两个条件都满足时,该程序将检查是否轮到对该块进行签名(line 29)。该程序可以立即对权重等于2的块进行签名;否则,可以在0到500×⌊|sealers|/2⌋+1毫秒之间的随机延迟后签名权重等于1的块(line 32)。在is-decided()函数(line 47)中描述了一旦稍后决定块,就会达成协商一致。循环的最后一步broadcast()将消息发送给其他参与者。

在接收到广播消息之后,不管它是否是sealer,在每个参与节点处调用deliver()函数(第43行)。程序使用的total-weight函数(line 40)比较两个区块链视野之间的权重,即它在本地维护的当前区块链和一个新接收的区块链视野。如果接收到的区块链权重较大,该程序将更新其本地视野;否则,它将保持相同的本地区块链视野。

为了考虑是否确定了块b(line 47),进程必须检查在b之后对块签名的sealer组。只有当大多数sealer在链上附加了随后的块时,一个块才能被认为是确定的。

 

0x03 Cloning Attack

克隆攻击的第一步是让某些攻击者将其以太坊实例复制到两个克隆中。克隆包含一个用户,该用户以相同的地址或公私钥对运行两个以太坊协议实例。请注意,这两个实例可以在使用相同IP地址的同一台计算机上运行,也可以在具有不同IP地址的其他计算机上运行。将这两个实例称为克隆,因为在消息开始延迟之前,一个实例与另一个实例具有相同的信息。此外,在整个攻击过程中,两个克隆都使用相同的公-私钥对。有趣的是以太坊允许这两个克隆的sealer都创建块,但是由于它们使用相同的私钥来密封块,因此它们被视为唯一的sealer。

在某个时刻,攻击者利用了少数的⌈n/2⌉-1个sealer的两组之间的消息延迟(偶然或由于网络攻击的结果),从而创建了短暂的分区。此时,这两个克隆可能无法共享完全相同的数据库内容,因为它们可能不知道区块链中存在的完全相同的区块。为了在分区开始时保持克隆,攻击者将其中一个克隆的区块链数据库的内容复制到另一个克隆的数据库,并将每个克隆连接到不同的分区。在此分区期间,以太坊协议重新调整对等方,以便同一组中的sealer保持通信。

请注意,它们在以太坊网络中获取分区的多种方法,包括通过错误配置路由,利用自然故障或恶意攻击网络。允许对互联网进行分区的网络攻击的一个示例是BGP劫持攻击。它的工作原理是,攻击者向一组广播发布到达另一组的错误路由,以拦截两组之间的所有流量。一旦流量被重新路由,攻击者就可以简单地延迟消息的传播。

 

0x04 利用多数的组保证进展

在攻击中利用克隆来给诚实的sealer以错觉,即每个组都包含大多数sealer。为了朝着双花的方向发展,每个小组都必须提交交易并因此决定区块,这就是为什么需要(2-(n mod 2))攻击者克隆实例的原因:

​ •n为奇数。诚实的sealer可以分为两组(n-1)/ 2,每组代表少数。为了保证该协议在分区两侧的进展,单个攻击者可以在每个少数组中简单地添加一个克隆,从而在每一侧达到大多数⌊n/2⌋+1个sealer。这就是当n为奇数时(2-(n mod 2))= 1个攻击者就足够的原因。

​ •n是偶数。单个攻击者可以将n-1个诚实的sealer分为两组,大小各异,一组包含n / 2个sealer,另一组包含n/2-1个sealer。但是,将一个克隆包含在第二组中不足以保证其进展。这就是为什么需要(2-(n mod 2))= 2个攻击者的原因。

总而言之,(2-(n mod 2))个攻击者将n个sealer的网络划分为大约两半,并向其中添加了克隆,以便每个组至少包含⌊n/2⌋+1个大多数的sealer。这保证了每个组上协议的进度,以便在一个组上获得事务TX1的提交,而在另一组中获得包含TX2的主干链提交。例如,对于一个n = 9的sealer网络,每个子组中必须至少有5个sealer。需要这样的条件以确保共识算法的最终性,以便从两个子组的角度来看,块将被决定或看起来是最终的。

注意在这里考虑分区的必要时间。在现实情况下,攻击者可能希望其事务的效果在停止分区之前发生。例如,在交易TX1中购买商品的攻击者可能希望在交易从区块链中丢弃之前先收到商品。

 

0x05 交易冲突

执行双花的最常见方法是,确保事务TX1最终被包含在分叉的一个分支中,然后说服收件人接受TX1,然后通过丢弃事务TX1的分支来解决该分叉。稍后,交易TX1的发送者可以简单地在另一个交易TX2中重新使用他最初在TX1中花费的资产。在以太坊中有趣的是,如果冲突事务TX2没有足够早地发出,则TX1可以重新包含在内存池中,并在以后提交。

克隆的目标是利用网络分区之间的消息延迟来快速发出两个冲突的事务。一旦将区块链网络划分为两个子组,攻击者就至少发布两个有冲突的交易,每个子组至少要进行一次交易。一个说明双花攻击的典型示例是两个相互冲突的交易:

TX1,在第一笔交易中,Alice将她所有的硬币交给Bob,在第二笔交易中,Alice将她所有的硬币都交给Carol,另一笔交易则发送给另一组。

很明显,同时进行这两项交易会破坏Alice帐户的完整性,并导致双花。一旦第一个事务显示为已提交,则传递延迟的消息或结束分区将具有丢弃两个事务之一的效果。

 

0x06 对Aura的克隆攻击

如先前在算法1中所述,Aura的当前实现仅在检测到分叉时选择最长的链作为主干链。因此,要影响对攻击者分支作为主干链的选择,攻击者只需通过在维护此分支的组中封装比其他组更多的块来帮助攻击者分支。

为了在一个分支中封装比另一个分支更多的块,攻击者在(n+1)×s秒内维护该分区,其中n是sealer的数量,s是分隔连续块的以秒为单位的步骤持续时间。原因有两个:

•首先,如算法1前面所述,Aura在创建块后需要ns延迟以确保其被决定。必须确定受害方的块状态,以确保TX1被提交。假设每侧的组大小均为⌊n/2⌋+1,并且每个sealer都一个接一个地封装,那么攻击者克隆也必须封装至少一个块。

•其次,攻击者必须确保攻击者分支的长度比受害者分支的长,以便Aura选择攻击者分支作为主干分支。仅当攻击者在攻击者分支上密封了两个块时,即与在受害者一侧密封的块数相比,才多出一个块。结果,攻击者需要将网络分区维持(n+1)×s秒,以至少获得两回合可以封装一个区块。

具有9个sealer的示例:为了简单起见,下图描述了一个对Aura的克隆攻击,具有n = 9个sealer且2-n mod 2 = 1个sealer是恶意的网络分区,即“Sealer 1”。因此,该攻击者通过其两个克隆实例出现在两组中,并给人一种错觉,即每个组都包含大多数的⌊n/2⌋+1= 5个sealer,而每个组中的一个sealer实际上是一个克隆。正如所看到的,这种攻击转化为让Sealer 1在合并两个分区之前只在较低的分区上创建最后一个块(图中用红色最右边的块描述)。这样,Sealer 1确保该分支将是主干分支,而图纸上面的分支将消失。因此,可以保证攻击者成功地双花。

 

0x07 对Clique的克隆攻击

在Clique中,克隆攻击的时间不需要在Aura中花费的时间。与Aura不同,Clique的封装器可以封装一个块,即使不是它的轮次(turn)。根据他们的轮次,有些sealer可能不得不等待,而另一些则不需要。这些差异会影响攻击者影响选择分叉的一个分支作为主干链的方式,并使攻击者比Aura快进行双花。

7.1 有序和无序sealer

对Clique的克隆攻击不同于对Aura的克隆攻击,始于它开始延迟消息。由于封装的顺序在Clique中很重要,因此攻击者最好根据封装器封装的顺序来决定开始延迟消息。

当sealer在轮到他时进行封装,将此sealer称为有序sealer,将该块称为有序块(参见 Alg. 3, Line 29)。在Clique的每个分区中最多有一个有序的sealer来封装当前块。当封装器在没轮到他时封装,们称此sealer为无序sealer,将此块称为无序块(参见 Alg. 3, Line 32)。由于sealer必须等待要封装的两个块之间的sealer-limit块,因此最多有(n-sealer-limit)个潜在的乱序sealer来封装一个块。有序块对分支占2权重,而无序块对分支占1权重,因此按顺序封装或无序封装会影响有关分支选择过程的决策。

另外,有序sealer可以将块附加到链上,而无需等待任何延迟,如算法3的Line 29所示。相反,无序sealer必须等待随机的时间,如算法3的Line 32所示。 该机制使顺序封装器有一定时间成为在轮到他时第一个进行封装的,但是如果顺序sealer滞后,则允许无序sealer对块进行封装。

由于主干链通过比较块权重的总和来选择分叉的分支,因此攻击者在分区时必须具有最大数量的有序sealer,以使总权重最大化。因此为了影响对作为主干链的分支的选择,攻击者必须选择适当的轮次以开始延迟消息。如果处理不当,攻击者可能失去双花的机会。

7.2 乱序sealer选择分支

下图描述了随着时间从上到下增加,使用n = 9的sealer和一名攻击者(Sealer 1)执行的攻击。最初,区块链从区块5开始,指示第一个区块被Sealer 5封装。随着时间的流逝,Sealers 6、7、8和9依次封装区块链的其他区块。由于尚无分区,所以有序sealer是第一个在各自的轮次间对这些块进行签名的,因此所有块均为图中以蓝色表示的有序块。在每个创建的块旁边是无法封装的sealer(灰色),有序sealer(绿色)或无序封装器(黄色)的sealer列表。

考虑攻击者Sealer 1执行克隆并延迟网络消息。在Sealer 9封装他的块之后,Sealer 1开始拦截左侧的一组sealers 2、3、4和5与右侧的一组sealers 6、7、8和9之间的消息。注意,由于在每一侧都存在其克隆之一,因此在两面都显示了Sealer 1。所产生的分区在图3中用区块链的分叉分成两个分支来表示。分区开始后,Sealer 1立刻在分区的每一侧发出两个冲突的事务TX1和TX2,这会双花。 Sealer 1的两个副本使他可以在每组中封装一个区块。请注意,这些框标记为1并用蓝色表示,因为此时Sealer 1是有序sealer。封装后由于sealer的限制,Sealer 1不再能够封装任何块,因此,Sealer 1在两组中均以灰色表示。

在分区的右侧,我们可以看到Sealer 6封装了下面的块,即使此时它不是按顺序封装。这是因为在网络被分区时,有序Sealer 2无法与此组通信。出于某种原因,在分区的左侧可能还会出现Sealer 2的速度不够快而无法封装下一块的情况,而另一个封装器(例如Sealer 3)设法将其封装。请注意,这可能是由于Sealer 3在封装之前必须等待的延迟是可以为空的随机数(Alg. 3, Line 32)。然而,由于必须等待 sealer-limit,来自Sealer 3的最后一次封装会阻止它按顺序封装下一个块,因此,下一个块又会出现无序。该过程继续进行,其中左侧的sealer有序封装,而右侧的sealer乱序封装。

最后,由于事务TX1和TX2现在都已成功提交,因此攻击者不再需要延迟消息并可以停止分区。实际上,交易现在都在一系列[n / 2] + 1 = 5个连续区块的第一个区块中,这足以让所有Clique用户将这些交易视为已提交,因为它们的区块已如算法3的第49行所示确定。我们可以得出结论,分区中左侧分支节点的权重为3×2 + 2×1 = 8,因为它包含3个有序块和2个无序块。相反,在分区过程中,右侧分支节点获得的权重为1×2 + 4×1 = 6,因为它包含1个有序块和4个无序块。从两个分支节点的权重差异出发,左侧的最重分支节点被选择为主干分支,而右侧权重少轻的分支被协议简单丢弃(Alg. 3, Line 44)。

7.3 不考虑封装顺序

请注意,即使sealer不了解拓扑,也可以使用一种方法来攻击Clique。此攻击与之前的攻击略有不同,因为它取决于攻击者是否有可能成为唯一能够在分区两侧封装块的sealer。攻击者可以简单地在受害分支上封装单个块,并在攻击者分支上持续封装块。对于攻击者而言,在最坏的情况下,所有即将出现的⌊n / 2⌋+1个有序sealer最终都位于受害者侧,这将使分区期间在受害者侧获得的分支权重最大化。

回想一下,在Clique(Alg. 3,Line 14)中,sealer限制始终为⌊n / 2⌋+1,现在,如果攻击者停止封装受害侧的第二个块,则在攻击过程中分区此侧获得的最大量将为(sealer-limit×2)。攻击者只需要保持另一分支上的封装,直到该分支上增加的权重达到(sealer-limit×2 + 1)。在这种情况下,攻击者可以成功地使双花,而不必考虑每组中的sealer。

 

0x08 Conclution

Aura和Clique之间的主要区别之一在于封装序列的可预测性。实际上,在Aura中严格执行该序列,而在Clique中,此序列可能会根据随机数和网络通信延迟之间的差异而更改。但是,这种轻微的算法差异会使共识算法对克隆攻击进行双花攻击时的弹性产生重大影响。

一方面由于严格执行封装顺序,Aura在网络分区的情况下很容易遭受克隆攻击。对Aura进行克隆攻击时,攻击者无需了解sealer的身份,也无需知道sealer的顺序。因此,恶意sealer只需要使用经典网络攻击(例如BGP劫持)对覆盖网络进行分区,即可成功进行双花,并有100%的成功机会。

另一方面,在Clique上没有拓扑信息的情况下可能会双花,但是在已知拓扑的情况下对Clique的攻击速度大约是对Aura的两倍。潜在的下一个有序sealer的可能范围极大地影响了双花的机会。当攻击者能够隔离下一个⌊n /2⌋+1个sealer时,它就能以100%的成功率进行双花攻击。在相反的情况下,仅了解接下来的两个有序sealer,最多只能保证60%的成功率。

有趣的是,在不了解拓扑的情况下考虑对Aura和Clique的攻击时,似乎攻击Clique的速度甚至比攻击Aura还要慢。原因是在最坏的情况下,所有有序sealer都位于受害方,攻击者必须获得一个两倍于受害方分支的分支,才能双花。与执行对Aura的克隆攻击相比,增长该分支节点将花费更多时间。但是总的来说,即使不了解拓扑结构,Aura和Clique共识算法也容易受到旨在双花的恶意sealer的攻击。

(完)