EVM并没有严格校验 可以发起以太坊短地址攻击
ddgghhjjkk
发表于 2022-12-15 09:11:23
100
0
0
2 n. `& d3 l9 \; o' r; ?* H, n: N
第一参数是发送代币的目的地址,第二个参数是发送token的数量。) A: l) N8 X6 s; J; g) C. ]
8 ]7 x% \! Q+ T$ O
当我们调用transfer函数向某个地址发送N个ERC-20代币的时候,交易的input数据分为3个部分:
4 字节,是方法名的哈希:a9059cbb+ H- [4 `+ X* U* i3 p: B+ o) ]. j
/ p; p: E5 j A9 P) y7 x/ c
32字节,放以太坊地址,目前以太坊地址是20个字节,高危补0+ Q2 D. E2 Z( Q) B s) b3 C0 \4 G
000000000000000000000000abcabcabcabcabcabcabcabcabcabcabcabcabca) b$ v5 E5 | B, p. j! k/ r
- j2 }+ t+ C L: f, F3 \; h3 c E
32字节,是需要传输的代币数量,这里是1*10^18 GNT
0000000000000000000000000000000000000000000000000de0b6b3a7640000
" c8 v1 ^" w& F+ i/ e4 q3 X, v
所有这些加在一起就是交易数据:6 y6 }: F0 I1 a! h0 n# d" p
a9059cbb000000000000000000000000abcabcabcabcabcabcabcabcabcabcabcabcabca0000000000000000000000000000000000000000000000000de0b6b3a7640000
, H* F9 h7 |6 U+ `9 j. j
0x01 以太坊短地址5 F# N* O. c4 n a$ o
当调用transfer方法提币时,如果允许用户输入了一个短地址,这里通常是交易所这里没有做处理,比如没有校验用户输入的地址长度是否合法。
! B9 N8 q/ B1 x1 y8 l
如果一个以太坊地址如下,注意到结尾为0:
# g, `, ~: o& e9 `4 l
0x1234567890123456789012345678901234567800
3 s7 h$ n' L7 x5 \
当我们将后面的00省略时,EVM会从下一个参数的高位拿到00来补充,这就会导致一些问题了。, ^0 R! I0 s9 |$ s7 [
这时,token数量参数其实就会少了1个字节,即token数量左移了一个字节,使得合约多发送很多代币出来。我们看个例子:
这里调用sendCoin方法时,传入的参数如下:
0x90b98a11 00000000000000000000000062bec9abe373123b9b635b75608f94eb8644163e 0000000000000000000000000000000000000000000000000000000000000002
; R. U' l6 o1 j h
这里的0x90b98a11是method的hash值,第二个是地址,第三个是amount参数。
如果我们调用sendCoin方法的时候,传入地址0x62bec9abe373123b9b635b75608f94eb8644163e,把这个地址的“3e”丢掉,即扔掉末尾的一个字节,参数就变成了:- }5 ?$ e q. X8 \8 O8 P8 r( N: x
/ H: c$ q1 `' y3 Y# c+ Y" t
0x90b98a11 00000000000000000000000062bec9abe373123b9b635b75608f94eb86441600 00000000000000000000000000000000000000000000000000000000000002 ^^ 缺失1个字节
1 @) {. t0 i; z1 \' Y
这里EVM把amount的高位的一个字节的0填充到了address部分,这样使得amount向左移位了1个字节,即向左移位8。
, g8 K ^# ~! q9 |1 [1 Y! @
这样,amount就成了2) R( @3 i! n% p! M* v
* o$ u+ ^% f, f! d/ }
0x02 构造短地址攻击
5 i' N6 Q% `, ~: I2 d
(1)首先生成一个ETH的靓号,这个账号末尾为2个0
; y p# s* l' H, J! g6 |/ @
使用一些跑号工具就可以做到,比如MyLinkToken工具,可以很轻易跑出末尾两个0的。* {5 c$ X$ S# a' i" F" |& p8 g9 C u
- e, P1 I: o& G3 U: m2 f h7 K
(2)找一个交易所钱包,该钱包里token数量为256000
(3)往这个钱包发送1000个币
' E* a) P3 S. I9 L
(4)然后再从这个钱包中提出1000个币,当然这时候写地址的时候把最后两个0去掉
) M/ s' ?' o7 O, @5 n
如果交易所并没有校验用户填入的以太坊地址,则EVM会把所有函数的参数一起打包,会把amount参数的高位1个字节吃掉。
(5)这三个参数会被传入到msg.data中,然后调用合约的transfer方法,此时,amount由于高位的1个字节被吃掉了,因此amount = amount
+ E; x# @7 l7 ]1 A: L
0x03 总结. j2 j# b9 S: [2 b/ U
针对这个漏洞,说实话以太坊有不可推卸的责任,因为EVM并没有严格校验地址的位数,并且还擅自自动补充消失的位数。此外,交易所在提币的时候,需要严格校验用户输入的地址,这样可以尽早在前端就禁止掉恶意的短地址。
成为第一个吐槽的人