Open code423n4 opened 1 year ago
JeffCX marked the issue as primary issue
I definitely agree doing a check in OnRecvPacket to make sure a sender exists in the accounts module is good practice.
However, assets that are transferred via IBC are bounced back to the original chain if the user does not exist on canto. Therefore, the onboarding middleware layer would not get triggered because the IBC transfer wouldn't be successful.
In testing, the warden changes the recipient inside the onboarding middleware. Since the recipient was initially valid, the call has gone through all previous checks successfully and the IBC transfer is successful. Hence the onboarding middleware still executes, even though the recipient is technically invalid now.
tkkwon1998 marked the issue as disagree with severity
This sounds like input sanitization at its root to me, typically these types of issues are QA in C4 contests.
0xean changed the severity to QA (Quality Assurance)
0xean marked the issue as grade-a
Lines of code
https://github.com/code-423n4/2023-06-canto/blob/main/Canto/x/onboarding/keeper/ibc_callbacks.go#L63 https://github.com/code-423n4/2023-06-canto/blob/main/Canto/x/onboarding/keeper/ibc_callbacks.go#L48
Vulnerability details
Impact
It appears that
user funds can be lost
in case of onboarding is made for a recipient account thatdoesn't exist
orhas an unsupported public key type
in the Canto network, which is why I submit this as aHigh
.So in case a user provide valid recipient in the onboarding (so the format is totally valid), there is a possibility that the account doesn't exist, in which case the expected behavior should be to short-circuit the onboarding (confirmed with
t_k___
in discord DM), but instead the onboarding works as if the account would exist, which means afterward the coins transfered will not be accessible by anyone and be lost. As I understand it compare to ETH network, it would be like if you transfer the coin to valid address but that you don't control.Additionally, since the recovery middleware do some check about if an account have a public key supported by Canto, it seems that this condition would also be required here to cover the similar case, where the account exist, but with a public key that is not supported by Canto, which would cause the same problematic.
Proof of Concept
Keep the code as it is in the repo. 1) Comment this line :
account := k.accountKeeper.GetAccount(ctx, recipient)
2) Add this line instead:var account authtypes.AccountI
3) Run the unit testswap / convert remaining ibc token - swap and erc20 conversion are successful
, it will pass, which confirm the bug, as it should fails as the expected result should be thatonboarding is disabled
in such case.Tools Used
Go v1.20 and Goland IDE
Recommended Mitigation Steps
I made the following modification that you can apply to address the current submission. Additionally, added small improvements the code which I would still recommend (Low) 1) I added a
break
statement when looking for the whitelist, as once one is found, there is no reason to continue looping. 2) MovedstandardDenom
down to be along where it is used (cleaner code), and also usingparams
instead of callingk.GetParams(ctx)
which is just a waste.Finally, I had another concern for a specific case where
sender == recipient
, but could not confirm if this is a real problem, but I would recommend the team to think about that scenario.Assessed type
Other