Platform: Code4rena
Start Date: 14/04/2023
Pot Size: $90,500 USDC
Total HM: 7
Participants: 59
Period: 14 days
Judge: LSDan
Total Solo HM: 3
Id: 232
League: ETH
Rank: 2/59
Findings: 2
Award: $11,952.84
🌟 Selected for report: 1
🚀 Solo Findings: 1
🌟 Selected for report: MalfurionWhitehat
11893.0456 USDC - $11,893.05
https://github.com/code-423n4/2023-04-ens/blob/main/contracts/dnsregistrar/OffchainDNSResolver.sol#L109-L113 https://github.com/code-423n4/2023-04-ens/blob/main/contracts/dnsregistrar/OffchainDNSResolver.sol#L119
The resolveCallback
function from OffchainDNSResolver
is used as part of the EIP-3668 standard to properly resolve DNS names using an off-chain gateway and validating RRsets against the DNSSEC oracle.
The issue is that the function lacks proper error handling, specifically, a try/catch block to properly bubble up OffchainLookup
error from the dnsresolver
extracted from the RRset. As the EIP specifies,
When a CCIP-aware contract wishes to make a call to another contract, and the possibility exists that the callee may implement CCIP read, the calling contract MUST catch all
OffchainLookup
errors thrown by the callee, and revert with a different error if thesender
field of the error does not match the callee address. [...] Where the possibility exists that a callee implements CCIP read, a CCIP-aware contract MUST NOT allow the default solidity behaviour of bubbling up reverts from nested calls.
As per the EIP, the result would be an OffchainLookup that looks valid to the client, as the sender field matches the address of the contract that was called, but does not execute correctly.
OffchainDNSResolver.resolve
, which reverts with OffchainLookup
, and prompts the client to execute resolveCallback
after having fetched the necessary data from the gatewayURL
dnsresolver
that is a CCIP-aware contract, and also supports the IExtendedDNSResolver.resolve.selector
interfaceIExtendedDNSResolver(dnsresolver).resolve(name,query,context);
could trigger another OffchainLookup
error, but with a sender
that does not match the dnsresolver
, which would be just returned to the client without any modificationssender
field would be incorrect as per the EIPManual review
Use the recommended example from the EIP in order to support nested lookups.
#0 - c4-pre-sort
2023-05-01T13:35:30Z
thereksfour marked the issue as primary issue
#1 - c4-sponsor
2023-05-05T14:02:40Z
Arachnid marked the issue as sponsor confirmed
#2 - c4-judge
2023-05-08T15:18:53Z
dmvt marked the issue as selected for report
🌟 Selected for report: Sathish9098
Also found by: 0x73696d616f, 0xAgro, 0xSmartContract, 0xTheC0der, ABA, ArbitraryExecution, Aymen0909, BRONZEDISC, Bauchibred, Dyear, Eurovickk, IceBear, Jerry0x, Jorgect, Josiah, MalfurionWhitehat, MohammedRizwan, RaymondFam, Recep, Rickard, SAAJ, Shubham, Udsen, auditor0517, brgltd, catellatech, chaduke, codeslide, eierina, favelanky, j4ld1na, lukris02, matrix_0wl, naman1778, pontifex, schrodinger, tnevler, urataps
59.7928 USDC - $59.79
DNSClaimChecker.parseString
reverts with unexpected reason if str
contains less than 4 bytesfunction parseString( bytes memory str, uint256 idx, uint256 len ) internal pure returns (address, bool) { // TODO: More robust parsing that handles whitespace and multiple key/value pairs if (str.readUint32(idx) != 0x613d3078) return (address(0x0), false); // 0x613d3078 == 'a=0x' return str.hexToAddress(idx + 4, idx + len); }
For example, attempting to claim the RRset a=
will revert, as it contains only 2 bytes
Remediation: check if len - idx >= 4
before calling str.readUint32(idx)
#0 - c4-judge
2023-05-08T15:09:38Z
dmvt marked the issue as grade-b