逃离黑暗森林:960万美元智能合约漏洞救援全记录

2020年9月,安全研究人员发现Lien Finance智能合约存在严重漏洞,25,000枚ETH面临风险。通过跨国协作与创新技术方案,成功从黑暗森林中救回960万美元用户资金。

逃离黑暗森林

2020年9月15日,一小群人彻夜工作,从一个脆弱的智能合约中救回了超过960万美元。这是我们的故事。

意外发现

我正准备结束一天的工作时,决定再看一眼某些智能合约。当然,我并没有期待发现什么有趣的东西。过去几周里,我看到了无数收益农耕克隆项目,它们都有着相同的宣传语:在我们这里质押代币,你就能成为下一个加密货币百万富翁。大多数项目只是经过充分审计代码的分叉,但有些项目进行了修修改改,有时会导致灾难性后果。

但在所有这些噪音中,我发现了一些以前从未见过的代码。该合约持有超过25,000枚以太坊,当时价值超过9,600,000美元,对于任何能在其逻辑中找到漏洞的人来说,这都将是非常丰厚的回报。

我快速浏览了转出以太坊的代码,发现了两处。其中一处将以太坊转移到一个硬编码的代币地址,所以可以忽略。第二个是一个销毁函数,它将以太坊转移给发送者。在追踪此函数的使用情况后,我发现任何人都可以免费为自己铸造代币,然后销毁它们以换取合约中的所有以太坊。我的心跳加快了。突然间,事情变得严重起来。

紧急响应

一些调查显示,我发现的合约是Lien Finance协议的一部分。不幸的是,他们的团队是匿名的!他们唯一支持的即时通讯平台是Telegram,我无法确定该频道的管理员是实际的协议开发者还是仅仅几个早期支持者。我最不想做的事情就是意外将漏洞利用方法泄露给错误的人。

在浏览他们的网站一段时间后,我注意到他们曾与ConsenSys Diligence和CertiK进行过审计。这似乎是一个很好的途径,因为ConsenSys和CertiK在审计期间肯定与开发者有过互动。我迅速在Telegram上联系了maurelian。

不幸的是,时间一分一秒过去,我的心继续怦怦直跳,但maurelian没有回应。看起来他已经睡觉了。绝望中,我向ETHSecurity Telegram频道发送了一条消息。

几分钟内,我收到了一个过去合作过多次的人的消息——Alex Wade。

组建救援团队

“我刚刚把头靠在枕头上,就有人敲我的门。是我的室友:‘Sam在ETHSec Telegram上询问有没有Diligence的人。’”

“事实上,这是一个漫长的夜晚。了解Sam的人都知道,这不会是好事。我找到了几个月前与Lien建立的频道和一个电子邮件地址。考虑到他们的团队是匿名的,这总比没有好。”

“我仍然半睡半醒。Sam不想在文本中透露细节,要求进行Zoom通话。我昏昏欲睡地希望回到床上,试图评估情况的严重性:”

“五分钟后,很明显这种情况需要咖啡”

Sam和我一起审查了代码。到这个时候,Sam已经准备了一个示例漏洞利用,并能够在他的机器上确认问题。对话很快转向讨论选项:

  1. 尝试自己利用这个漏洞
  2. 联系Lien并让他们公开,敦促用户提款

这两个选项都不吸引人。第一个选项有风险,因为正如Dan Robinson和Georgios Konstantopoulos在《以太坊是黑暗森林》中讨论的那样,我们的交易被抢先交易的可能性非常真实。第二个选项同样有风险,因为公开声明会引起对问题的关注,并为攻击者创造机会窗口。我们需要第三个选项。

回忆起《以太坊是黑暗森林》中的一个部分,Sam联系了Scott Bigelow:

技术挑战

“如果你发现自己处于这种情况,我们建议你联系Scott Bigelow,他是一位一直在研究这个主题的安全研究员,并且有一个更好的混淆器的原型实现。”

“在参与《以太坊是黑暗森林》中的恢复尝试后,我渴望重新比赛,那次尝试最终输给了抢先交易者。我花时间监控抢先交易并设计了一个简单的系统,似乎能够欺骗通用的抢先交易者,至少用我能够测试的200美元是这样。当Sam在深夜联系我,用听起来无害的’介意再熬夜一个小时左右吗’时,我迫不及待想试一试!我已经在计划了:我将如何进行一些调整,熬夜几个小时,在帮助救援和归还几千美元用户资金后获得成就感,然后好好睡一觉。”

“当Sam与我分享合约时,这些计划立即破灭了:约25,000 ETH,价值960万美元,处于危险之中。尽管我多么想要重新比赛,但960万美元远远超出了我简陋脚本的能力范围。”

矿池合作

“过去几个月,我一直在为此目的与矿工建立联系:白帽交易合作。如果有任何时候需要呼吁矿工包含交易而不给抢先交易者窃取的机会,那就是现在。幸运的是,Tina和我过去几个月一直在合作建立这种合作。当时看起来机会渺茫,但值得一试:让Tina加入救援尝试,与矿池合作挖掘私人交易。”

“我刚从Bobcat森林大火中撤离,正在啜饮着不知名的海滩饮料,对着黑暗太平洋波浪的单调声音发呆,这时Sam的Telegram私信把我震回了一个更黑暗的现实:‘资金面临风险,可被抢先交易’。过去几周,我一直在与Sam和Scott合作一个关于MEV的研究项目,在他们发送请求之前就已经能猜到他们的要求:一个直接通道,保护白帽交易不被内存池’黑暗森林’中的’高级捕食者’狙击。”

由于这是一个有风险的举动,涉及向矿工暴露我们的策略,我们决定应该首先尝试获得匿名Lien团队的批准。在Alex尝试通过ConsenSys内部渠道联系的同时,我们也尝试让CertiK加入。

跨国协作

“我意识到可能还需要4个小时CertiK的美国审计师才会醒来,但时间正在流逝。除了知道CertiK为相当多的亚洲项目提供服务外,我对CertiK了解不多,我尝试联系CertiK中国团队以利用时区差异。我在’DeFi the World’和’Yellow Hats’微信群中发送了一条听起来很随意的消息。30分钟内,四个线索独立地滑入我的私信,确认我联系的微信ID确实是CertiK CTO Zhaozhong Ni本人。我被加入了一个有5名CertiK团队成员的微信群,但此时我仍然不能透露项目或漏洞细节。为了最小化暴露和潜在责任,我们只能邀请一名CertiK成员加入我们的白帽行动。在通过官方电子邮件进行最终验证后,CertiK的工程负责人Georgios Delkos加入了我们的通话。”

在Georgios的帮助下,Alex能够迅速联系到Lien团队并验证他们的身份。我们向他们通报了当前情况,并请求他们允许尝试直接与矿池合作以救援脆弱资金。经过一些审议,Lien团队同意尝试直接救援资金或发布警告的风险太高,并批准继续前进。

技术实施

现在我们需要确定一个拥有现成基础设施并愿意尽快与我们合作的矿池。我们应该联系哪个矿池?矿池的哪个联系人能够迅速做出技术决策,帮助我们争分夺秒?

SparkPool浮现在脑海中,因为我知道他们一直在开发一个名为Taichi Network的公共基础设施,可以轻松提供我们所需的功能。我决定联系SparkPool的联合创始人Shaoping Zhang,他过去曾帮助我调查内存池事件。

半小时后,Shaoping回应:“你的意思是我们有没有交易白名单服务?抱歉,我们没有。” 糟糕,有些东西在翻译中丢失了,“白帽"和"白名单"在中文中发音相似。

“有价值1000万美元的资金面临风险。samczsun在线。“我再次尝试沟通情况而不透露任何具体细节。

“你们又在拯救世界了吗?需要我们的矿池帮助吗?“令我惊讶和宽慰的是,Shaoping开玩笑地提供了帮助。经过官方电子邮件验证后,Shaoping在一屋子SparkPool开发人员的支持下加入了我们的马拉松式Zoom通话。

关键技术方案

“午饭后,正当我准备小睡时,我收到了Tina的消息:‘SparkPool以前帮助过白帽交易吗??‘我起初误以为是交易白名单。以前没有白帽接触过我们,我们对’白帽交易’涉及的内容不熟悉。在Tina更详细地解释后,我意识到他们需要的是私人交易服务,即白帽想要发送交易来拯救DeFi合约,但为了防止被抢先交易,他们需要矿池包含交易而不广播它。”

“我们一直在我们的Taichi Network上开发’私人交易’功能,该功能仍在开发中,尚未经过测试。我将白帽的请求带给我们的开发团队,并解释了紧急性:我们的私人交易功能需要在几小时内投入生产。我们的开发人员表示他们会尽力按时完成,我们立即开始工作。我们在2小时内完成了私人交易功能的开发,然后花了一些时间修复错误。”

在我们完成内部测试后,我们将whitehat.taichi.network端点发送给Scott Bigelow以交付白帽有效载荷。

交易执行

当SparkPool努力交付这个全新的白帽API时,Sam和我正在完成生成4个顺序签名交易的脚本。按顺序处理这些交易本身不会提取约25,000 ETH,但会将30,000 SBT+LBT代币(被"错误"创建)转移给Lien团队,允许他们提交最终交易将这些代币转换回ETH。通过将可无限铸造的SBT+LBT代币转移给Lien而不是ETH,我们使用更多交易来向通用抢先交易者隐藏攻击工作原理(以防重组),并且我能够避免产生960万美元的收入,即使只是暂时的。

一旦我们生成了4个签名交易,Sam和我花了很长时间使用各种多调用交易模拟工具验证它们的组合行为。这4个交易,总共不到1.5KB的数据,准备窃取960万美元的资产,只要除了SparkPool之外没有人在为时已晚之前看到它们。

我用一个无意义的交易测试了SparkPool的白帽端点,它完全按预期工作:交易在内存池中看不到,然后突然作为SparkPool区块的一部分出现!就像看着水蒸气直接变成冰,而没有那个讨厌的液相。

在调整交易创建脚本以直接将交易馈送到SparkPool的新端点后,时机到了。我犹豫了片刻,但这绝对是我们最大的努力。我们可能会损失960万美元,但不会有遗憾:我在IntelliJ中点击了"运行”。不知道为什么,我预计需要一段时间,就像节点会理解情况的严重性并慢慢来。但它没有;交易在几毫秒内就发送了。

成功救援

通话中的每个人都开始如此精力充沛地刷新Etherscan,我想知道Etherscan团队是否会看到3分钟的流量高峰。由于只有SparkPool拥有这些交易,并且只有一部分SparkPool的算力专用于此目的,除了出汗和等待,别无他法。每个来自其他矿工出现的区块都在嘲笑我们。通话中会有人宣布矿工,引起紧张的轻笑。在我们的交易被包含之前大约15个区块感觉像是几个小时,但最终,我们有了完美无瑕的交易:被挖掘,按顺序,没有回滚。

我们宽慰地看着越来越多的区块建立在我们的区块之上,我们对区块重组的担忧迅速消退。Lien团队现在拥有足够的SBT+LBT代币来清算他们的整个系统,Sam去协调救援的最后阶段。

既然我们已成功将代币转移给Lien,并且没有任何抢先交易的迹象,无论是尝试过的还是其他的,我们迅速向他们发送了好消息。他们确认收到了代币,并立即发送交易提取合约中存储的大部分以太坊。几秒钟后,一个待处理交易出现在Etherscan上。

当我们看着加载指示器旋转时,我趁机反思导致这一刻的事件。最初只是快速浏览一些合约,最终变成了完整的战情室,吸引了来自世界各地的专家。没有Alex和Georgios,我们无法联系到Lien开发者。没有Scott,我们将盲目进行救援。没有Tina,我们将无法联系到CertiK或SparkPool。没有SparkPool,我们将注定重复Dan几周前写下的历史。

然而,在一个周二的深夜,我们这群不太可能的人为了共同的事业团结起来,不知疲倦地工作,试图确保超过960万美元能够归还给它们的合法所有者。我们过去7个小时的所有努力都导致了这一个待处理交易和随之而来的旋转点。

当加载指示器最终变成绿色勾号时,通话中紧张的沉默让位于集体的宽慰叹息。

我们逃离了黑暗森林。

comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计