Closed code423n4 closed 1 year ago
Known issue by the sponsor (https://github.com/code-423n4/2023-01-canto-identity#automated-findings--publicly-known-issues)
String confusions: Subprotocols are identified by a string and there are multiple ways to encode the same human-readable string. It is the responsibility of the developer that integrates with CID to ensure that he queries the correct string.
Even though it's a valid point, it requires the user to make a mistake (it's not a systematic issue - regardless of how the likelihood is inflated in this submission). Additionally, the severity of the issue is very much overinflated.
I will for now leave this submission open for the sponsor review, but I'm inclined to close this issue as "Out of scope".
OpenCoreCH marked the issue as sponsor disputed
Agree that this also belongs to string confusions which were out of scope. I think it's important to mention that in practice, a user will rarely have a reason to type this string directly (unless he really wants to and knows what he is doing). Usually, there will be a frontend for a subprotocol that prepares the necessary call for the user. So this should be considered a developer interface, not a user-facing interface (which is also the reason that we do not perform any string sanitization).
berndartmueller marked the issue as unsatisfactory: Out of scope
Lines of code
https://github.com/code-423n4/2023-01-canto-identity/blob/dff8e74c54471f5f3b84c217848234d474477d82/src/SubprotocolRegistry.sol#L79-L101
Vulnerability details
Impact
The input sanitization statements in
SubprotocolRegistry.sol
'sregister()
function are:The subprotocol registry does not check for
_name
, and accepts an empty string "" in the protocol name field. This is an issue since in practically all manual contract calling tools (remix, etherscan etc), empty string is the default value for a string field. In remix, it does even raise an error if a function expecting a string is called without writing anything in the parameter dialog box.A malicious user can register the empty string "" subprotocol and specify non-zero fees. The user can register a bogus contract as the
_nftAddress
which passes thesupportsInterface
check and always returns true insafeTransferFrom
calls, allowing anyone to calladd()
. Any user/developer unfortunate enough to make anadd()
call in cidNFT contract with a missing subprotocol name will end up paying an arbitrary fee in note tokens to the malicious user.The impact of this issue is higher than a user simply putting in the wrong subprotocol name due to the following reasons:
add()
call will be reverted since a subprotocol probably doesn't exist with that name.add()
call is still likely to be reverted if the user doesn't hold the necessary nft address's necessary tokenId.Since the impact is high (loss of note tokens), and the circumstances of it occurring are believable (missed input during contract call), this is classified as high severity.
Proof of Concept
The following test can be added to
CidNFT.t.sol
:This shows
user1
can register empty string, anduser2
, when calling, loses note balance. In this POC theuser2
is minted an nft, but the attackeruser1
can simply create a bogus ERC721 contract which passes thesupportsInterface
check:and always returns
true
in itssafetransferFrom
function, allowing theadd()
call to go through.Tools Used
Foundry, Remix
Recommended Mitigation Steps
Add a simple sanity check during registration in
SubprotocolRegistry.sol
: