12.SWC-112_delegatecall
2023-07-13 16:11:20 # 09.SWC

SWC-112_delegatecall

Delegatecall to Untrusted Callee

  • Description: There exists a special variant of a message call, named delegatecall which is identical to a message call apart from the fact that the code at the target address is executed in the context of the calling contract and msg.sender and msg.value do not change their values. This allows a smart contract to dynamically load code from a different address at runtime. Storage, current address and balance still refer to the calling contract.

    Calling into untrusted contracts is very dangerous, as the code at the target address can change any storage values of the caller and has full control over the caller’s balance.

  • Remediation: Use delegatecall with caution and make sure to never call into untrusted contracts. If the target address is derived from user input ensure to check it against a whitelist of trusted contracts.

vulnerability contract 1:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
pragma solidity ^0.4.24;

contract Proxy {

address owner;

constructor() public {
owner = msg.sender;
}

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

}

vulnerability contract 2:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
pragma solidity ^0.4.24;

contract proxy{
address owner;

function proxyCall(address _to, bytes _data) external {
require( !_to.delegatecall(_data));
}
function withdraw() external{
require(msg.sender == owner);
msg.sender.transfer(address(this).balance);
}
}

/*
You can't use proxyCall to change the owner address as either:

1) the delegatecall reverts and thus does not change owner
2) the delegatecall does not revert and therefore will cause the proxyCall to revert and preventing owner from changing

This false positive may seem like a really edge case, however since you can revert data back to proxy this patern is useful for proxy architectures
*/
Prev
2023-07-13 16:11:20 # 09.SWC
Next