您的需求已经提交,我们将在48小时内联系您
全国服务热线:400-1000-221
确定
试用申请
请填写真实的企业信息,方便我们尽快了解您的企业安全需求。

*公司名称

*所在行业

*联系人

QQ

*联系电话

您的需求
私有云产品
云垒 立体式私有云安全纵深防御平台
云眼 新一代(云)主机入侵监测及安全管理系统
啸天 网络安全态势感知
云固 新一代网页防篡改系统
云御 新一代网站应用防御系统
云网 补丁管理系统
公有云产品
云磐 立体式公有云安全纵深防御平台
安全云主机
高级服务
抗DDoS云服务
高级渗透测试服务
攻击取证与溯源分析服务
信息安全等级保护服务
重大活动安保服务
勒索病毒防护
区块链安全
其他需求
*验证码
{{message}}
试用申请
CVE-2018-17145:比特币INVDoS漏洞

漏洞概述

2018年6月,研究人员Braydon Fuller 在Bitcoin Core 中发现了一个安全漏洞——INVDoS 漏洞,CVE编号为CVE-2018-17145。该漏洞为Inventory 内存溢出DoS漏洞,属于DoS攻击漏洞的一种。攻击者利用该漏洞可以创建伪造的比特币交易,当比特币区块链节点处理该交易时回引发服务器内存资源不受控制的消耗,最终使得系统奔溃。

漏洞修复后研究人员选择不公开漏洞细节,以预防潜在的漏洞利用。上周,有其他研究人员独立发现了该漏洞,随后研究人员将漏洞细节公开。

 

攻击技术细节

恶意节点可以通过快速发送多个含有随机哈希值的交易inv消息来发起攻击,最多发起49999项,但不发送对应的tx数据。当多个节点同时发起攻击时可以加速攻击并升级为DDoS 攻击。当连接速度为1Gbps (125 MB/s) 时,每秒钟可以发送含有49999项的83inv消息,也就是说攻击的最大速度为每秒钟 4166584 inv 项。

Bcoin细节

比特币中的漏洞来源于用来追踪节点inventory 的Map的大小可以没有限制的增加,但是有一个基于时间的限制在节点拖延和没有响应时可以清空txMap。如果有足够的inventor哈希值在timeout 检查前被发送,内存就会快速增长并引发进程奔溃。P2P 网络消息也可以通过暴露的代码路径 handlePacket -> handleInv -> handleTXInv -> ensureTX -> getTX 在没有限制的情况下增加txMap 内存:

getTX(peer, hashes) {
...
for (const hash of hashes) {
if (this.txMap.has(hash))
continue;
this.txMap.add(hash);
peer.txMap.set(hash, now);
...
}
...
}

该问题可以通过增加对节点txMap 大小的限制和移除超过限制的节点来解决。Christopher Jeffrey 在commit 05c38853d7f50fb4ad87e28fa7b46017f78e2955 中修复了该问题。

Bitcoin Core细节

Bitcoin Core 中的问题更加隐蔽,位于限制类似map增长的代码中,参见src/net processing.cpp 中的ProcessMessage :

if (vInv.size() > MAX_INV_SZ)
{

LOCK(cs_main);
Misbehaving(pfrom->GetId(), 20,
strprintf("message inv size() = %u",
vInv.size()));
return false;
}

但是程序的真实行为有所不同,从程序的行为来安似乎并没有限制,而且内存可以无限增长。该问题很容易检查,对src/net processing.cppProcessMessage 的GetMainSignals().Inventory(inv.hash) 没有保护的限制会使得m callbacks pending的大小比用来追踪事件的SingleThreadedSchedulerClient 的处理以更快的速度增长。漏洞源代码参见src/validationinterface.cpp:

void CMainSignals::Inventory(const uint256 &hash) {
m internals->m schedulerClient.AddToProcessQueue([hash, this] {
m internals->Inventory(hash);
});
}

该漏洞通过移除有漏洞的代码修复,具体参见commit beef7ec4be725beea870a2da510d2817487601ec。

Btcd细节

Btcd将接收到的交易inventory项目保存在peer.knownInventory (peer/peer.go)中,peer.knownInventory 是一个MRU map (mruInventoryMap),用来限制大小。但是peer.knownInventory的实例使用的MRU map暴露了一个引发内存泄露的漏洞。mruInventoryMap.Add 中到wire.InvVect的指针在之后的SyncManager.handleInvMsg 中进行了修改。在netsync/manager.go 中:

if peer.IsWitnessEnabled() {
iv.Type = wire.InvTypeWitnessTx
}

mruInventory.Add 尝试从invList 中清除LRU 项目时,而且不再匹配invMap key,因为该对象已经改变了。因为lru.Type != iv.Type所以请除会失败。因为内存使用不断的增长,在peer/mruinvmap.go中:

if uint(len(m.invMap))+1 > m.limit {
node := m.invList.Back()
lru := node.Value.(*wire.InvVect)
// Evict least recently used item.
delete(m.invMap, *lru)
...
}

除了mruInventoryMap 外,还有2个map会保存接收到的inventory 哈希作为peerSyncState: requestedTxns 和 requestedBlocks 的密钥。这些map会用来预防内存泄露。Btcd 通过转向修复的 LRU实现或转向更新版的map来修复该问题。该漏洞在7月17日通过commit 4b3f7f3c7a490151801c0aaf117befeae1c6bc1b修复。

更多漏洞技术细节参见:https://invdos.net/#