- UID
- 169246
- 阅读权限
- 90
- 注册时间
- 2021-11-25
- 最后登录
- 1970-1-1
- 在线时间
- 小时
- 人气
- 点
- MC币
- 个
- 贡献
- 点
|
撰文: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 |
|