智能合约漏洞——委托调用给不受信任的被调用者(Delegatecall to Untrusted Callee)

委托调用给不受信任的被调用者(Delegatecall to Untrusted Callee)

当用户A通过合约B来call合约C的时候,执行的是合约C的函数,上下文(Context,可以理解为包含变量和状态的环境)也是合约C的:msg.sender是B的地址,并且如果函数改变一些状态变量,产生的效果会作用于合约C的变量上。

  delegatecall是一种特殊的调用,当用户A通过合约B来delegatecall合约C的时候,执行的是合约C的函数,但是上下文仍是合约B的:msg,sender是A的地址,并且如果韩式改变一些状态变量,产生的效果会作用于合约B的变量上。可以这样理解:一个投资者A(用户A)把他的资产(B合约的状态变量)都交给一个风险投资代理(C合约)来打理。执行的是风险投资代理的函数,但改变的是资产的状态。(以上转载自:https://blog.csdn.net/djklsajdklsajdlk/article/details/140522665)

  本质上,delegatecall委托其他合约来修改调用合约的存储。由于delegatecall对合约提供了如此多的控制,因此仅对受信任的合约(如自己的合约)使用此功能。如果目标地址来自用户输入,请确保它是一个受信任的合约。

考虑以下合约,其中delegatecall被误用,导致了一个漏洞:

contract Proxy {
    address public owner;

    constructor() {
        owner = msg.sender;
    }

    function forward(address callee, bytes calldata _data) public {
        require(callee.delegatecall(_data), "Delegatecall failed");
    }
}

contract Target {
    address public owner;

    function pwn() public {
        owner = msg.sender;
    }
}

contract Attack {
    address public proxy;

    constructor(address _proxy) {
        proxy = _proxy;
    }

    function attack(address target) public {
        Proxy(proxy).forward(target, abi.encodeWithSignature("pwn()"));
    }
}

当Attack合约的attack函数被调用时,它会调用Proxy合约的forward函数,传入target合约的地址以及pwn函数的ABI编码。Proxy合约接收到调用后,通过delegatecall调用target合约的pwn函数。由于delegatecall保留了调用者的环境(包括msg.sender),所以pwn函数实际上会将Attack合约的调用者作为新的拥有者。

保护措施:

为了降低delegatcall相关的风险,请考虑以下策略:

  (1)白名单可信合约:确保delegatecall的目标地址是您控制的合约,或者是经过验证和可信列表的一部分。

  (2)限制delegatecall的作用域:只对特定的、受控的操作使用delegatecall。除非绝对必要,否则避免将其公开为通用函数。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值