前言
最近关于交易所的假充值漏洞层出不穷,很显然,交易所与公链的对接并没有我们想象得那么完善,此类问题由慢雾科技首次提出,在这里感谢他们采取负责任的披露方式来让整个生态认识到此类问题的严重性。
在门罗币的该问题披露之后,BCSEC团队对此进行了相关分析,供行业内参考。
漏洞分析
该问题在今年6月11就已经被用户发现,并在门罗币的GitHub仓库上提交了相关issue。
该用户称他在执行show_transfers out指令的时候客户端给他返回了错误的转账数量,并表示非常怪异。
随后,在当天门罗币的官方团队便对此进行了修复,并发布了修复代码。
右方的代码为已修复的代码,其实对于漏洞的修复关键代码就是被红框标记的那一段。我们来细看一下。
if (public_keys_seen.find(pub_key_field.pub_key) != public_keys_seen.end())
{
MWARNING("The same transaction pubkey is present more than once, ignoring extra instance");
continue;
}
public_keys_seen.insert(pub_key_field.pub_key);
以上便是最主要的修复代码,大概意思是判断当前事务的pubkey是否在之前的pubkey中已存在,若已存在便跳过该事务。
若没有加上这段代码,会造成怎样的后果呢?
每笔交易的pubkey的都是唯一的,所以若两笔交易的pubkey一样便意味这两笔交易是完全一样的重复交易,应该在保留其中一笔交易之后其他的重复交易完全忽略。
攻击者可以发送大量重复的交易给对方,这在门罗币中是允许的,因为最终计算余额不会计算重复的交易,重复的交易会被忽略。但是由于该漏洞修复之前,门罗币客户端的show_transfers指令并没有跳过重复的交易,所以每笔重复交易的转账金额也会被计算在内并最终输出出来。
也就是说,当某个人或者交易所通过show_transfers指令来确认入账资金的时候,便会出现问题,一个很常见的攻击场景便是攻击者对交易所的充值地址发送多条重复交易,若交易所校验不严谨没有检测真实钱包收账余额,仅仅通过show_transfers来确认用户充值的话,便会出现假充值漏洞,导致交易所给用户充值的余额和交易所自己实际收到的余额不符,攻击者假充值成功后可以进行消费或提款。
利用方式
那么,要如何利用该漏洞呢,发送重复的交易在门罗币客户端中是没有提供相关指令的,所以目前只有两种方案。
1.根据门罗币的P2P协议,自行实现一个发包器,成本较高。
2.直接在门罗币的开源代码中插入利用代码,然后编译运行,成本较低。
该漏洞的发现者使用的是第二种方式,直接在门罗币的cryptonote_tx_utils.cpp文件的第354行中插入大量重复代码。
add_tx_pub_key_to_extra(tx, txkey_pub);
add_tx_pub_key_to_extra(tx, txkey_pub);
add_tx_pub_key_to_extra(tx, txkey_pub);
例如,在354中插入如上重复代码,这样在编译出的客户端每次发起交易的时候便会向目标多发送3次重复交易,这样便达到了利用该漏洞的目的,而且避免了花大量成本编写EXP,虽然这种方式相对于常见的EXP来说较为臃肿。
攻击案例
目前已经有攻击者对利用基于门罗币二次开发且没有修复该漏洞的加密货币ARQ币对Altex交易所进行了攻击,根据门罗币的Github仓库显示,门罗币有1607个分支,这些分支都有可能还没有修复此问题,导致被攻击者利用。
修复方式
1.交易所使用门罗币客户端v0.12.3.0或更高的版本来代替旧版本。
2.交易所加强充值验证逻辑,例如钱包实际余额验证。
参考
https://hackerone.com/reports/364904
https://bcsec.org/index/detail/tag/2/id/228