[PNM-003] The preimage DB (i.e., NameWrapper.names
) can be maliciously manipulated/corrupted
#197
Labels
2 (Med Risk)
Assets not at direct risk, but function/availability of the protocol could be impacted or leak value
bug
Something isn't working
sponsor confirmed
Sponsor agrees this is a problem and intends to fix it (OK to use w/ "disagree with severity")
Lines of code
https://github.com/code-423n4/2022-07-ens/blob/ff6e59b9415d0ead7daf31c2ed06e86d9061ae22/contracts/wrapper/NameWrapper.sol#L520
Vulnerability details
Description
By design, the
NameWrapper.names
is used as a preimage DB so that the client can query the domain name by providing the token ID. The name should be correctly stored. To do so, theNameWrapper
record the domain's name every time it gets wrapped. And as long as all the parent nodes are recorded in the DB, wrapping a child node will be very efficient by simply querying the parent node's name.However, within a malicious scenario, it is possible that a subdomain can be wrapped without recording its info in the preimage DB.
Specifically, when
NameWrappper.setSubnodeOwner
/NameWrappper.setSubnodeRecord
on a given subdomain, the following code is used to check whether the subdomain is wrapped or not. The preimage DB is only updated when the subdomain is not wrapped (to save gas I beieve).However, the problem is that
ens.owner(node) != address(this)
is not sufficient to check whether the node is alreay wrapped. The hacker can manipulate this check by simply invokingEnsRegistry.setSubnodeOwner
to set the owner as theNameWrapper
contract without wrapping the node.Consider the following attack scenario.
base.eth
sub1.base.eth
sub1.base.eth
should be set as expired shortlysub1.base.eth
instead ofbase.eth
, so it is safe to make it soonly expiredsub1.base.eth
ens.setSubnodeOwner
to set the owner ofsub2.sub1.base.eth
as NameWrapper contractsub1.base.eth
nameWrapper.setSubnodeOwner
forsub2.sub1.base.eth
names[namehash(sub2.sub1.base.eth)]
becomes emptynameWrapper.setSubnodeOwner
foreth.sub2.sub1.base.eth
.names[namehash(eth.sub2.sub1.base.eth)]
becomes\x03eth
It is not rated as a High issue since the forged name is not valid, i.e., without the tailed
\x00
(note that a valid name should be like\x03eth\x00
). However, the preimage BD can still be corrupted due to this issue.Notes
Discussed with the project member, Jeff Lau.
If there is any issue running the attached PoC code, please contact me via
izhuer#0001
discord.Suggested Fix
When wrapping node
X
, check whetherNameWrapper.names[X]
is empty directly, and update the preimage DB if it is empty.PoC / Attack Scenario
There is a PoC file named
poc3.js
To run the PoC, put then in
2022-07-ens/test/wrapper
and runnpx hardhat test --grep 'PoC'
.poc3.js
The text was updated successfully, but these errors were encountered: