code-423n4 / 2021-11-streaming-findings

0 stars 0 forks source link

ArbitraryCall() allows attackers to steal ERC20 tokens from users wallets #242

Closed code423n4 closed 2 years ago

code423n4 commented 2 years ago

Handle

Jujic

Vulnerability details

A call to an arbitrary contract with custom calldata is made in arbitraryCall(address who, bytes memory data), which means the contract can be an ERC20 token, and the calldata can be transferFrom a previously approved user.

Impact

The wallet balances (for the amount up to the allowance limit) of the tokens that users approved to the Stream contract can be stolen.

Proof of Concept

https://github.com/code-423n4/2021-11-streaming/blob/56d81204a00fc949d29ddd277169690318b36821/Streaming/src/Locke.sol#L743

The attacker create Stream contract on the Factory and malicious ERC20 contract

Bob has approved 1000 tokens on Stream contract

Attacker call function:

arbitraryCall(address who, bytes memory data) public lock externallyGoverned {

where:

who = address arbitrary malicious ERC20 contract 

data = abi.encodeWithSignature( "transferFrom(address,address,uint256)",
        address(Bob),
       any  address hacker,
        1000 tokens  )
... 

(bool success, bytes memory _ret) = who.call(data);
        require(success);

As a result, 1000 token will be stolen from Bob and sent to the attacker.

Tools Used

Remix

Recommended Mitigation Steps

You can remove this dangerous function from the protocol.

0xean commented 2 years ago

dupe #258