Users receive NFTs based on their contributions to different charities. By having these NFTs people could check how much a wallet has donated to any charity (currently there is no way to differentiate between the different charities based on the NFT's metadata). It would be very problematic if there was a way to mint these tokens, while not actually sending out the money to the charities.
Any user could get GivingThanks NFTs for free (minus the gas costs) by two ways:
Missing access control in GivingThanks.sol
-> updateRegistry()
Wrong return value in CharityRegistry
-> isVerified()
The simplified function we want to exploit is GivingThanks
-> donate()
If we somehow managed to bypass the isVerified() check on the charity input param, we could use our own address and get minted an NFT without any charity receiving it. After knowing about the two issues above, we have two ways to do that:
Register our address as a charity using CharityRegistry
-> registerCharity
change registry
in GivingThanks
using updateRegistry
and then use our own custom CharityRegistry
that would return true always
I've created my POC using the first method, because it gets the point across, but both exploit paths are equally destructive.
There's a severe disruption of protocol functionality
add access control to updateRegistry()
and change registeredCharities[charity]
to registeredCharities[charity]
in isVerified
Likelyhood: High, anyone can change it at anytime Impact: High, can bypass the verification process
Likelyhood: High, the function returns registered charities instead of verified ones. Impact: High, Any charities can be registered by anyone and will be declared as verified by this function bypassing verification.
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.