StephenGrider / EthereumCasts

Companion repo to an Ethereum/Solidity course on Udemy
2.13k stars 1.31k forks source link

Reentry attack vulnerability in Campaign.sol #11

Open sergeny opened 6 years ago

sergeny commented 6 years ago
   function finalizeRequest(uint index) public restricted {
        Request storage request = requests[index];

        require(request.approvalCount > (approversCount / 2));
        require(!request.complete);

        request.recipient.transfer(request.value);
        request.complete = true;
    }

When we are sending money to the recipient, nothing prevents a second recursive call to finalizeRequest. Even though the function is restricted, the recipient could pass control to the manager, who would then execute a recursive call. In this way, the manager, in cooperation with a vendor, could get an approval for a small amount, but withdraw many times that amount.

Technically, it would a solution to check that manager is a human and not a smart contract, but no such check is being done. Furthermore, one could make an innocent-looking smart contract, pretending it's just a convenience tool for the manager, in case someone decides to look, but keep it upgradable to leave a backdoor.

Update: the proposed solution is to interchange the last two lines, setting the flag to true before doing the transfer.

JuiceyDuecy commented 6 years ago

Just wondering what exactly was the fix?

JuiceyDuecy commented 6 years ago

Git diff I guess

sergeny commented 6 years ago

You could swap the last two lines, setting complete to true before doing the transfer.