Skip to content

Do not accept truncated function selectors.#3065

Merged
pirapira merged 3 commits intodevelopfrom
reject_truncated_selectors
Oct 18, 2017
Merged

Do not accept truncated function selectors.#3065
pirapira merged 3 commits intodevelopfrom
reject_truncated_selectors

Conversation

@chriseth
Copy link
Contributor

This prevents problems where function selectors end in zeros and similar things.

Especially, if you have a contract that only has a single function and this function's selector is 0x00000000, the fallback function was not triggered on empty data.

Copy link
Contributor

@pirapira pirapira left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

@axic
Copy link
Contributor

axic commented Oct 11, 2017

Is the interfaceFunction selector parser padding it with zero?

@chriseth
Copy link
Contributor Author

No, the EVM is. The code is div(calldataload(0), 0x1000..0000)

@axic
Copy link
Contributor

axic commented Oct 11, 2017

Right. I am inclined to say this may be worth considering as an entry on the bug list.

@chriseth
Copy link
Contributor Author

We have scales on which we evaluate bugs for the bug list:

  1. discoverability in tests, 2) ocurrence probability, 3) exploitability

This bug scores extremely positive on all three scales:

  1. if you have a fallback function and you test it, you will notice that it does not work.

  2. you have to have a contract with less than 5 external functions and one of them has to have a specific out of 2**32 names. If your fallback function is made to register ether transfers, then that function has to be non-payable.

  3. I don't think this is exploitable, it can only be used to deceive users: You can fool them into calling a certain function on the contract although they "just" wanted to send ether to the contract.

@holiman
Copy link
Contributor

holiman commented Oct 13, 2017

I experimented with this for the uctf:

pragma solidity^0.4.11;

contract Foo{
    uint public result =0; 
    function Foo(){
        
        
    }
    function overdiffusingness(bytes a,uint256 b,uint256 c,uint256 d,uint256 e)  payable returns (uint)
    {
        result = 42;
        return 42;
    }
    
    function () {
        
        result = 13;
    }
    
}

I could find no fault in the solidity implementation.

@chriseth
Copy link
Contributor Author

It turns out, there are even less cases where this can happen: If your contract has a fallback function, you are safe.

This means this can be used to call functions with signature zero if someone just wants to send ether to the contract, and this function also has to be payable.

@chriseth chriseth force-pushed the reject_truncated_selectors branch from 0e0ce43 to f2670a7 Compare October 13, 2017 16:31
@holiman
Copy link
Contributor

holiman commented Oct 13, 2017

I really like the method signature that I brute-forced. Too bad it was useless for the uctf competition though 😢

@pirapira
Copy link
Contributor

I also tried two function signatures with the same hash, but Solidity refused that.

@holiman
Copy link
Contributor

holiman commented Oct 13, 2017

Yeah, that's also something I fiddled with for uctf.

@chriseth chriseth requested a review from axic October 16, 2017 10:38
"summary": "It is possible to craft the name of a function such that it is executed instead of the fallback function in very specific circumstances.",
"description": "If a function has a selector consisting only of zeros, is payable and part of a contract that does not have a fallback function and at most five external functions in total, this function is called instead of the fallback function if Ether is sent to the contract without data.",
"fixed": "0.4.18",
"severity": "very low"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be a key "verylow" or a user readable string?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would say both. Why can't keys have spaces?

@chriseth
Copy link
Contributor Author

Weird, I don't get the test errors locally.

@chriseth chriseth force-pushed the reject_truncated_selectors branch from ca85fa6 to 7849b92 Compare October 17, 2017 22:20
@pirapira pirapira merged commit 4a9a986 into develop Oct 18, 2017
@pirapira pirapira deleted the reject_truncated_selectors branch October 18, 2017 09:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants

Comments