虫洞攻击:一种针对支付通道网络的攻击

支付通道网络(Payment Channel Network, PCN),是由支付通道构建起来的网络,是 Layer-2 扩容解决方案的一种类型。支付通道指的是链(Layer-1)上的两个用户 P_AP_B 之间建立起链下沟通的通道,该通道的建立是基于链上的脚本或者合约的。双方在互相支付的过程中只需要在连下各自本地更新最新状态,关闭通道时再同步到链上即可。双方状态不一致的情况可在争议解决(Dispute)阶段解决,具体细节请自行 Google。

PCN 则是为了解决大规模使用场景,如果只使用两方支付通道,为了保证两两之间可达,那么 100 个用户之间将会建立 9900 个支付通道,这样的开销可以通过路由来大幅缩减。假设用户 P_AP_B 之间, P_BP_C 之间已经建立有支付通道,在 PCN 下, P_AP_C 之间不需要建立通道,只需要以 P_B 为跳转进行支付,这意味着 P_A 需要先把钱打给 P_BP_B 再把钱打给 P_C 。为了防止 P_B 从中作梗贪掉了这笔钱,我们需要一种机制保证这种多跳(Multi-Hop)支付的原子性(要么都成功,要么都失败,不会出现一个通道成功了但另外一个没有成功),这个机制被称为哈希时间锁合约(Hash Time Lock Contract, HTLC),具体细节请自行 Google。

但是 P_B 并没有任何动力去做这件事,因此我们需要引入手续费。假设手续费为 1 CKB,如果 P_A 想给 P_C 转 10 CKB,那么需要先给 P_B 一个 \mathsf{HTLC}(P_A, P_B, H(s), 11, 2t) ,其中 H(\cdot) 为抗碰撞哈希函数, s 为一个只有 A 知道的随机数, t 是一个单位时间。也就是说, 2t 之前, P_B 可以提供 s^\prime ,如果 H(s^\prime) = H(s)P_B 获得 P_A 支付的 11 CKB;否则, 2t 之后 P_A 可以取回他的 11 CKB。然后 P_BP_C 提供 \mathsf{HTLC}(P_B, P_C, H(s), 10, t) (注意这里不再是 2t ,至于为什么,请自行 Google)。这样, P_B 就收取了 1 CKB 的佣金。因此,我们通常会有下面这样的多跳 PCN:

图 1*:Alice 向 Edward 支付 10 CKB
*Malavolta, Giulio, et al. “Anonymous multi-hop locks for blockchain scalability and interoperability.” Network and Distributed System Security Symposium (NDSS) . 2019.

可以看到,黑色虚线按照数字标号执行(第一步原图有笔误,应该是 y := H(R) )之后,绿色虚线由右至左依次执行,代表正常流程。当遭遇恶意节点 Bob 和 Dave 之后,绿色虚线变为红色虚线。Edward 将 R 提供给 Dave,获得了 Dave 的 10 CKB,Dave 为了 1 CKB 的收益,理应向 Carol 揭示 R (Carol 还不知道 R ,这是因为 PCN 中不存在广播这样的操作),但是他可以和 Bob 合谋,直接跳过 Carol 把 R 交给 Bob,Bob 可以把 R 给 Alice 然后获得 13 CKB。Dave 由于没有按时向 Carol 揭示 R ,因此 Dave 无法获得 Carol 的 11 CKB。在 Carol 的视角里,她还以为可能是因为 Edward 离线了或者 Dave 钱不够了所以才会超时,她并不会意识到这是攻击。这样,总共算下来,Bob 和 Dave 合谋赚取了 3 CKB,可是他们本应只赚取 2 CKB,他们从中盗取了 Carol 应得的佣金。事实上,合谋的两个节点之间有多少个受害人,他们就能多攫取多少倍的佣金。这样的攻击对很多 PCN 成立,包括闪电网络。同时,在一些比较成熟的网络譬如 Ripple 中,多跳支付是比较常见的,使得这样的攻击的发动条件不是那么难以达成。这样的攻击被叫做虫洞攻击(Wormhole Attack)。

更多细节请参考 NDSS’19 的一篇论文 Anonymous multi-hop locks for blockchain scalability and interoperability

2 Likes

写错了。

现在闪电网络的中心化情况挺严重的。

有几个小问题:

  • 所以在 Alice 向 Edward 发送交易前,Bob 和 Dave 之间是没有支付通道的是吗?
  • Alice 向 Edward 发交易的时候,有没有一个确认最短交易路径的一个过程,即通过最少的中间人,从而支付最少的手续费。
  • 那么这种虫洞攻击的作恶模式是不是,大节点之间故意不建立支付通道,然后合谋去吃掉交易中间过程中的手续费?
1 Like

多谢,已改正。

  1. 只有相邻节点才有支付通道,Bob 和 Dave 之间攻击全程都不需要建立支付通道。
  2. 这个看路由算法了,这种算法是存在的,但哪个项目采用了什么算法这个我不了解。
  3. 对,如果某个攻击者拥有多个身份,譬如 Bob 和 Dave。那他的身份之间最好不要建立支付通道。

攻击前提是手续费足够高,又不至于高到开通支付通道。

其实我觉得这不是攻击,更像一种套利,说明这个市场或者路由算法没有给出最优解。

为什么?Bob 和 Dave 的合谋在这个情形中不需要做出权衡。一旦他们确认自己处在同一个支付链中(Dave 可以先无脑直接给 Bob,然后 Bob 一试就知道了),只需要付出一次通讯的代价就可以赚取中间受害者的手续费。

这个当然是没有争议的“攻击行为”,因为它打破了系统想要保持的安全属性:原子性。尽管在攻击发生与不发生两种情况下,Alice 与 Edward 都完成了转账,但是攻击者之间支付链是全部失败的。所以对于 Alice 到 Edward 这样的完整支付链来讲,它的原子性遭到了破坏。这也是为什么这样的攻击能够在有手续费的设定下获利,但是却在无手续费的情况下不能获利。事实上,这个攻击能否发生与“路由最优”没有什么关联,与路由方式有一定关系。

这样的攻击可以避免吗?很遗憾,如果这样的路由是动态的(节点没有关于路径的先验知识),并且仅限于相邻节点之间进行通讯,且通讯是两轮的(一轮锁定,一轮解锁),那么这样的攻击是总能发生的。严格的证明在 NDSS‘19 那篇论文中有给出,直观上理解,就是 Alice 和 Bob 之间的锁定(任何形式的锁定),永远无法区分 Bob 提供的解锁密钥是攻击得来的还是正常交易得来的,因为他俩在锁定的时候还不知道后面的路径是什么。

那么通过调整手续费可以避免吗?也不行,比如,如果失败者也可以获得手续费,那么对于中间节点的激励就会出现问题。这是由于这样的攻击是基于诚实节点无法分辨出攻击行为和正常行为的(如果能分辨,他就可以拒绝攻击者的解锁),对手续费的调整必然会波及所有节点。

I see,原来的理解有点小问题。 我有一个疑问,在绿色的路径中,是否可以通过某种广播的方式e向a,b,c,d全部揭示R?

正确的广播可以解决这个问题,问题就在于,Edward 无法确保自己知道正确的路由,如果只靠两轮交互的话。因此也无法保证他能进行正确的广播。这种冲突在考虑隐私保护的支付通道网络中尤其明显,因为他们需要尽可能保证支付隐私使得外部观察者无法了解到 Alice 支付给了 Edward 多少钱。

1 Like

我之前也会偏向于认为这是一种套利行为或者是钻漏洞的行为,而不会认为这是一种攻击行为,感谢丘巨的解答。

目前看好像并没有什么可以解决这种攻击的方式,在这转账的过程中诚实节点是无法分辨攻击行为和正常行为的,但是在转账完成后,是不是可以分辨出到底有没有发生虫洞攻击?比如 Carol 能不能发现自己被跳过忽略了;Alice 能不能发现如果是按照 Alice-Bob-Dave-Edward 的路径,她只需支付3CKB的手续费,而她现在支付了4CKB。然后通过这种攻击后提交证明的方式,惩罚作恶节点,从而防范虫洞攻击

不是路径的问题,而是通道一旦建立,攻击者可以绕过中间某个节点。

嗯嗯,攻击者可以绕过中间某个或者某些节点,这个攻击没有很好的办法可以阻止。但是在攻击完成后,可不可能通过什么方式,发现的确发生了这一次虫洞攻击,然后再采用其他手段,对攻击者进行惩罚什么的

你这个想法我考虑过。虽然这个绕开了“两轮交互无法避免虫洞攻击”,但是实际上攻击完成后,除非受害者意识到了真实路径是什么,否则他永远无法知道自己是否受到了攻击。受害者想要知道这种消息,在不增加每次 off-chain 支付沟通轮次的情况下(依然是两轮交互),受害者只能等到这次支付所有节点想智能合约提交关闭通道的申请时获得这样的消息。而目前关闭通道是不包含每次支付的消息的,只包含最终状态。如果强行修改协议为包含每次支付的部分状态也是不现实的,因为智能合约需要等到这次支付有关的所有人都向智能合约提交信息才能判断受害者是否受到了攻击,这要求每一笔支付都有部分消息被包含在关闭通道的提交里面,这对 scalability 来讲是不可容忍的。