Users can skirt fuses on subnodes #117
Labels
3 (High Risk)
Assets can be stolen/lost/compromised directly
bug
Something isn't working
duplicate
This issue or pull request already exists
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#L539
https://github.com/code-423n4/2022-07-ens/blob/ff6e59b9415d0ead7daf31c2ed06e86d9061ae22/contracts/wrapper/NameWrapper.sol#L504
https://github.com/code-423n4/2022-07-ens/blob/ff6e59b9415d0ead7daf31c2ed06e86d9061ae22/contracts/wrapper/NameWrapper.sol#L524
https://github.com/code-423n4/2022-07-ens/blob/ff6e59b9415d0ead7daf31c2ed06e86d9061ae22/contracts/wrapper/ERC1155Fuse.sol#L298
Vulnerability details
Impact
If users are granted subnode ownership through
setSubnodeRecord
orsetSubnodeOwner
inNameWrapper.sol
,and that node is owned by the NameWrapper contract in the ENS registry (and the unwrap fuse is not set), then attackers can reset flags and do whatever they want with the subnode records.
I marked this as medium because users can recover from this if they noticed, and very specific circumstances have to be set, but the damage done can be large. The circumstances of this bug also don't seem unlikely.
This mainly happens because
_transferAndBurnFuses
uses the_transfer
function in theERC1155Fuse.sol
contract and that performs a callback through the ERC1155_doSafeTransferAcceptanceCheck
call.Proof of Concept
I created a simple attacker contract and tested with a javascript test inside of the already existing test suite provided in the code:
Attacker.sol
:Javascript test to show this all works:
Tools Used
javascript, solidity, and chai tests inside repo
Recommended Mitigation Steps
To make sure users can't exploit this, I would recommend making sure all state changes in the contract happen before we call any callbacks.
For example, a possible solution here is creating a special
_transfer
function in theERC1155Fuse.sol
that does a last_setData
call with the new fuses before calling_doSafeTransferAcceptanceCheck
, so passing in fuses and data into the function to set before the user gets any access.Any solution that makes sure that callback happens after the new data is set is preferred and will work.
The text was updated successfully, but these errors were encountered: