长推:被盗4800万美元,Kyber 合约漏洞深入研究
【GPT】 Kyber漏洞是一个复杂的智能合约漏洞,攻击者利用LP范围头寸调整曲线的流动性值,以获得无限的金钱故障。Kyber可以在现有合约上打补丁,加入断言,以防止出现漏洞。
原文标题:Finished a preliminary deep dive into the Kyber exploit
1/ 完成了对 Kyber 漏洞的初步深入研究,我想我现在对发生的事情有了很好的了解。
这无疑是我见过的最复杂、最精心设计的智能合约漏洞利用……
2/ 首先要注意的是,此漏洞是针对 Kyber 实施中心化流动性而特有的。
没有理由相信其他信誉良好的中心化流动性 dex,例如 Ambient 或 Uniswap,会受到此漏洞的威胁(尽管 Kyber 分叉显然是)。
3/ 我们将看看攻击者在以太坊上耗尽的第一个矿池 ETH/wstETH。尽管所有其他池都遵循类似的策略。
对这个矿池的攻击可以在这个交易中找到:
https://etherscan.io/tx/0x09a3a12d58b0bb80e33e3fb8e282728551dc430c65d1e520fe0009ec519d75e8/advanced
4/ 这个特定的交易消耗了三个独立的池,但现在我们只关注 ETH/wstETH 的消耗。
每个池的排水过程是独立的,因此我们只需要了解一个即可。每个池的利用都是在闪电贷中进行的,以操纵价格和流动性。
5/ 在 wstETH/ETH 案例中,漏洞利用从 1 万个 wstETH(价值 2300 万美元)的闪电贷开始。
下一步是将 2800 个 wstETH(价值 600 万美元)交换到池中,将价格从 1.05 ETH 推高到 0.0000152。与大多数闪电贷不同,其原因不是为了操纵预言机。
6/ 关键是将池价格移动到中心化流动性曲线的区域,该区域现有流动性为 0。由于攻击依赖于对 Kyber 集中流动性数学的极其精确的操纵,这基本上创建了一个“新画布”。
7/ 该漏洞以 0.0000146 至 0.0000153 的价格范围铸造 3.4 wstETH 流动性。然后,利用者出于某种原因燃烧了 0.56 wstETH 的流动性(可能是为了使后续的数值计算完美地排列)。
8/ 该漏洞利用该价格执行两次掉期。现在请记住这里没有其他流动性。在没有数字错误的情况下,这样做的人只会用自己的流动性来回交易,并且所有流量将净为零(减去费用)。
9/ 然而,发生的是无限的金钱故障。
第一个掉期是剥削者以 0.0157 ETH 的价格出售 1056 wstETH,将价格压低至 0.0000146(略低于其流动性价格范围)。
10/ 第二次交换方向相反。剥削者以 0.06 ETH 从池中购买 3911 wstETH,将池的价格推回至 0.00001637(略高于其流动性范围的上限)。
11/ 就是这样。漏洞利用已完成。资金池已耗尽。
请注意,在第二次交换中,他收到的钱多于第一次交换中支付的金额(3911 vs. 1052 wstETH)。请记住,这里唯一的流动性是他一开始铸造的 ~3 wstETH。额外的钱从哪里来?
12/ 这就是事情变得非常棘手的地方。我花了几个小时才弄清楚发生了什么。
第一条线索来自于第二次互换结束时池流动性的静态状态。注意到什么奇怪的事情了吗?
13/ 在 Kyber 中,剩余范围内流动性的值位于“baseL”poolData 变量中。
这不应该是0吗?请记住,第二次掉期的价格“超出”了攻击者的流动性范围。这里不应该有流动性。
14/ 不知何故,该漏洞使矿池认为其流动性比这些价格范围内的实际流动性要多。现在我们明白了无限资金故障从何而来。
如果资金池认为流动性比实际多,那么它就会为大额掉期支付过高的费用。
15/ 第二条线索来自比较第一次和第二次交换的调用跟踪堆栈。
在 Kyber 中,当跨越刻度边界时,会调用“updateLiquidityAndCrossTick”。它根据该时刻的 LP 范围头寸调整曲线的流动性值。
关于【长推:被盗4800万美元,Kyber 合约漏洞深入研究】的延伸阅读
扬言要接管KyberSwap,加密史上「最硬气」的黑客留言
11月23日,KyberSwap遭受攻击,涉及资金4700万美元,黑客要求控制KyberDAO,拥有所有权,并要求原项目方放弃Kyber资产。社区猜测,黑客可能是KyberSwap团队成员或与KyberSwap有关的人员。
Pantera 合伙人:一文看懂兼容 EVM 的比特币经济层 L2 Mezo
Mezo是一家旨在解决比特币生态系统中可扩展性和可编程性问题的公司,由资深专业人士领导。他们最近获得了2100万美元的融资,受到顶级投资公司的关注。通过构建兼容EVM的比特币层,Mezo将释放比特币在DeFi和其他领域的新潜力,成为塑造比特币未来的重要力量。
16/ 第二次掉期处理正确。开始时,价格超出了 LP 位置的范围。然后,掉期以低于 LP 仓位的价格结束。因此,当价格超出范围时会再次调用。
17/ 然而,在第一次交换中,updateLiquidityAndCrossTick 从未被调用。请记住,曲线价格一开始是在区间内的,然后掉期移动了价格,直到价格略微超出区间(请注意是 "略微")。
它本应被调用,但在第 1 次掉期时从未被调用。
18/ 现在一切都已就绪。
当 LP 仓位超出范围时,updateLiquidityAndCrossTick 负责将流动性从曲线中移除。当它移回范围内时,就会将流动性重新加入曲线。
如果它坏了会怎样?
19/ 如果你能让它在你的 LP 仓位超出范围时不调用,那么流动性就永远不会从曲线中移除。你现在欺骗了资金池,让它以为自己有更多的流动性。
20/ 但当你重新回到这个范围时,你要确保它被调用。流动性就会重新加入,尽管第一次时它从未被移除。这就是双重计算!资金池会重复计算原始 LP 仓位的流动性。
无限资金故障。
21/ 漏洞利用者是如何绕过掉期 1 的 updateLiquidity 调用的?这才是真正的技术性问题。
在集中流动性的 AMMs 中,掉期是作为一系列步骤计算的。在每一步中,您必须确定是否会达到 tick 边界或用尽掉期。
22/ Kyber 运行此交换步骤,并检查该步骤的结束价格是否与下一个刻度价格相同。如果不一致,则认为掉期已用尽,没有到达刻度线,因此不需要调用 `updateLiq`。
23/ 然而,请注意检查的是不等式,而不是方向比较。如果您以某种方式执行了一个交换步骤,并使价格结束在刻度线之外,那么即使您跨越了刻度线,检查也会失败,而且 "更新流动性 "永远不会被调用。
24/ 通常这种情况不会发生,因为 `computeSwapStep` 函数会首先计算在到达刻度线之前可交换的金额上限。
如果该金额小于掉期的剩余部分,它就会有把握地预测期末价格不会达到刻度线。
25/ calcReachAmount 预测掉期数量不会达到刻度线,但不知何故,最终价格却略微超出了刻度线。
26/ 这是因为 "达到数量 "是达到 tick 边界的上限,计算值为...22080000,而漏洞利用者设置的交换数量为...220799999。
由此可见,这个漏洞的设计是多么精心。检查失败率<0.00000000001%。
27/ 这与 Kyber 如何实现数量计算(计算上限,直到达到界限)和价格变化有关。两者使用的运算方式略有不同。
28/ 在非常小心控制和精确设计的情况下,界限检查会告诉你,小于 X 的掉期数量将使你保持在刻度线价格之内。
但并行计算的价格变动计算将应用 X 互换数量,并最终超出刻度线界限。
29/ 我记得在为 @ambient_finance 编写智能合约时,我对这个问题有无尽的偏执。
出于这个原因,我们的代码在每一步都包含了明确的检查,如果交换数量耗尽,这些步骤就会明确在 tick 边界内。
30/ 好消息是,至少可以直接在现有的 Kyber 合约上打补丁,在交换步骤中加入类似的断言,以防止将来出现这种漏洞。
免责声明:本文仅代表作者个人观点,不代表链观CHAINLOOK立场,不承担法律责任。文章及观点也不构成投资意见。请用户理性看待市场风险,以及遵守所在国家和地区的相关法律法规。
图文来源:Doug Colkitt,如有侵权请联系删除。转载或引用请注明文章出处!