智能合约安全:短地址攻击

昨天一位博友提到短地址攻击的问题,感觉挺有意思的,就花了点时间研究了一下。

1.什么是短地址攻击

大家都知道,如果我们想调用智能合约的函数,需要在交易的payload字段中填充一段字节码。以ERC20的transfer()的函数为例,函数原型为:

function transfer(address to, uint amount) public returns (bool success);

我们需要通过一段68个字节的字节码来调用该函数进行转账,比如:

a9059cbb000000000000000000000000146aed09cd9dea7a64de689c5d3ef73d2ee5ca000000000000000000000000000000000000000000000000000000000000000001

具体可以分解为3个部分:

  • 4字节函数签名:a9059cbb
  • to参数:000000000000000000000000146aed09cd9dea7a64de689c5d3ef73d2ee5ca00
  • amount参数:0000000000000000000000000000000000000000000000000000000000000001

大家可能注意到,这个转账地址有点特殊:最后两个数字为0。

假如有个用户“不小心”忘记输入最后这两个0了怎么办?这样我们的输入就只有67个字节了。EVM是通过CALLDATALOAD指令从输入数据中获取函数参数的,因此它会先从后面的amount参数里“借”两个0来补足前面的地址参数。当它要加载amount参数的时候,发现位数不够,会在右边补0,参见以太坊源码:
在这里插入图片描述
所以,经过这么一折腾,实际上EVM看到是下面这些参数:

  • 4字节函数签名:a9059cbb
  • to参数:000000000000000000000000146aed09cd9dea7a64de689c5d3ef73d2ee5ca00(借0)
  • amount参数:0000000000000000000000000000000000000000000000000000000000000100(补0)

看到问题了没?转账地址没变,但是转账金额增大了256倍!如果你的转账地址后面有足够多的0,那么转账金额将会大得惊人~

但是有人会说,这没啥毛用啊,难道智能合约的作者会傻到不检查你地址的余额,就直接让你提币走人吗?我猜想这跟目前中心化交易所的运营机制相关。考虑下面的场景:用户充币到交易所钱包,交易所又把这些币转移到了它们内部的合约账户中。等用户发起提币申请,并通过人工审核后,再从合约中把币打到用户的账户中。

在这种情况下,交易的msg.sender就是交易所本身,因此可以通过余额检查。当然,这里有个前提:你必须能够通过人工审核!也就是审核员失职。实际上,从没有人成功利用过这个漏洞,最先发现这个问题的GNT项目组,也仅仅是观察到一笔异常交易而已,并没有产生任何实质性损失。网络上流传的攻击方法是:先找到一个里面有足够数量代币的交易所账户,充1000个币进去,然后再申请提1000个币,就可以提出来256000个币。但是,在我看来这似乎并不可行,如果有读友能想出可行

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值