0
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;

/*
Let's say Alice can see the code of Foo and Bar but not Mal.
It is obvious to Alice that Foo.callBar() executes the code inside Bar.log().
However Eve deploys Foo with the address of Mal, so that calling Foo.callBar()
will actually execute the code at Mal.
*/

/*
1. Eve deploys Mal
2. Eve deploys Foo with the address of Mal
3. Alice calls Foo.callBar() after reading the code and judging that it is
   safe to call.
4. Although Alice expected Bar.log() to be execute, Mal.log() was executed.
*/
contract Foo {
    Bar bar;

    constructor(address _bar) {
        bar = Bar(_bar);
    }

    function callBar() public {
        bar.log();
    }
}

contract Bar {
    event Log(string message);

    function log() public {
        emit Log("Bar was called");
    }
}

// This code is hidden in a separate file
contract Mal {
    event Log(string message);

    // function () external {
    //     emit Log("Mal was called");
    // }

    // Actually we can execute the same exploit even if this function does
    // not exist by using the fallback
    function log() public {
        emit Log("Mal was called");
    }
}

In the given example, three contracts are introduced: Foo, Bar, and Mal. The Foo contract interacts with the Bar contract under the assumption that the function callBar() will execute the code inside Bar’s log() function. However, an attacker (Eve) can deploy the Mal contract and provide its address to Foo, effectively causing callBar() to execute the code within Mal instead of Bar. From the above contracts i didn't understand what will happens under the hood if we deploy some other contract(Foo) at the address of other contract(Mal).Explain what happens under the hood or provide any links to understand better.

2 Answers 2

1

In your contract, the bar = Bar(_bar); doesn't mean creating a new contract, but rather it's taking the contract on a pre-deployed address _bar.

In order to create a new contract, new keyword is utilized. Like bar = new Bar();

Take a look at this amazing explanation: New | Solidity 0.8

0

there is a way to deploy a contract at a specific address, regardless of the creator and the nonce. This is done by using a technique called "create2", which allows a contract to create another contract with a deterministic address. The address of the created contract depends on the address of the creator, a salt (a random value), and the bytecode of the contract. By choosing a specific salt and bytecode, one can deploy a contract at any desired address, as long as that address does not already have a contract or balance. This technique can be used to exploit contracts that interact with other contracts based on their addresses. For example, in the given code, the Foo contract expects to interact with the Bar contract at a certain address. However, an attacker can deploy the Mal contract at that address using create2, and trick Foo into calling Mal instead of Bar. This way, the attacker can execute malicious code or steal funds from Foo. To prevent this kind of attack, contracts should not rely on hardcoded addresses or trust external contracts without verifying their code. One way to do this is to use interfaces or abstract contracts that define the expected behavior and functions of other contracts. Another way is to use tools like Etherscan or Sourcify that allow users to verify the source code and bytecode of deployed contracts.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.