Closed code423n4 closed 1 year ago
berndartmueller marked the issue as primary issue
OpenCoreCH marked the issue as disagree with severity
Valid finding, will be changed.
However, I do not see any direct impact and think that wrong events have been historically marked as QA. But I leave that to the judge.
I agree with the sponsor. According to the C4 judging criteria, I consider downgrading it to QA (NC).
QA (Quality Assurance) Includes both Non-critical (code style, clarity, syntax, versioning, off-chain monitoring (events, etc)
berndartmueller changed the severity to QA (Quality Assurance)
berndartmueller marked the issue as grade-b
Lines of code
https://github.com/code-423n4/2023-01-canto-identity/blob/main/src/CidNFT.sol#L257-L272
Vulnerability details
The
remove
function present in theCidNFT
contract can be used to dissociate a subprotocol NFT from a CID. This function takes a_nftIDToRemove
parameter that is useful for the case ofAssociationType.ACTIVE
in order to look for the position in the underlying array that needs to be deleted. However, this parameter is wrongly used in the other two association type cases to emit events, and allows a bad actor to emit arbitrary data.https://github.com/code-423n4/2023-01-canto-identity/blob/main/src/CidNFT.sol#L257-L272
In both
AssociationType.ORDERED
andAssociationType.PRIMARY
cases, the code will remove the current associated subprotocol NFT ID (currNFTID
) but will emit the event using the_nftIDToRemove
parameters, which is user controlled.Impact
This can be used by an attacker to forge the remove event data and set an arbitrary subprotocol NFT ID when emitting the log. This may eventually lead to other consequences as this event is likely used by off-chain indexers.
PoC
In the following, an attacker uses Alice's subprotocol NFT ID to call the
remove
function. ThePrimaryDataRemoved
event will be emitted using her subprotocol id.Recommendation
In the cases of
AssociationType.PRIMARY
andAssociationType.ORDERED
, theremove
function should emit the corresponding event using the actual stored subprotocol NFT ID (currNFTID
) instead of the_nftIDToRemove
passed as an argument.