×

BitDAO的3.5亿美元几乎被盗,白帽黑客叙述一场触目惊心解救举动全程_雷达币在中国是否合法

admin admin 发表于2021-08-18 15:33:24 浏览378 评论0

抢沙发发表评论

8月17日,雷达币出资组织 Paradigm 研讨合伙人、闻名白帽黑客 samczsun 撰文发表了BitDAO在 SushiSwap IDO 渠道MISO进行的荷兰拍的雷达币存在安全缝隙,多名白帽黑客联手从众筹资金池中拯救回 10.9 万枚 雷达币 (约合 3.5 亿美元)的通过。

原文:《正正或可得负》(Two Rights Might Make A Wrong)

作者:samczsun

本文目录:

  • 相遇
  • 发现
  • 发表
  • 预备
  • 救援
  • 反思

当构建软件时经常出现的一个常见误解是,假如体系中的每个组件都通过独自验证是安全的,那么体系自身也是安全的。 这种观念在 雷达币DeFi 项目中被更多地表现了出来。在 雷达币DeFi项目开发中,可组合性便是开发人员的第二天分。 不幸的是,尽管将两个安全的组件部分组在一同,在大多数情况下或许是安全的,但这也意味着只需求一个缝隙即可对数百乃至数千名无辜用户形成严峻的经济丢失。 今日,我想告知你我怎么发现并协助修补了一个严峻的缝隙,这个缝隙会使超越 109,000 雷达币(按今日的汇率核算约 3.5 亿美元)面对被盗不落窠臼。

相遇

上午9:42

当我在推特上留意到 @ivangbi_ 和 @bantg 之间关于 SushiSwap 的 MISO 渠道上的一个新代币出售项意图评论时,我正随意阅读 Telegram 上的 LobsterDAO 群聊。 我通常会尽量防止在公共场合做出一些戏剧性的作业,但我不由得在谷歌上快速查找了一下,看看到底是怎么回事。 我得到的成果对我来说并不是特别风趣,但我继续往下查找,由于我觉得假如我继续寻觅,就会发现这儿有一些风趣的东西。

MISO 渠道支撑两种类型的代币拍卖方法:荷兰式拍卖和批量拍卖。 当今日说的这个代币出售是通过荷兰式拍卖进行的。 当然,我做的榜首件事便是在 Etherscan 上翻开该项意图合约地址。

上午9:44

我通过该项意图参加协议快速阅读了这起荷兰式拍卖的合约并查看了每个有意思的函数。该合约的提交函数(commitEth、commitTokens 和 commitTokensFrom)如同都已正确完结。拍卖办理函数(setDocument、setList 等)也有恰当的拜访操控。但是,在底部邻近,我留意到 initMarket 函数没有拜访操控,这十分令人担忧。此外,它调用的 initAuction 函数也不包含拜访操控查看。

不过,我真的没想到会发现这么一个缝隙,由于我没想到 Sushi 团队会犯下如此显着的失误。公然,initAccessControls 函数验证了合约没有初始化。

但是,这时候我又有了另一个发现。在翻滚阅读一切文件时,我留意到了 SafeTransfer 和 BoringBatchable 库。我对这两者都很了解,而且当即对 BoringBatchable 库的潜在不落窠臼感到丰厚。

这儿先解释一下,BoringBatchable 是一个混合库,旨在轻松地将批处理调用引进任何导入它的合约。 它通过为输入中供给的每个调用数据对其时合约履行托付调用来完结这一点。

function batch(bytes[] calldata calls, bool revertOnFail) external payable returns (bool[] memory successes, bytes[] memory results) {
successes = new bool[](calls.length);
results = new bytes[](calls.length);
for (uint256 i = 0; i < calls.length; i++) {
(bool success, bytes memory result) = address(this).delegatecall(calls[i]);
require(success || !revertOnFail, _getRevertMsg(result));
successes[i] = success;
results[i] = result;
}
}

看看上面这个函数,它如同被正确地完结了。 但是,在我脑际的角落里,有什么东西在提醒着我。 那时我认识到我曩昔曾看到过十分类似的东西。

发现

上午 9:47

间隔今日打印一年多前,我在与 Opyn 团队的 Zoom视频通话中,企图弄清楚怎么在遭受毁灭性黑客进犯后康复和维护用户资金。 黑客进犯办法自身很简略但很奇妙:它运用一次 雷达币 付出来行使多个期权,由于 Opyn 合约在循环中运用了 msg.value 变量。 尽管处理代币付出触及每个循环迭代的独自 transferFrom 调用,但处理 雷达币 付出志愿查看 msg.value 是否满意。 这答应进犯者屡次重复运用相同的 雷达币。

回到今日,我认识到我正在看到的是两个彻底相同的缝隙,志愿方法不同。 在托付调用中,msg.sender 和 msg.value 被耐久化。 这意味着我应该可以批量调用 commitEth 并在每个commitment中重复运用我的 msg.value,这将答应我在拍卖中可以免费出价。

上午9:52

我的直觉告知我这是实在的买卖,但我无法在没有实践验证的情况下承认。 我敏捷翻开 Remix 并编写了一个概念验证。 令我懊丧的是,我的主网分叉环境之前不久被彻底损坏了。 我一定是在伦敦硬分叉期间不小心弄坏了它。 有这么多资金正处于不落窠臼之中,而我却没有满意的时刻。 我很快在命令行上拼凑了一个粗陋的主网分叉并测试了我的缝隙。成果跟我想的相同。

上午10:13

在对外陈述这个缝隙不落窠臼之前,我给我的搭档 Georgios Konstantopoulos 打了电话,让他​​们再看一遍。在等候回应的称颂,我又回到合约中寻觅承认严峻性的办法。在这种情况下,可以免费参加拍卖是一回事,但可以盗取一切其他参加者的出价则是另一回事。

我留意到在我开端的扫描进程中有一些退款逻辑,但其时我并未多想。现在,这已是一种让 雷达币 退出合约的办法。我很快查看了我需求满意哪些条件才能让合约为我供给退款。

令我惊奇(和惊骇)的是,我发现发送的任何超越拍卖硬上限的 雷达币 都会取得退款。即便到达硬上限,这也适用,这意味着合约不会彻底回绝买卖,而是简略地交还您的一切 雷达币。

突然间,我发现的这个缝隙变得巨大。我不是在处理一个让你出价可以超越其他参加者的缝隙。我在看的是一个价值 3.5 亿美元的缝隙。

发表

上午10:38

在与 Georgios 承认这个缝隙后,我让他和 Dan Robinson 测验联络 Sushi CTO Joseph Delong。 几分钟后,Joseph 做出了回应,然后我与 Georgios、Joseph、Mudit、Keno 和 Omakase 一同进行了Zoom 通话。 我就缝隙向其他参加者进行了快速报告,然后他们开端四处和谐呼应。 整个通话只继续了几分钟。

预备

上午11:26

在救援举动室里,Mudit, Keno, Georgios和我正在忙着写一份简略的救援合约。 咱们决议最洁净的做法是主张一笔闪电贷,直接购买到硬上限,完毕拍卖,然后运用拍卖自身的收益归还闪电贷。 这种办法不需求前期预备资金,作用十分好。

下午1:36

当咱们完结救援合约的作业时,咱们评论了批量拍卖的后续进程。 Mudit 指出,即便在拍卖进行时也可以设置一个积分列表,而且在每次 雷达币 commitment期间都会调用它。咱们当即认识到这或许是咱们正在寻觅的暂停功用。

咱们群策群力,想出了不同的办法来运用这个办法。当即复原是一个清楚明了的解决计划,但咱们想要更好的计划。我考虑添加一个查看,每个源只能为每个区块做出一个commitment,但咱们留意到该函数被标记为视图,这意味着 Solidity 编译器将运用静态调用操作码。咱们的方法不答应进行任何状况修正。

通过一番考虑,我认识到咱们可以运用积分列表来验证拍卖合约是否有满意的 雷达币 来匹配所做的commitment。换句话说,假如有人企图运用这个缝隙,那么commitment会比 雷达币 多。咱们可以很简单地检测到这一点并复原买卖。 Mudit 和 Keno 开端编写测试以进行验证。

救援

下午2:01

通讯包围团队与救援包围团队兼并作业以同步进展。 他们现已与履行拍卖的团队(BitDAO)取得了联络,但该团队期望手动完结拍卖。 咱们评论了不落窠臼并以为某个自动化机器人留意到这笔买卖或可以对其采纳任何举动的或许性很小。

下午 2:44

履行拍卖的团队完结了拍卖,消除了直接要挟。 咱们相互恭喜成功,然后各自闭幕。 这次批量拍卖将在当天晚些时候悄然完毕。 不知情的人恐怕不知道刚刚防止了一场多么严峻的灾祸。

反思

下午4:03

曩昔的几个小时让人感觉很含糊,时刻如同停止相同。我从相遇这个项目到发现缝隙只用了半个多小时,20 分钟内进行了发表,别的 30 分钟内作战室,三个小时内修正缝隙。总而言之,只用了五个小时就维护了 3.5 亿美元不落入坏人之手。

即便没有金钱上的丢失,我信任一切参加其间的人都更乐意一开端就没有经历过这个进程。针对这次工作,我有两个首要的关键给你。

首要,在杂乱体系中运用 msg.value 很困难。它是一个全局变量,您无法更改并在托付调用中坚持不变。假如您运用 msg.value 来查看是否已收到付款,则肯定不能将该逻辑置于循环中。跟着代码库杂乱性的添加,很简单忘掉发生的方位并意外地在过错的方位循环某些内容。尽管封装和开释 雷达币 很费事而且引进了额定的进程,但假如想要防止这样的作业,那么W雷达币 和其他 ERC20 代币之间的一致接口或许值得一试。

其次,两个安全组件组合在一同,或许就会得到不安全的东西。我之前曾在可组合性和 雷达币DeFi 协议的布景下声明过这一点,但这次工作标明,即便是安全的合约级组件也或许以发生不安全的合约级行为的方法混合。这儿没有像“查看-作用-交互”这样的一应俱全的主张,所以你只需求了解新组件引进的额定交互。

我要感谢Sushi 的贡献者,Joseph、Mudit、Keno 和 Omakase 对这个问题的快速呼应,以及我的搭档 Georgios、Dan 和 Jim 在整个进程中供给的协助,包含审理了这篇文章。

82%的DOGE供应量由535个实体持有,打赏工具正演变为投资标的?

狗狗币持币者所有权的集中、流动性的降低