Sablier implements a gracePeriod
(until 7 days after first claim) and a clawback
functionality so that the creator has enough time to analyse and retrive funds in case of an emergency or a malicious campaign, or any other reason deemed fit by the admin.
While this functionality protects the creator from losing funds incase he created a campaign with malicious/invalid merkleTree as mentioned here, it still doesn't protect him from losing funds incase of a manipulated/invalid csv file.
This is because the claim
function is available to everyone even during the grace period
and can be exploited to end the campaign as soon as it is created.
The claim
function might seem like a design choice because the recipient still gets his airdrop and the caller pays for gas.
However, it can open up attack vectors and loss of critical functionalities for the protocol and in some cases loss of funds.
This design(or vulnerability) will not been an issue if the merkle proofs and addresses were not known because to perform the attack through the app by trying to claim all the airdrops one by one will be impossible, but we will see how an attacker can get those information in the POC
section.
This vulnerability occurs in both the SablierV2MerkleLL::claim
and SablierV2MerkleLT::claim
.
Suppose a campaign is created with just five recipients(for the sake of our example),
and there is a mistake in the allocation of amounts in csv
file of the campaign;
when it should have been:
The campaign creator notice this during the grace period
and calls clawback
to retrive the funds.
Any recipient who will benefit from it(or could be anyone) can frontrun it by claiming all the airdrops at once which will revert the clawback since all the funds are claimed.
This could also be done as soon as any campaign is created.
As a result the campaign creator and user5, will lose funds.
This is just one possible example with very less recipient, but there are could be many possible mistakes in the csv file like, listing the same recipient twice, etc.
Since airdrops could be created by anyone and the csv file is out of the controll of sablier, there could be campaigns with hundreds or thaousands or even less than 10 number of recipients and as the protocol grows there would be more campaigns and the chance to make mistake(or a manipulated csv) in the csv files will only increase. And the protocol fails to protect this with the gracePeriod
if claim
function is exploited.
To show this attack, I've used campaign $USDT By 0x13c..F50b
as an example.
This airstream is live and contains only two recipients with one claimed and is choosen purposely to make this example easier.
Note that this airstream uses the currently deployed version of sablier, but this part of the code is the same with this codebase given for audit.
So, to claim it directly by calling the contract we need to get the required inputs, this is open for anyone to query and is well documented here, which makes the exploit alot easier for the attacker.
First, before we get the merkle proofs we need to know the addresses of the recipients and anyone can get this through the app by going to the target airstream ---> manage ---> Download Merkle tree
. And we will get something like:
We can also get this directly from ipfs using the cid
which we can get it from etherscan.
After this we still need what merkle proofs are to be passed along with each addresses, so finally
to get the informations required we query the api using python:
run this file and get the proofs needed:
Now that we have the required inputs, we can claim the airstream using this test:
now we can see that the attacker can successfully clam the airdrop by calling the contract directly(to run the test please initialize a new forge project);
Note: The test example given is no different than manually claiming for the recipient through the Sablier app which is practically impossible for the attacker to do it for campaigns with hundreds of recipients. But the point I want to make here is in the python code where the attacker could get all the proofs needed.
The attacker can automate the process of getting all the proofs for all the recipients through the api using python, and instead of claiming it one by one he could batch up and claim it all in one transaction to make it more gas efficient and faster using a contract like this:
grace period, which is one of a critical functionality for the protocol can be taken away from every newly created campaign by a reciever(who profits from it) or by an attacker who is willing to pay the gas fees. And with chains like polygon the fees paid will be much lower. This would mean the grace period
and expiry date of the campaign
was not there in the first place.
in case the campaign was created with streams that are uncancellable then there could be permanent loss of funds for the creator or recipients. In this case a recipient can gain from the attack but even with an attacker with no incentive if done the users of the protocol i.e. creators and recipients will be affected from it.
impact : medium, because funds are indirectly at risk and some level of disruption to the protocol's functionality.
likelihood : medium, because It might occur under specific conditions, it would need a campaign creator mistake or intention to clawback
funds, and as the no. of campaigns increases this likelyhood also increases.
manual
Restrict the claim
functions in such a way that only the recipient can call it during the grace period and after the grace period open the function to anyone so that someone else can claim it for recipient addresses with no gas.
add this code block in the claim
function of both SablerV2MerkleLL
and SablerV2MerkleLT
:
This protects the campaign from an attacker claiming all the airdrops before gracePeriod passed, ensuring that campaign creators get enough gracePeriod
if they have any intention to clawback funds and also the protocol doesn't lose out on the design(allowing recipients with no gas to be able to claim airdrop).
https://docs.codehawks.com/hawks-auditors/how-to-determine-a-finding-validity
https://docs.codehawks.com/hawks-auditors/how-to-determine-a-finding-validity
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.