As the blockchain world expands, Solana has stepped into the spotlight as a compelling alternative to Ethereum. But behind its lightning-fast transactions and low fees lies a hidden world of unique security challenges.
One such vulnerability that we frequently encounter during our security audits on the Solana blockchain is known as the “Revival Attack“. This post will dive deep into how these attacks work, their impact, and how to prevent them.
A Revival Attack occurs when a malicious actor prevents an account from being properly closed on the Solana blockchain, allowing them to reuse the account in ways the program didn’t intend. This vulnerability stems from the way Solana handles account closure and garbage collection.
On Solana, accounts need to maintain a minimum balance of lamports (Solana’s native token) to remain “rent-exempt” and avoid being garbage collected (i.e. deleted) by the runtime. When a program wants to close an account, it typically:
1. Transfers out all lamports from the account
2. Expects the Solana runtime to garbage collect the account
However, there’s a critical detail: garbage collection only happens after a transaction completes. This creates a window of opportunity for attackers.
Let’s look at a vulnerable implementation of an account closure:
This code appears to close the account by removing its lamports, but it has a critical flaw: the account can be “revived” within the same transaction. An attacker could send a transaction with these 2 instructions:
At the end of the transaction account_to_close will still be “rent-exempt” so it will not be deleted by the garbage collector.
To illustrate how a Revival Attack might work in a Solana protocol, let’s consider a staking vault program. This program allows users to deposit their tokens into a vault, which would then be staked on their behalf.
Users could then redeem their staked tokens, along with any rewards earned, by calling a redeemStakedTokens instruction.
Here’s a simplified version of the vulnerable redeemStakedTokens instruction:
By transferring out lamports from the user_stake PDA, the protocol expects it to be deleted at the end of the end of the transaction. It can actually be revived and reused!
An attacker could exploit this vulnerability using the following transaction structure:
By bundling these instructions in a single transaction, the attacker can:
The impacts of Revival Attacks can be severe:
To properly close accounts and prevent Revival Attacks, implement all three of these measures:
2. Set a closed account discriminator:
All functions that should not support an account being revived should then check that imputed accounts discriminators.
3. Transfer out all lamports:
If you’re using the Anchor framework, you can use the close constraint, which handles all these steps automatically:
Note that since Anchor 0.30.0 the close constraint no longer adds a CLOSED_ACCOUNT_DISCRIMINATOR. It only:
Thus, the account could be reinitialized later or revived in the same transaction but with zeroed out data.
While you can’t prevent an attacker from refunding an account with lamports, proper implementation of all three closure steps ensures that:
1. The account data is wiped, preventing reuse of old state
2. The closed discriminator prevents the program from accepting the account in future transactions
3. You program should be exploit-proof at this stage but users could still put some accounts in a state that is not usable but not garbage collected at the same time. If that’s something you do not want in your program, Solana course book recommends to implement a Manual Force Defund function.
Revival Attacks represent a subtle but significant vulnerability in Solana programs. As security researchers at FuzzingLabs, we’ve seen this pattern repeatedly in bug bounty programs. Always implement proper account closure mechanisms, preferably using Anchor’s close constraint.
Remember: in blockchain security, the smallest oversight in account management can lead to significant exploits. Always thorough test your account closure logic, and consider how your program handles closed accounts that maintain their rent-exempt status.
https://solana.com/developers/courses/program-security/closing-accounts
Mathieu Troullier / Patrick Ventuzelo
Founded in 2021 and headquartered in Paris, FuzzingLabs is a cybersecurity startup specializing in vulnerability research, fuzzing, and blockchain security. We combine cutting-edge research with hands-on expertise to secure some of the most critical components in the blockchain ecosystem.
Contact us for an audit or long term partnership!