Silly Amber Shell - Attacker can copy valid message and call `solana-vault::oapp_lz_receive` with arbitrary accounts allowing him to steal tokens from `vault_deposit_wallet` #119
Attacker can copy valid message and call solana-vault::oapp_lz_receive with arbitrary accounts allowing him to steal tokens from vault_deposit_wallet
Summary
An attacker can to listen for message sent on source chain, and execute them with crafted inputs on the destination chain to drain the protocol owned token account.
The solana-vault::oapp_lz_receive instruction can be called by anyone, as no verification is done on the transaction signer. Also, no checks are performed regarding the content of the message, and the actual token accounts provided with the instructions and involved in the token transfers.
The transfer is done from the vault_deposit_wallet (owned by PDA owned by the solana-vault program) to the user_deposit_wallet (which isn't verified), this allows an attacker to unauthorizedly drain USDC tokens from the vault_deposit_wallet
This allows an attacker to listen for message sent from the source chain, and front-run on the destination chain the Executor call to solana-vault::oapp_lz_receive, by replicating the content of the sent message, but maliciously swapped the user_deposit_wallet account provided in the instruction context, which don't match the expected receiver of the message.
_Also, it seems that in the current implementation of the Uln program, the attacker can proceed with the verification himself as there is no restriction on the caller, but here we don't even need that hypothesis as our attacker can simply wait for the verification to be commited to then call the solana-vault::oapp_lz_receive function._
See how, in contrast, another project checks the receiving wallet against the message param
Root Cause
solana-vault::oapp_lz_receive can be called by anyone
no check ensuring that the transfer correspond to the received message
transfer is executed using a PDA signer owned by the calling contract, meaning anyone can execute the transfer if no specific verification checks are done.
Internal pre-conditions
Victim request a withdrawal from source chain
Message get sucessfully verified on destination chain
External pre-conditions
Attacker detect victim withdrawal request and extract the message
Attacker calls solana-vault::oapp_lz_receive before the Executor with malicious inputs
Attack Path
Alice request a withdrawal
The message is constructed on the EVM Oapp (source chain) and sent through LZ to the Solana Oapp (destination chain)
at this point, the attacker sees the transaction on the source chain and extract the message
Once the message gets verified the attacker call solana-vault::oapp_lz_receive with the extracted message but provide its own user_deposit_wallet account rather than Alice's one
the transfer is executed and the attacker receive the funds
Impact
Loss of funds
PoC
No response
Mitigation
Ensure that user_deposit_wallet is the one expected in the message payload.
Silly Amber Shell
High
Attacker can copy valid message and call
solana-vault::oapp_lz_receive
with arbitrary accounts allowing him to steal tokens fromvault_deposit_wallet
Summary
An attacker can to listen for message sent on source chain, and execute them with crafted inputs on the destination chain to drain the protocol owned token account.
The
solana-vault::oapp_lz_receive
instruction can be called by anyone, as no verification is done on the transaction signer. Also, no checks are performed regarding the content of the message, and the actual token accounts provided with the instructions and involved in the token transfers.The transfer is done from the
vault_deposit_wallet
(owned by PDA owned by the solana-vault program) to theuser_deposit_wallet
(which isn't verified), this allows an attacker to unauthorizedly drain USDC tokens from thevault_deposit_wallet
This allows an attacker to listen for message sent from the source chain, and front-run on the destination chain the Executor call to
solana-vault::oapp_lz_receive
, by replicating the content of the sent message, but maliciously swapped theuser_deposit_wallet
account provided in the instruction context, which don't match the expected receiver of the message._Also, it seems that in the current implementation of the Uln program, the attacker can proceed with the verification himself as there is no restriction on the caller, but here we don't even need that hypothesis as our attacker can simply wait for the verification to be commited to then call the
solana-vault::oapp_lz_receive
function._See how, in contrast, another project checks the receiving wallet against the message param
Root Cause
solana-vault::oapp_lz_receive
can be called by anyoneInternal pre-conditions
External pre-conditions
solana-vault::oapp_lz_receive
before the Executor with malicious inputsAttack Path
payload_hash.hash
which is necessary when clear is called (1)(2) during thesolana-vault::oapp_lz_receive
instructionsolana-vault::oapp_lz_receive
with the extracted message but provide its ownuser_deposit_wallet
account rather than Alice's oneImpact
Loss of funds
PoC
No response
Mitigation
Ensure that
user_deposit_wallet
is the one expected in the message payload.