sherlock-audit / 2024-05-pooltogether-judging

0 stars 0 forks source link

elhaj - Potential ETH Loss Due to transfer Usage in Requestor Contract on `zkSync` #80

Open sherlock-admin2 opened 1 month ago

sherlock-admin2 commented 1 month ago

elhaj

medium

Potential ETH Loss Due to transfer Usage in Requestor Contract on zkSync

Summary

Vulnerability Detail

notice that in case msg.sender is a contract that have some logic on it's receive or fallback function the ETH is definitely not retrievable. since this contract can only withdraw eth to it's own addres which will always revert.

Impact

sherlock-admin2 commented 3 weeks ago

1 comment(s) were left on this issue during the judging contest.

infect3d commented:

invalid__ only affect bots that deliberately chose to set code inside the fallback function

trmid commented 3 weeks ago

The zkSync doc link provided in the issue does not seem to have information on this behaviour anymore. Is there an updated link on the issue?

nevillehuang commented 3 weeks ago

request poc

sherlock-admin4 commented 3 weeks ago

PoC requested from @elhajin

Requests remaining: 1

elhajin commented 3 weeks ago
InfectedIsm commented 2 weeks ago

Escalate

This submission make the assumption that the caller will set code in their callback to process received ETH. This pose the assumption that those callers will not be aware of the limitation of the transfer/send behavior on these chains. Setting code in the callback isn't required at all for the caller. By simply not setting code in their callback, the issue disappear, thus this is a user error and not a vulnerability of the codebase, but rather a proposition of improvement of the implemented mechanism.

from the doc: https://docs.zksync.io/build/developer-reference/best-practices#use-call-over-send-or-transfer

Avoid using payable(addr).send(x)/payable(addr).transfer(x) because the 2300 gas stipend may not be enough for such calls, especially if it involves state changes that require a large amount of L2 gas for data. Instead, we recommend using call.

sherlock-admin3 commented 2 weeks ago

Escalate

This submission make the assumption that the caller will set code in their callback to process received ETH. This pose the assumption that those callers will not be aware of the limitation of the transfer/send behavior on these chains. Setting code in the callback isn't required at all for the caller. By simply not setting code in their callback, the issue disappear, thus this is a user error and not a vulnerability of the codebase, but rather a proposition of improvement of the implemented mechanism.

from the doc: https://docs.zksync.io/build/developer-reference/best-practices#use-call-over-send-or-transfer

Avoid using payable(addr).send(x)/payable(addr).transfer(x) because the 2300 gas stipend may not be enough for such calls, especially if it involves state changes that require a large amount of L2 gas for data. Instead, we recommend using call.

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.

nevillehuang commented 2 weeks ago

I wouldn't call this user error because any address can be used to transfer funds to creator. Also it does not just affect caller with no code and there is clear evidence from the sponsor acknowledgement and lack of details in contest that the sponsor wasn't aware of this issue.

0xAadi commented 2 weeks ago

Disagreeing with the Escalation

By simply not setting code in their callback, the issue disappears.

Removing the callbacks from the caller will not solve this issue.

The core issue is not related to the use of code in the callback; rather, it is a limitation of the ZkSync chain. The core issue arises due to the dynamic gas measurement followed in ZkSync.

ZkSync usually requires more than 2300 gas to process transfer()/send() functions. Therefore, the withdraw() function will always revert due to the lack of enough gas to process transfer() on ZkSync.

ZkSync explicitly mentions this in their security and best practice documentation:

Avoid using payable(addr).send(x)/payable(addr).transfer(x) because the 2300 gas stipend may not be enough for such calls.

The situation worsens if there are any callback functionalities in the caller.

This is a known issue in ZkSync, as evidenced by previous occurrences in other protocols:

Note: Please see issues #24 and #139, which explain the issue in detail.

InfectedIsm commented 2 weeks ago

Fair enough, I wasn't able to find that even without callback execution it could spend more than 2300. Sorry for the misunderstanding, and thanks for the detailed explanation!

0xAadi commented 2 weeks ago

In addition to my previous comment:

This issue causes a loss of ETH in ZkSync.

According to Sherlock's docs, this issue should be considered as valid HIGH:

IV. How to identify a high issue:

  1. Definite loss of funds without (extensive) limitations of external conditions.

Please consider upgrading the severity to HIGH.

Please find my thoughts on the duplicates below:

24 and #139 both identify the same issue in ZkSync.

94 missed the aforementioned issue but did identify another medium-risk attack path.

119 missed both of the aforementioned attack paths but identified a more general issue.

WangSecurity commented 1 week ago

Since the escalator agrees with the other side (correct me if it's wrong) and based on the discussion above, I believe this issue should remain as it is. Planning to reject the escalation.

0xAadi commented 1 week ago

the escalator agrees with the other side (correct me if it's wrong)

true, reference

@WangSecurity, As I mentioned in this duplicate and here, This vulnerability can cause loss of ETH on the zkSync chain.

Therefore, please consider upgrading the severity of this issue from medium to high.

WangSecurity commented 1 week ago

Is there a specific number of ETH that has to be transferred in that case, or it can be as small as 1 wei? And as I understand there's still a possibility the transfer would work correctly?

InfectedIsm commented 1 week ago

Rng draw rewards are very low ( <0.0001 WETH), as it can be seen on the Pool Together dashboard: https://analytics.cabana.fi/optimism The loss that will be experienced by rng drawer isn't large enough to be an argument for a high severity imo

WangSecurity commented 1 week ago

I agree with the comment above, I believe it's a small value and only caused on one chain, hence, I believe medium is more appropriate.

The decision remains the same, planning to reject the escalation and leave the issue as it is.

WangSecurity commented 1 week ago

Result: Medium Has duplicates

sherlock-admin4 commented 1 week ago

Escalations have been resolved successfully!

Escalation status:

sherlock-admin2 commented 5 days ago

The protocol team fixed this issue in the following PRs/commits: https://github.com/GenerationSoftware/pt-v5-rng-witnet/pull/9