以太坊多种盗币揭秘之重放攻击
摘要: 账户余额足够时,会出现大量应该被移除的pendin交易,在部分交易完成后,pending交易消失的的情况。当账户余额足够时,重新广播交易的节点会将之前所有的交易再次广播出去,在交易完成后,剩余pending交易会因为余额不足再次从交易缓存池中被移除。
交易缓存池的重放攻击
对于曾经被盗币,修复方案仅为关闭对公网暴露的RPC接口,关闭后继续使用节点中相关账户的节点,可能会受到该攻击。
在之前讲到,为了实现攻击者不停的发送转账请求的功能,笔者使用了while True循环,并且在geth终端中看到了多条成功签名的交易hash。由于交易缓存池拥有一定的校验机制,所以除了第一笔交易0x4ad68aafc59f18a11c0ea6e25588d296d52f04edd969d5674a82dfd4093634f6外,剩下的交易应该因为账户余额不足而被移出交易缓存池。
但是在测试网络中却出现了截然不同的情况,在我们关闭本地的geth客户端后,应该被移出交易缓存池的交易在余额足够的情况下会再次出现并交易成功:
(为了避免该现象的出现,可以在成功转账之后利用break终止相关的循环)
这个交易奇怪的地方在于:在账户余额不足的情况下,查找不到任何Pendding Transactions:
当账户余额足够支付时,被移出交易缓存池的交易会重新出现,并且是 Pendding 状态。
在部分pendding的交易完成后,剩余的交易将会继续消失。
这也就意味着,如果攻击者能够在利用偷渡漏洞的过程中,在交易被打包进区块,账号状态发生改变前发送大量的交易信息,第一条交易会被立即实行,剩余的交易会在受害人账号余额大于转账金额+gas 消耗的金额的时候继续交易,而且这个交易信息在大多数情况下不会被查到。
对于这个问题进行分析研究后,我们认为可能的原因是:以太坊在同步交易缓存池的过程中可能因为网络波动、分布式的特点等原因,导致部分交易多次进入交易缓存池。这也导致部分应该被移出交易缓存池的交易多次重复进入交易缓存池。
具体的攻击流程如下:
本地复现过程
对于前面讲到的现象进行了多方面的猜测。最终在低版本的geth中模拟复现了该问题。但由于现实环境的复杂性和不可控性,并不能确定该模拟过程就是造成该现象的最终原因,故该本地复现流程仅供参考。
攻击复现环境位于私链中,私链挖矿难度设置为0×400000,保证在挖出区块之前拥有足够的时间检查各节点的交易缓存池。geth的版本为1.5.0。
被攻击者的节点A:通过geth–networkid 233–nodiscover–verbosity6–ipcdisable–datadir data0–rpc–rpcaddr0.0.0.0console启动。
矿机节点B,负责挖矿:通过geth–networkid 233–nodiscover–verbosity 6–ipcdisable–datadir data0–port30304–rpc–rpcport 8546 console启动并在终端输入miner.start(1),使用单线程进行挖矿。
存在问题的节点 C:通过geth–networkid 233–nodiscover–verbosity 6–ipcdisable–datadir data0–port 30305–rpc–rpcport 8547 console启动。
各节点启动后通过admin.nodeInfo和admin.addPeer()相互添加节点。
1. 攻击者扫描到被攻击节点A开放了rpc端口,使用如下代码开始攻击:
2.节点A的用户由于转账的需求,使用personal.unlockAccount()解锁账户,导致偷渡漏洞发生。由于一共进行了三次转账请求并成功广播,所以A、B、C交易缓存池中均存在这三笔交易。
3. 由于网络波动等原因,此时节点C与其它节点失去连接。在这里用admin.removePeer()模拟节点C掉线。节点B继续挖矿,完成相应的交易。后两笔交易会因为余额不足从交易缓存池中移除,最终节点A,B的交易缓存池中将不会有任何交易。
4.上述步骤1-3即是前文说到的偷渡漏洞,被攻击者A发现其节点被攻击,迅速修改了节点A的启动命令,去除了–rpc–rpcaddr 0.0.0.0,避免RPC端口暴露在公网之中。之后继续使用该账户进行了多次转账。例如,使用其它账号给节点A上的账号转账,使的节点A上的账号余额为1.980065000882e+24
5.节点C再次连接进网络,会将其交易池中的三个交易再次广播,发送到各节点。这就造成已经移除交易缓存池的交易再次回到交易缓存池中。
6.由于此时节点A的账户余额足够,第二个交易将会被打包进区块,节点A中的余额再次被盗。
在实际的场景中,不一定会出现节点 C 失去连接的情况,但由于存在大量分布式节点的原因,交易被其它节点重新发送的情况也是可能出现的。这也可以解释为什么在前文说到:账户余额足够时,会出现大量应该被移除的pendin交易,在部分交易完成后,pending交易消失的的情况。当账户余额足够时,重新广播交易的节点会将之前所有的交易再次广播出去,在交易完成后,剩余pending交易会因为余额不足再次从交易缓存池中被移除。
除了文章说到的现象外,亦不排除攻击者设置了恶意的以太坊节点,接收所有的交易信息并将部分交易持续广播。但由于该猜想无法验证,故仅作为猜测思路提供。
(作者:区块链安全档案,内容来自链得得内容开放平台“得得号”;本文仅代表作者观点,不代表链得得官方立场)
评论(0)
Oh! no
您是否确认要删除该条评论吗?