According to Jet Protocol’s official blog, they recently fixed a bounty vulnerability that would allow malicious users to withdraw any user’s deposit funds. The SlowMist security team briefly analyzed this vulnerability and shared the analysis results as follows.
Jet Protocol is a lending market running on Solana. Users can deposit tokens (such as USDC, SOL) in their accounts into the vault to earn annualized income, and they can also lend another token at a certain percentage. currency. In this process, the contract will give the user a note certificate, as the user’s future withdrawal certificate, which is LP in familiar terms, and the reason for this vulnerability is also related to the design of this LP.
We know that compared with Ethereum contracts, Solana contracts do not have the concept of state. Instead, an account mechanism is used. Contract data is stored in the associated account. This mechanism greatly improves Solana’s blockchain performance, but it also gives Contract writing brings some difficulties. The biggest difficulty is the need to fully verify the entered account. Jet Protocol uses the Anchor framework for development. Anchor is developed by the well-known project Serum team on Solana, which can simplify many account verification and cross-contract calling logic.
How does Anchor work? We can start with a piece of code from Jet Protocol:
The deposit_account account here is the account used to store LP token data. When users use it for the first time, they need to call the contract to generate the account and pay a certain storage fee.
The #[account] macro definition here defines the generation rules for this account:
Rule 1: #[account(init, payer = <target_account>, space = <num_bytes>)]
In this constraint, init refers to creating and initializing an account by calling the system contract across contracts, and payer=depositor means that the depositor pays for the new account Storage space charges.
Rule 2: #[account(seeds = <seeds>, bump)]
This constraint will check whether the given account is a PDA derived from the currently executing program. The PDA (Program Derived Address) account is a program derived without a private key. Account, seed and bump are generated seeds. If bump is not provided, the Anchor framework uses canonical bump by default, which can be understood as automatically assigning a deterministic value.
Using a PDA, programs can programmatically sign certain addresses without the need for a private key. At the same time, the PDA ensures that no external user can also generate a valid signature for the same address. These addresses are the basis for cross-program calls, which allow Solana applications to compose with each other. Here the “deposits” character + reserve account public key + depositor account public key are used as seeds, and bump is passed in when the user calls.
规则 3：#[account(token::mint = <target_account>, token::authority = <target_account>)]
This is an SPL constraint for easier verification of SPL accounts. The deposit_account account specified here is a token account, its mint authority is the deposit_note_mint account, and the authority authority is market_authority.
There are many macro definitions for Account, which are not mentioned here. For details, please consider the documentation:
With these prerequisites, we can directly look at the vulnerability code:
Under normal circumstances, when the user calls the function withdraw_tokens to withdraw coins, he will pass in his LP account, and then the contract will destroy his LP and return the corresponding amount of tokens. But here we can see that the deposit_note_account account is not subject to any constraints, and the user can freely pass in the LP account of other users. Don’t use someone else’s LP account without their signature authorization?
Through the previous analysis of the macro definition code, we already know that the market_authority account has the operation authority of LP tokens, and does not require the user’s own signature. So what kind of account is market_authority? We can look here:
This market_authority is also a PDA account. That is to say, the contract can destroy the user’s LP tokens through its own invocation. Then for a malicious user, it is very simple to launch an attack. Simply set the deposit_note_account account as the target account you want to steal, and set the withdraw_account account as your own collection account, you can destroy his LP and put his The deposit principal is withdrawn to your own account.
Finally, let’s take a look at the official fix:
The patch does not directly restrict the deposit_note_account account, but removes the PDA signature of the burn operation, and changes the authority permission to depositor. In this case, the user will not be able to directly call the function here for withdrawal, but must use another function withdraw. () to indirectly call, and the account macro definition in the withdraw() function has been strictly verified. If a malicious user passes in someone else’s LP account, he will not be able to pass the verification of the macro rules, and will not be able to pass the macro rules. Verification, because the depositor needs to meet the signature verification of the signer, and cannot be faked as someone else’s account.
The discovery process of this vulnerability is quite dramatic. The discoverer of the vulnerability, @charlieyouai, shared his thoughts on the discovery of the vulnerability on his personal Twitter. At that time, he found that the authority of burn was market_authority, and users could not sign, thinking it was a bug , which will cause the call to fail and the user to be unable to withdraw money, so a bounty vulnerability was submitted to the official, and then he went to eat, sleep and play Doudou.
Then the official developers realized the seriousness of the problem. Strictly speaking, they know that this code has no vulnerabilities that cannot be withdrawn, but that everyone can withdraw, old iron, a bug that works well. Do you know what it means? ? ! Fortunately, no attack occurred.
At present, many hacking incidents on Solana are related to the account verification problem. The SlowMist security team reminds the majority of Solana developers to pay attention to the strict review of the account system.
Posted by:CoinYuppie，Reprinted with attribution to:https://coinyuppie.com/vulnerability-essay-talking-about-pda-and-anchor-account-verification-through-jet-protocol-arbitrary-withdrawal-vulnerability/
Coinyuppie is an open information publishing platform, all information provided is not related to the views and positions of coinyuppie, and does not constitute any investment and financial advice. Users are expected to carefully screen and prevent risks.