Platform: Code4rena
Start Date: 12/07/2022
Pot Size: $75,000 USDC
Total HM: 16
Participants: 100
Period: 7 days
Judge: LSDan
Total Solo HM: 7
Id: 145
League: ETH
Rank: 74/100
Findings: 1
Award: $78.88
π Selected for report: 0
π Solo Findings: 0
π Selected for report: IllIllI
Also found by: 0x1f8b, 0x29A, 0xDjango, 0xNazgul, 0xNineDec, 0xf15ers, 8olidity, Aussie_Battlers, Bnke0x0, Ch_301, Critical, Deivitto, Dravee, ElKu, Funen, GimelSec, JC, JohnSmith, Lambda, MiloTruck, PwnedNoMore, ReyAdmirado, Rohan16, Rolezn, Ruhum, RustyRabbit, Sm4rty, TomJ, Waze, _Adam, __141345__, alan724, asutorufos, benbaessler, berndartmueller, bin2chen, brgltd, bulej93, c3phas, cRat1st0s, cryptonue, cryptphi, csanuragjain, delfin454000, dxdv, exd0tpy, fatherOfBlocks, gogo, hake, hyh, joestakey, kyteg, lcfr_eth, minhtrng, p_crypt0, pashov, pedr02b2, philogy, rajatbeladiya, rbserver, rishabh, robee, rokinot, sach1r0, sashik_eth, seyni, simon135, svskaushik, zuhaibmohd, zzzitron
78.881 USDC - $78.88
function register( string calldata name, address owner, uint256 duration, bytes32 secret, address resolver, bytes[] calldata data, bool reverseRecord, uint32 fuses, uint64 wrapperExpiry ) public payable override { IPriceOracle.Price memory price = rentPrice(name, duration); require( msg.value >= (price.base + price.premium), "ETHRegistrarController: Not enough ether provided" ); _consumeCommitment( name, duration, makeCommitment( name, owner, duration, secret, resolver, data, reverseRecord, fuses, wrapperExpiry ) );
function makeCommitment( string memory name, address owner, uint256 duration, bytes32 secret, address resolver, bytes[] calldata data, bool reverseRecord, uint32 fuses, uint64 wrapperExpiry ) public pure override returns (bytes32) { bytes32 label = keccak256(bytes(name)); if (data.length > 0) { require( resolver != address(0), "ETHRegistrarController: resolver is required when data is supplied" ); } return keccak256( abi.encode( label, owner, duration, resolver, data, secret, reverseRecord, fuses, wrapperExpiry ) ); }
The Commitment
is an important mechanism to safeguard users from front run register, the commitment design should make it impossible to front run a register()
transaction.
However, we noticed that the makeCommitment
is a public function to generate the commitment
later to be used for the onchain commit()
call.
Even though it's not necessarily so (the frontend may implement their own local/offline makeCommitment
function), the existence of this public makeCommitment()
method on the ETHRegistrarController
contract creates a Schelling point, which makes it more likely for the frontend choose just to use it.
In which case, the RPC will be able to know the exact domain the user is planning to register, they can later further confirm it (when the user sends the commit()
transaction) by comparing the hash with the previous makeCommitment()
calls.
We usually consider the public RPC providers trustworthy or harmless, but they can be malicious when they are compromised. And always, they should not be trusted in the first place.
Public RPC gateway provided by Ankr for Polygon (https://polygon-rpc.com) and Fantom (https://rpc.ftm.tools) were comprised via DNS hijack on Jul 1, 2022:
https://twitter.com/Mudit__Gupta/status/1542840515292532736
Change makeCommitment()
from public
to internal
, and instruct all official frontend and third-party user interfaces to implement an offline commitment computation function and use that instead.
#0 - jefflau
2022-07-27T08:47:37Z
Recommend severity 0.
#1 - dmvt
2022-08-03T16:50:31Z
This is very low likelihood. Downgrading to QA.