Skip to content
This repository has been archived by the owner on Jan 7, 2024. It is now read-only.

0x52 - Malicious user can grief withdrawing users via VUSD reentrancy #153

Open
sherlock-admin opened this issue Jul 3, 2023 · 11 comments
Labels
Escalation Resolved This issue's escalations have been approved/rejected Has Duplicates A valid issue with 1+ other issues describing the same vulnerability Medium A valid Medium severity issue Reward A payout will be made for this issue Sponsor Confirmed The sponsor acknowledged this issue is valid Will Fix The sponsor confirmed this issue will be fixed

Comments

@sherlock-admin
Copy link
Contributor

0x52

medium

Malicious user can grief withdrawing users via VUSD reentrancy

Summary

VUSD#processWithdraw makes a call to withdrawal.usr to send the withdrawn gas token. processWithdrawals is the only nonreentrant function allowing a user to create a smart contract that uses it's receive function to deposit then immediately withdraw to indefinitely lengthen the withdrawal queue and waste large amounts of caller gas.

Vulnerability Detail

VUSD.sol#L69-L77

    while (i < withdrawals.length && (i - start) < maxWithdrawalProcesses) {
        Withdrawal memory withdrawal = withdrawals[i];
        if (reserve < withdrawal.amount) {
            break;
        }

        (bool success, bytes memory data) = withdrawal.usr.call{value: withdrawal.amount}("");
        if (success) {
            reserve -= withdrawal.amount;

To send the withdrawn gas token to the user VUSD#processWithdrawals utilizes a call with no data. When received by a contract this will trigger it's receive function. This can be abused to continually grief users who withdraw with no recurring cost to the attacker. To exploit this the attacker would withdraw VUSD to a malicious contract. This contract would deposit the received gas token then immediately withdraw it. This would lengthen the queue. Since the queue is first-in first-out a user would be forced to process all the malicious withdrawals before being able to process their own. While processing them they would inevitably reset the grief for the next user.

NOTE: I am submitting this as a separate issue apart from my other two similar issues. I believe it should be a separate issue because even though the outcome is similar the root cause is entirely different. Those are directly related to the incorrect call parameters while the root cause of this issue is that both mintWithReserve and withdraw/withdrawTo lack the reentrant modifier allowing this malicious reentrancy.

Impact

Malicious user can maliciously reenter VUSD to grief users via unnecessary gas wastage

Code Snippet

VUSD.sol#L45-L48

VUSD.sol#L50-L52

VUSD.sol#L58-L60

Tool used

Manual Review

Recommendation

Add the nonreentrant modifer to mintWithReserve withdraw and withdrawTo

@0xshinobii
Copy link

Will add the nonreentrant modifer to mintWithReserve withdraw and withdrawTo

@0xshinobii 0xshinobii added Sponsor Confirmed The sponsor acknowledged this issue is valid Will Fix The sponsor confirmed this issue will be fixed labels Jul 18, 2023
@ctf-sec
Copy link
Collaborator

ctf-sec commented Jul 18, 2023

To exploit this the attacker would withdraw VUSD to a malicious contract. This contract would deposit the received gas token then immediately withdraw it.

I put this issue and #160 together because these two issue highlight different ways of wasting gas, but they also focus on how to waste gas in external call.

Recommend checking #160 as well.

and I leave the #158 as a separate issue because the root cause is the returned call data is emitted in the contract code itself

@0xshinobii
Copy link

yes noted. #160 has slightly different cause but same effect. So the solution for all these related issues is

@IAm0x52
Copy link
Collaborator

IAm0x52 commented Jul 20, 2023

Escalate

As the sponsor has pointed out, this is a different issue from the dupes. While the outcome of wasting gas is similar, the root cause is completely different. The root cause for this is reentrancy across functions, while the root cause of issues marked as dupes is that there is no gas limit. I suggest that this issue be separated and the dupes groped together as separate issues.

Edit:
Missed #195. That and this should be considered a separate issue

@sherlock-admin2
Copy link

sherlock-admin2 commented Jul 20, 2023

Escalate

As the sponsor has pointed out, this is a different issue from the dupes. While the outcome of wasting gas is similar, the root cause is completely different. The root cause for this is reentrancy across functions, while the root cause of issues marked as dupes is that there is no gas limit. I suggest that this issue be separated and the dupes groped together as separate issues.

Edit:
Missed #195. That and this should be considered a separate issue

You've created a valid escalation!

To remove the escalation from consideration: Delete your comment.

You may delete or edit your escalation comment anytime before the 48-hour escalation window closes. After that, the escalation becomes final.

@sherlock-admin sherlock-admin added the Escalated This issue contains a pending escalation label Jul 20, 2023
@ctf-sec
Copy link
Collaborator

ctf-sec commented Jul 20, 2023

See escalation #116

There are a lot of ways to consume all gas in external call (reentrancy to expand the queue size, gas token, for loop, swap, etc....), cannot count each of them as duplicates

I think grouping all these issue about wasting gas in external call to one issue make sense, root cause is gas limit not capped.

@0xArcturus
Copy link

Agreed with escalation,
as also mentioned in #195, the root cause of this is the lack of reentrancy guard and the withdrawals.length changing during execution. This attack can bloat the queue by reentering with a single withdraw call, while the dupes are focused on consuming gas in a single call.

@hrishibhat hrishibhat added Medium A valid Medium severity issue and removed High A valid High severity issue labels Aug 4, 2023
@hrishibhat
Copy link

Result:
Medium
Has duplicates
Agree with the escalation that this should be a separate issue along with #195

@sherlock-admin2 sherlock-admin2 removed the Escalated This issue contains a pending escalation label Aug 4, 2023
@sherlock-admin sherlock-admin added the Escalation Resolved This issue's escalations have been approved/rejected label Aug 4, 2023
@sherlock-admin2
Copy link

Escalations have been resolved successfully!

Escalation status:

@0xshinobii
Copy link

Fixed in this PR. The description is in the PR.

@IAm0x52
Copy link
Collaborator

IAm0x52 commented Aug 10, 2023

Fix looks good. mintWithReserve, withdraw, and withdrawTo now use the nonreentrant modifier to prevent this exploit

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Escalation Resolved This issue's escalations have been approved/rejected Has Duplicates A valid issue with 1+ other issues describing the same vulnerability Medium A valid Medium severity issue Reward A payout will be made for this issue Sponsor Confirmed The sponsor acknowledged this issue is valid Will Fix The sponsor confirmed this issue will be fixed
Projects
None yet
Development

No branches or pull requests

7 participants