您尚未登录,请登录后浏览更多内容! 登录 | 加入最MC

QQ登录

只需一步,快速开始

 找回密码
 加入最MC

QQ登录

只需一步,快速开始

查看: 109|回复: 0
打印 上一主题 下一主题

[【少女の茶会】] 关于慢雾深度解析 Bitfinex 天价手续费转账:BUG+显示错误「酿成大错」

[复制链接]
跳转到指定楼层
楼主
发表于 2022-1-5 10:00:37 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

撰文:T @ 慢雾安全团队imtoken官网的相关知识也可以到网站具体了解一下,有专业的客服人员为您全面解读,相信会有一个好的合作!https://www.imtoken.vote




事件背景

分析源自一笔转账金额 10 USDT,手续费却高达 7,676 枚 ETH 的天价手续费交易。02991798761912492195597878277759587115



核心点

技术层面的核心问题是: - 的 TB 不支持传入浮点型的数据, 用了 - 的 TB 。

简而言之:DA 在使用  构造交易的时候,传入的手续费如果带有小数的,会因为类型转换出现  导致在浏览器返回了一个很大的数作为手续费。且硬件钱包没有显示清楚,导致用户直接授权签了这边天价手续费的交易。



关键代码分析

根据此 I

-1497 中的描述,开始了分析。

我们以倒叙的方式来说明问题,这样更方便理解。核心问题是 - 的 TB 不支持传入浮点型的数据。

首先看看关键的代码,提得比较多的是  的问题,主要聚焦讨论的是 PFPG 和 FPG 这两个参数的值,由于传入的浮点型,导致计算错误,得到了错的手续,从而发生了 「天价手续的事件」。

经过分析后,这两个参数都是经过 B 进行处理的,所以开始分析 B。

-950461559T#L200-L201

FPG =  BN(B(FPG ===  ? 0 : FPG))    PFPG =  BN(      B(PFPG ===  ? 0 : PFPG)    )

B 会去调用 - 的 TB 函数,这个函数主要处理了两件事情。

-96681-#L1950

TB() {    = TH();    B(TE((2)), );}

将  转成 H-96681-#L199

TH() {    = S(16);  --   0 + ;}

判断是否可以被 2 整除,如果不行需要在字符开头添加一个 0 ,这里主要是为了能够成功的将数据 2 个 1 组写入到 。-96681-#L1920

TE() {    = ;  --        (  !== ) {      E([-]    ,    ,    +   + ,  TE);  }   ( % 2) {     = 0 + ;  }   ;}

以出错的示例数据:97422995055000 进行分析,经过 TB 函数中的 TH 和 TE 处理后得到 790598,这部分浏览器  和  的结果都是一致的。

不一致的地方是在  B 的操作:

B(TE((2)), );



处理方式分析:浏览器

通过  打包好  文件并对文件进行引用,然后在浏览器上进行调试分析。

首先输入的示例字符 97422995055000 会进入到 TB 的函数中进行处理。

同步分析 TB 的处理过程,这部分和」关键代码分析「部分的代码逻辑是一样的,处理转换部分得到的结果是 790598。

接下来分析如何将转换后的字符填充进入的  中,通过这步可以得到  的内容是 126, 144, 89, 187, 14, 140, 205 对应的是 7, 90, 59, , , 8, 。

07 - 126 090 - 144 059 - 89 0 - 187 0 - 14 08 - 140 0 - 205

这里发现  这部分的小数点消失了,于是开始解小数点消失之迷,追踪到 W 这个函数,这个函数会将得到的数据 2 个一组进行切分。然后用了 I 对切分后的数据进行解析。

然而 I(,16) - 14===I(,16) - 14 消失的小数点被 I 吃掉了,导致最终写入到  中的数据发生了错误,写入  的值是 790598。



处理方式分析:

由于浏览器上出问题的是 7_**__**_90598 在写入  的时候小数点被 I 吃掉了导致数据出错,但是经过分析, 的数据也是错误的,且产生错误的原因是和浏览器的不一样。

首先我们先看下如下的示例:

组不同的数据填充到  得到的结果居然是一样的,经过分析  的  有个小特性,就是 2 个一组切分后的数据,如果没法正常通过  解析的,就会把那一组数据以及之后的数据都不处理了,直接返回前面可以被正常处理的那部分数据。可以理解为被截断了。这部分可以参考  底层的  中 _ 中的代码逻辑。

  B(79059, )       B(790598, )       B(79059, )



执行结果的比较

由于会将原始数据 790598 中的  及之后的数据进行截断,所以最终错误的值是 79059,相比正确的值 079059 小。

的执行结果:

浏览器由于会将原始数据 790598 中的  吃掉,所以最终错误的值是 790598,相比正确的值 079059 大很多。

浏览器的执行结果:



问题的原因

- 的 TB 函数不支持浮点型的数据,且在这个函数中没有判断传入的变量类型,来确保变量类型是预期内的。由于  的 B 引用了 - 的 TB 进行处理,也没有对数据进行检查。导致了这次事件的发生,所幸最终善良的矿工归还了「天价手续费 7626 ETH」。



吸取的教训

从第方的库的角度来看,在编码过程中应该要遵循可靠的安全的编码规范,在函数的开头要对传入的数据进行合法性的检查,确保数据和代码逻辑是按照预期内执行。

从库的使用者的角度来看,使用者应该要自行阅读第方库的开发文档和对接文档,并且也要对代码中接入第方库的逻辑进行测试,通过构造大量的数据进行测试,确保业务上能够正常按照期望执行,保证高标准的测试用例的覆盖率。

参考资料 :-14972-7-------6117062761
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友