I am currently experimenting a bit with Solana accounts and I am wondering if it is possible to change the owner of an account.
I am curious it is possible since the security of some programs are relying on this owner check, as explained here
I am also looking into the assign function and on how it works, but I was not able to make it work yet.
Am I misunderstanding something or just was not able to make it work?
Here the Python code is used:
tx = Transaction().add(
create_account(CreateAccountParams(
from_pubkey=attacker_keypair.public_key,
new_account_pubkey=account_keypair.public_key,
lamports=client.get_minimum_balance_for_rent_exemption(0)["result"],
space=0,
program_id=attacker_keypair.public_key,
))
)
send_and_confirm_tx(client, tx, attacker_keypair, account_keypair)
print('Sending 1st tx to program')
tx = Transaction().add(TransactionInstruction(
keys=[
AccountMeta(pubkey=account_keypair.public_key, is_signer=False, is_writable=False),
],
program_id=PROGRAM_ID,
))
send_and_confirm_tx(client, tx, attacker_keypair)
print('Sending 2nd tx to program')
tx = Transaction().add(assign(AssignParams(
account_pubkey=account_keypair.public_key,
program_id=attacker2_keypair.public_key
)))
send_and_confirm_tx(client, tx, account_keypair)
Error message is: InvalidAccountForFee
account_keypair
was already assigned to attacker_keypair
, so when you try to use it as the fee payer in 2nd tx
, the runtime yells at you, since account_keypair
can only have its lamports reduced by the program living at attacker_keypair
. To quickly fix your current issue, you can do:
print('Sending 2nd tx to program')
tx = Transaction().add(assign(AssignParams(
account_pubkey=account_keypair.public_key,
program_id=attacker2_keypair.public_key
)))
send_and_confirm_tx(client, tx, attacker_keypair, account_keypair)
This will cause another problem however. account_keypair
is already owned by attacker_keypair
, so only a program deployed to attacker_keypair
can reassign ownership of account_keypair
. You can read up more on the Solana Account model at: https://docs.solana.com/developing/programming-model/accounts#ownership-and-assignment-to-programs
The part that's interesting to you is:
The owner is a program id. The runtime grants the program write access to the account if its id matches the owner. For the case of the System program, the runtime allows clients to transfer lamports and importantly assign account ownership, meaning changing the owner to a different program id. If an account is not owned by a program, the program is only permitted to read its data and credit the account.
This means that to reassign ownership, you need to write an on-chain program that reassigns the ownership to attacker2_keypair
, deploy it to attacker_keypair
, and then send a transaction containing an instruction to attacker_keypair
.
Here are some example programs that perform the assign
on the AccountInfo
: https://github.com/solana-labs/solana/blob/85a2e599bbbf3d51f201167f921718e52c7ce59f/programs/bpf/rust/realloc/src/processor.rs#L54