【漏洞分析】KaoyaSwap 安全事件分析
相关信息
KaoyaSwap 是 BSC 链上的一个自动做市商 AMM。然后,现在他们的官网 https://www.kaoyaswap.com/ 已经打不开了(如果我打开方式没错的话)。所以就直接进行攻击事件的分析吧。
攻击交易:https://bscscan.com/tx/0xc8db3b620656408a5004844703aa92d895eb3527da057153f0b09f0b58208d74
攻击者在进行攻击之前,自己构建了两个代币协助完成攻击,下面将他们分别称为 TA 和 TB 。
TA address:0x74eF69Defe8bae1Fe660fB93265FC1bc79c9bDa8
TB address:0xD84379C4eeA25d05574f9F0B99E3Bf73500Ca4B4
交易流程
因为攻击是发生在 AMM 上的,所以我们可以根据代币的流向先大概分析一下攻击者在这笔交易中都做了些什么,看看能不能看出有什么奇怪的地方。下面绿色框图是 Tokens Transferred 的内容,红色框图的是 Internal Txns 的内容。

- 首先闪电贷 1800 BNB
- 调用 swapExactTokensForTokens 函数,用 672 BNB 换出 125023 KY
- 调用 swapExactTokensForTokens 函数,用 100 BNB 换出 6666 BUSD
- 调用 addLiquidity 函数,添加 1026 BNB 和 50 TA,获得 226 KALP 流动性代币

- 调用 addLiquidity 函数,添加 1 BNB 和 1 TB,获得 0.9 KALP 流动性代币
- 调用 addLiquidity 函数,添加 1 TA 和 1 TB,获得 0.9 KALP 流动性代币


- 调用 swapExactTokensForETHSupportingFeeOnTransferTokens 函数,其中 path 参数为
[TA, WBNB, TB, TA, WBNB]的地址。这个函数还涉及到 BNB 的转账,但是函数 Output 中没有体现。(剧透一下,转出了 1019 BNB 给攻击地址。具体情况后面的代码分析会解释)。
Input:
"amountIn": "8000000000000000000000",
"amountOutMin": "1",
"path": [
"0x74ef69defe8bae1fe660fb93265fc1bc79c9bda8",
"0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c",
"0xd84379c4eea25d05574f9f0b99e3bf73500ca4b4",
"0x74ef69defe8bae1fe660fb93265fc1bc79c9bda8",
"0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c"
],
"to": "0xa722ca7bf032de8f7a675da75dfec661bc89ace9",
"deadline": "1661293930“
Output:
0x


- 调用 removeLiquidityETHSupportingFeeOnTransferTokens 函数,销毁 226 KALP,获得 8050 TA,Output "amountETH": "6392515470500594443"
- 调用 removeLiquidityETHSupportingFeeOnTransferTokens 函数,销毁 0.9 KALP,获得 0.0009 TB,Output "amountETH": "1020797089459256392608"

- 调用 removeLiquidity 函数,传入 0.9 KALP,获取 0.5 TA 和 1.9 TB
- 调用 swapExactTokensForTokens 函数,传入 83918 KY,获得 25170 BUSD

- 在 pancakeswap 中把 17740 KY 换成 5457 BUSD,把 23364 KY 换成 24 WBNB。
- 归还 1800 WBNB 闪电贷。
- 然后把 37294 BUSD 和 271 WBNB 转移到 0xd87f 地址中
总的来看,攻击者主要投入了 1026 BNB 到 WBNB 和 TA 的池子中,然后通过 swapExactTokensForETHSupportingFeeOnTransferTokens 函数以 8000 TA 获得 1019 BNB,并且通过 removeLiquidityETHSupportingFeeOnTransferTokens 函数移除 WBNB 和 TB 池子的流动性获得 1020 BNB。
投入 1026 BNB,获得 (1019 + 1020) BNB,其中必有蹊跷。
代码分析
首先来分析一下 swapExactTokensForETHSupportingFeeOnTransferTokens 函数,先调用 _transferIn 转入 TA,然后调用 _swapSupportingFeeOnTransferTokens 函数按照 path 进行一系列 swap 操作,计算 _pools[TA,WBNB][WBNB] 的变化,根据差值给 to 地址发送相等数量的 BNB。
需要关注的函数:_transferIn 和 _swapSupportingFeeOnTransferTokens。这些函都涉及到了一个关键的变量 _pools ,它是这次攻击的关键点。

先来看 _transferIn 函数,它的作用是把 path 中的第一个代币转入合约中,并修改对应的 _pools 值。

_swapSupportingFeeOnTransferTokens 函数根据 path 所提供的代币地址进行 swap,并将对应的 _pools 变量进行修改。

其中 _transferOut 函数的作用就是向 to 地址发送 amount 数量的 token。

当 swapExactTokensForETHSupportingFeeOnTransferTokens 函数中 path = [TA, WBNB, TB, TA, WBNB] 时所发生的情况是(下面简称 [A, W, B, A, W]):
首先在 _transferrIn 函数中:
_pool[AW][A] + amountIn
然后在 _swapSupportingFeeOnTransferTokens 函数中(注意 _pool[AW][W] 做了两次减法操作):
i = 0 , _pool[AW][W] – amountOutput1, _pool[WB][W] + amountOutput1
i = 1 , _pool[WB][B] – amountOutput2, _pool[BA][B] + amountOutput2
i = 2 , _pool[BA][A] – amountOutput3, _pool[AW][A] + amountOutput3
i = 3 , _pool[AW][W] – amountOutput4
转账的金额只通过最后一对 pair 的 _pool 数值 _pool[AW][W] 的减少量(从 AW 这个池子里换出了多少 W)来确定。正确的方法应该是只关注最后一步中 _pool[AW][W] 的减少量,而不是整个 swap 过程中 _pool[AW][W] 的总(累计)减少量。如果采用总(累计)减少量计算,则当 path 中有重复的 pair ([A, W])不连续出现时,会多次计算 _pool[AW][W] 的减少量,最终导致 balanceBefore.sub(balanceAfter) 的值大于实际值。
我们看到第 1 次 TA 换 WBNB 的时候,换出来 1019.797089459257413406 WBNB,第 2 次 TA 换 WBNB 的时候,换出来 0.000395070241992122 WBNB,累加得到 1019.797484529499405528 WBNB,吻合之前提到的值。而正常情况下应该转出的 WBNB 因该为 0.000395070241992122 WBNB,同时将 [WBNB, TB] 池子中 TB 的币价大幅提高(转入了大量 WBNB)。


综上所属,利用了 _pools 变量在整个 swap 过程中累计减少量的漏洞,攻击者用一笔钱,在提高了 [WBNB, TB] 池子中 TB 的币价的同时, swap 出了超量的 WBNB。然后再移除 [WBNB, TB] 池子的流动性, 获取大量的 BNB。
【漏洞分析】KaoyaSwap 安全事件分析的更多相关文章
- CVE-2013-2551漏洞成因与利用分析(ISCC2014 PWN6)
CVE-2013-2551漏洞成因与利用分析 1. 简介 VUPEN在Pwn2Own2013上利用此漏洞攻破了Win8+IE10,5月22日VUPEN在其博客上公布了漏洞的细节.它是一个ORG数组整数 ...
- CVE-2014-0322漏洞成因与利用分析
CVE-2014-0322漏洞成因与利用分析 1. 简介 此漏洞是UAF(Use After Free)类漏洞,即引用了已经释放的内存,对指定内存处的值进行了加1.其特点在于攻击者结合flash实现了 ...
- CVE-2013-3897漏洞成因与利用分析
CVE-2013-3897漏洞成因与利用分析 1. 简介 此漏洞是UAF(Use After Free)类漏洞,即引用了已经释放的内存.攻击者可以利用此类漏洞实现远程代码执行.UAF漏洞的根源源于对对 ...
- 漏洞分析:OpenSSH用户枚举漏洞(CVE-2018-15473)分析
漏洞分析:OpenSSH用户枚举漏洞(CVE-2018-15473)分析 漏洞分析:OpenSSH用户枚举漏洞(CVE-2018-15473)分析 - FreeBuf互联网安全新媒体平台 https: ...
- 常用 Java 静态代码分析工具的分析与比较
常用 Java 静态代码分析工具的分析与比较 简介: 本文首先介绍了静态代码分析的基 本概念及主要技术,随后分别介绍了现有 4 种主流 Java 静态代码分析工具 (Checkstyle,FindBu ...
- Memcached源代码分析 - Memcached源代码分析之消息回应(3)
文章列表: <Memcached源代码分析 - Memcached源代码分析之基于Libevent的网络模型(1)> <Memcached源代码分析 - Memcached源代码分析 ...
- mysql 分析3使用分析sql 性能 show profiles ;
show variables like '%profiling%'; 查看状态 查看时间去哪了``` set profiling=1;// 打开 show profiles; 查看执行过的 ...
- [转载] 常用 Java 静态代码分析工具的分析与比较
转载自http://www.oschina.net/question/129540_23043 简介: 本文首先介绍了静态代码分析的基本概念及主要技术,随后分别介绍了现有 4 种主流 Java 静态代 ...
- x264源代码简单分析:宏块分析(Analysis)部分-帧间宏块(Inter)
===================================================== H.264源代码分析文章列表: [编码 - x264] x264源代码简单分析:概述 x26 ...
随机推荐
- Jenkins之配置GitHub-Webhook
前提条件1: 运行Jenkins的机器需要安装git,并且git.exe文件在系统的环境变量里面,或者手动在 Manage Jenkins -> Global Tool Configuratio ...
- spring boot用ide新建项目遇到的restcontroller不能导入的问题
才开始学习spring boot,第一个程序helloworld就碰到@RestController和@RequestMapping(/hello)的注解都会报错的问题. 我个人的解决方法: 1.sp ...
- 对互斥事件和条件概率的相互理解《考研概率论学习之我见》 -by zobol
1.从条件概率来定义互斥和对立事件 2.互斥事件是独立事件吗? 3.每个样本点都可以看作是互斥事件,来重新看待条件概率 一.从条件概率来定义互斥和对立事件 根据古典概率-条件概率的定义,当在" ...
- ShardingSphere-proxy-5.0.0分布式哈希取模分片实现(四)
一.说明 主要是对字符串的字段进行hash取模 二.修改配置文件config-sharding.yaml,并重启服务 # # Licensed to the Apache Software Found ...
- cmd命令与bat编程
命令解压缩文件 winrar 命令行解压文件 winrar x 要解压的文件 要解压到的路径 (保存压缩文件内的目录结果) 直接覆盖 -o+ 覆盖已存在文件 在不提示 ...
- ES5的继承和ES6的继承有什么区别?让Babel来告诉你
如果以前问我ES5的继承和ES6的继承有什么区别,我一定会自信的说没有区别,不过是语法糖而已,充其量也就是写法有区别,但是现在我会假装思考一下,然后说虽然只是语法糖,但也是有点小区别的,那么具体有什么 ...
- 简单性能测试:springboot-2.x vs actix-web-4.x benchmark
性能测试:springboot-2.x vs actix-web-4.x benchmark 转载请注明出处 https://www.cnblogs.com/funnyzpc/p/15956465.h ...
- Spring框架系列(8) - Spring IOC实现原理详解之Bean实例化(生命周期,循环依赖等)
上文,我们看了IOC设计要点和设计结构:以及Spring如何实现将资源配置(以xml配置为例)通过加载,解析,生成BeanDefination并注册到IoC容器中的:容器中存放的是Bean的定义即Be ...
- 配置SSM公钥及创建远程仓库和在IEDA中集成git操作
3.将.ssh下的id_rsa.pub公钥copy到gitee工作台中 4.创建个人仓库 5.设置开源许可证:开源是否可以随意转载,开源但是不能商业使用,不能转载,- 限制! 6.克隆到本地! IDE ...
- Python 内置logging 使用详细讲
logging 的主要作用 提供日志记录的接口和众多处理模块,供用户存储各种格式的日志,帮助调试程序或者记录程序运行过程中的输出信息. logging 日志等级 logging 日志等级分为五个等级, ...