Hundred Finance 攻击事件分析
Hundred Finance
背景知识
Hundred Finance 是 fork Compound 的一个借贷项目,在2023/04/15遭受了黑客攻击。攻击者在发起攻击交易之前执行了两笔准备交易占据了池子,因为发起攻击的前提是池子处于 empty 的状态(发行的 hToken 数量为 0)。
准备交易:
- https://optimistic.etherscan.io/tx/0xf479b1f397080ac01d042311ac5b060ceccef491867c1796d12ad16a8f12a47e
- https://optimistic.etherscan.io/tx/0x771a16e02a8273fddf9d9d63ae64ff49330d44d31575af3dff0018b04da39fcc
交易分析
两次准备交易一共存入 63816 + 30000000 = 30063816 wei WBTC,获得 3190800 + 1499976495 = 1503167295 wei hWBTC
WBTC decimal = 8,hWBTC decimal = 8
执行攻击交易,首先从 AAVE V3 闪电贷出来 500 WBTC

通过 tendery 的模拟交易可以查询到,在攻击交易执行前,池子中存在 30064194 wei WBTC

首先 redeem 之前存入的所有 WBTC,将池子还原到 empty 的状态。

redeem 之后池子中存在 378 wei WBTC(其中1wei为留存资金,377wei为reserve资金),发行 0 hWBTC。empty状态仅代表 hWBTC 的 totalsupply 为 0。(如果先入为主地认为 WBTC的数量也为0,那么当你看到后面的时候会发现凭空多redeem出来了1 wei WBTC)
创建合约 0xd340 并往其中发送 50030063816 wei WBTC
合约 0xd340:
首先存入 4 WBTC,mint 200 hWBTC

redeem 19999999998 wei hWBTC,收到 4 WBTC。此时合约持有 2 wei hWBTC

向池子转入 50030063816 wei WBTC,然后借出 1021.915074492787011273 ETH

调用 redeemUnderlying 函数取出 50030063815 wei WBTC,消耗 1 wei hWBTC。此时合约持有 1 wei hWBTC,池子持有 1 wei WBTC

攻击合约调用 liquidateBorrow 函数对创建的 0xd340 合约的债务进行清算。支付 0.000000267919888739 ETH,获得 1 wei hWBTC。

redeem 1 wei hWBTC,获得 2 wei WBTC,此时池子重新回到 empty 状态。这样做的目的是为了可以再次掏空其他池子。

把 50030063817 wei WBTC 转移走

随后攻击者又再进行了6次相同的操作来掏空其他的池子完成获利,文章篇幅有限就不再展开说明。
漏洞代码分析
合约 0xd340 在进行 redeem 操作时利用了精度丢失的漏洞,获取超额的 WBTC 。漏洞的发生在于 redeemFresh 函数中。

进入到 trace 分析,发现在 truncate 函数中进行了精度丢失。

跟进代码查看 truncate 函数的具体实现方法,在对输入参数 exp 除 1e18 的时候发生了精度丢失。

攻击细节分析
在分析攻击的过程中,对一些细节的部分存在着困惑,尝试着用生疏的技巧浅浅的分析一下。
为什么要先 mint 再 redeem,剩余 2 wei hWBTC
因为 mint 函数只能根据抵押物的数量来 mint hToken。也就是说在 initialExchange = 0.02 WBTC/hWBTC 的情况下,即使是传入 1 wei 的 WBTC,也会 mint 出 50 wei hWBTC。想要得到 2 wei hWBTC的剩余,没办法通过直接 mint 2 hWBTC 的方式(因为你无法提供 0.04 wei WBTC),所以只能先 mint 出大量的 hWBTC,然后再 redeem 使其剩余 2 wei。
所以按道理来说是不是先 mint 出 50 wei hWBTC,再 redeem 48 wei hWBTC 也可以?

为什么要剩余 2 wei hWBTC,而不是其他数量
剩余一定数量的 hWBTC 是为了后续构造精度丢失的攻击,使得合约从 hWBTC 的数量来计算抵押率是满足的,从而批准这笔 redeem,而实际上借出的 WBTC 数量是不满足抵押率要求的。而攻击者构造 2 wei 的这个数量就是为了通过精度丢失,是的超额借出的 WBTC 数量最大化。
假设在 2 wei 的情况下,borrow 了一半价值(1 wei)的资产:
赎回价值 1.99… wei hWbtc 的 WBTC,实际销毁 1 wei hWbtc。此时超额部分为 0.99… wei hWBTC,获得的 WBTC 占总资金的 1.99 / 2 。
在 20 wei 的情况下,borrow 了一半价值(10 wei)的资产:
赎回价值 10.99… wei hWbtc 的 WBTC,实际销毁 10 wei hWbtc。此时超额部分为 0.99… wei hWBTC,获得的 WBTC 占总资金的 10.99 / 20 。
通过上面两个例子我们可以得出,剩余的 hWBTC 数量越少,攻击者通过精度丢失所获得的超额 WBTC 比例就越大。
剩余的 hWBTC 数量可不可以为 1 wei 呢?
假设剩余 1 wei hWBTC,攻击者可以借出 100% 价值的资产,此时赎回价值 0.99… wei hWBTC 的 WBTC,利用精度丢失实际 burn 0 hWBTC。这样构造最大的好处是借出的资产可以达到 100%,而 2 wei 的方案借出资产只能借出 50%。
攻击者是如何构造获利场景的
攻击者只消耗 1 wei hWBTC ,然后 redeemUnderlying 出了 50030063815 wei WBTC

攻击者先 deposit 50030063816 wei WBTC,然后 redeem 50030063815 wei WBTC,希望通过 redeem (deposit amount - 1) 的方式构造精度丢失的场景:redeem 出价值 1.999… wei hWBTC 的 WBTC,最终会 burn 1 wei hWBTC,超额收益 0.999... hWBTC。

但是由于在攻击执行前池子里剩余有 1 wei WBTC,所以攻击者直接 redeem 50030063816 wei WBTC 也是可以达到 burn 1 wei hWBTC 的目的的。也就是说只有当 redeem 50030063817 wei WBTC 的时候才会 burn 2 wei hWBTC。

这个精度缺失攻击的前提是池子中 WBTC 的数量大于 hWBTC 的数量
假设 3 WBTC,2 hWBTC,可得 exchangeRateStoredInternal = 3 / 2 = 1.5
赎回 2 WBTC,计算需要 burn 的 hWBTC 数量:2 / 1.5 = 1.333… → 1 hWBTC
可以通过一个公式来计算出攻击者持有部分 hWBTC 的情况下通过精度丢失得到最大获利的情况吗?
- 假设池子持有 x WBTC,总共发行了 y hWBTC。攻击者持有 z hWBTC (z < y),赎回 kx WBTC (0 < k < 1)
- exchangeRateStoredInternal = x / y
- 由 1 和 2 可得,要 burn 的 hWBTC 数量 = kx / (x / y) = ky
- 攻击者为了获取尽可能大的超额收益,需要通过精度丢失漏洞构造 burn z + 0.999… hWBTC → burn z hWBTC
- 由 3 和 4 可得,ky = z + 0.999 → k = (z + 0.999) / y
举例说明:
- 假设池子持有 20000 WBTC,总共发行了 100 hWBTC,exchangeRateStoredInternal = 200。攻击者持有 50 hWBTC
- k = (z + 0.999) / y = (50 + 0.999) / 100 = 0.5099
- 赎回 kx = 0.5099 * 20000 = 10198 WBTC
- burn 的 hWBTC 数量为 kx / (x / y) = 10198 / 200 = 50.99 → 50
如何计算出清算所需要的 token 数量
通过 liquidateCalculateSeizeTokens 函数,计算得出提供 267919888739 wei ETH,能够清算获得 1 wei hWBTC

然后攻击者执行 liquidateBorrow 函数,提供 267919888739 wei ETH 进行清算,获得 1 wei hWBTC 。具体的计算过程以及涉及的参数如下图所示:

后记
都周末了还搁这写分析文章博主是没有自己的生活的吗?
Hundred Finance 攻击事件分析的更多相关文章
- 007_ip统计及攻击ip分析
线上经常有被扫描的DDoS攻击事件,需要集合日志进行分析,这里有两种方法,分别是通过shell和python的方式. 一.shell '''<1>shell一句命令分析 http://bl ...
- 【APT】Hades APT组织针对乌克兰发起网络攻击事件分析
背景 Hades一个充满神秘色彩的APT组织,该组织因为2017年12月22日针对韩国平昌冬奥会的攻击活动被首次发现,后来卡巴斯基将该次事件的攻击组织命名为Hades.但是该攻击组织的归属问题却一直未 ...
- OneAlert 入门(三)——事件分析
OneAlert 是国内首个 SaaS 模式的云告警平台,集成国内外主流监控/支撑系统,实现一个平台上集中处理所有 IT 事件,提升 IT 可靠性.有了 OneAlert,你可以更快更合理地为事件划分 ...
- OneAlert 入门(二)——事件分析
OneAlert 是国内首个 SaaS 模式的云告警平台,集成国内外主流监控/支撑系统,实现一个平台上集中处理所有 IT 事件,提升 IT 可靠性.有了 OneAlert,你可以更快更合理地为事件划分 ...
- 跨浏览器resize事件分析
resize事件 原生事件分析 window一次resize事件: IE7 触发3次, IE8 触发2次, IE9 触发1次, IE10 触发1次 Chrome 触发1次 FF 触发2次 Opera ...
- GridView事件分析
GridView事件分析 (转) P1默认数据绑定过程 编号 事件名称 作用 E1 DataBinding 数据绑定之前触发,在这个事件之前(第一次生成GridView),GridView不存在行数据 ...
- 新浪微博XSS攻击事件
http://blog.csdn.net/terryzero/article/details/6575078 6月28日20时14分左右开始,新浪微博出现了一次比较大的XSS攻击事件.大量用户自动发送 ...
- 孟加拉央行SWIFT攻击事件恶意木马分析(转)
第一章 分析概述 该恶意木马样本为运行于winodws平台上的PE文件(名称:evtdiag.exe).文件大小为64KB,编译时间是2016年2月5日. 经分析,该样本为定制的攻击SWIFT客户端程 ...
- 讲述ssh服务攻击案例及事件分析
修改中 本文出自 "李晨光原创技术博客" 博客,谢绝转载!
- android 触摸事件分析
背景知识: 触摸屏可以有多个触控点 android中管理触控点通过一个数组来管理,涉及到index和id两个变量, index表示在数组中的下标,id表示这个触控点(pointer)的id,point ...
随机推荐
- modulemap的使用方法
modulemap的作用 modulemap 文件是用来解决 C,Object-C,C++ 代码在 Swift 项目中集成的问题的. 在 Swift 项目中,如果需要使用 C,Object-C 或 ...
- 工作笔记--简单网线连接,使另一台设备通过笔记本电脑的wifi上网
条件 笔记本电脑能够通过 wifi 上网 另一台与笔记本电脑网线连接正常 配置固定 ip,使之可以互相 ping 通 操作 点击右下角 wifi 图标,点击[网络和 Internet 设置] 在高级网 ...
- Go的函数定义
格式: 1 func function_name( [parameter list] ) [return_types] { 2 函数体 3 } 注释: func:函数由 func 开始声明 funct ...
- TCP如何实现可靠传输、流量控制、拥塞控制
上一篇文章中讲述了TCP首部的存储的数据,这一篇来聊聊这些数据帮助TCP实现一些特性. 可靠传输 TCP传输会保障数据的可靠和完整,如果数据传输过程丢失了,会重新传输. 保障的第一种协议方式是 停止等 ...
- 聊聊 RocketMQ 名字服务
NameServer 是专为 RocketMQ 设计的轻量级名字服务,它的源码非常精简,八个类 ,少于1000行代码. 这篇文章, 笔者会从基础概念.Broker发送心跳包.NameServer 维护 ...
- [etcd]基本数据库操作
前言 etcd数据库操作基本围绕着对键值和目录的CRUD操作,以及生命周期的管理. 之前在单节点部署了三实例集群,而etcdctl默认找的是127.0.0.1:2379,所以这里先声明一个临时全局变量 ...
- 配置MySQL主从复制(一主一从)
前言 MySQL主从复制简介 MySQL主从复制的目的是实现数据库冗余备份,将master数据库的数据定时同步到slave库中,一旦master数据库宕机,可以将Web应用数据库配置快速切换到slav ...
- 《小白WEB安全入门》01. 扫盲篇
@ 目录 基础知识 什么是WEB 什么是前端 什么是后端 什么是数据库 什么是协议 什么是WEB安全 什么是服务器 什么是IP地址.端口 什么是局域网.广域网.内网.外网 什么是URL 什么是MAC地 ...
- 学习JavaScript的路径
学习JavaScript的路径可以按照以下步骤进行: 了解基本概念:首先学习JavaScript的基本概念,包括变量.数据类型.运算符.数组.对象.循环和条件语句等.可以通过阅读相关的教材.在线课程或 ...
- SQL多表查询指南
SQL多表查询指南 在实际的数据库应用中,通常需要查询涉及多个表的数据.SQL提供了多种方法来执行这种多表查询操作. 内连接(INNER JOIN) 内连接是将多个表中满足连接条件的行组合在一起的操作 ...