Secret Vault on Aptos

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

Any user can read the owner's secret vault

get_secret() does not enforce that the owner is calling it + any user can read the owner's secret vault

Description

  • get_secret() does not enforce that the owner is calling it.

  • Any user can read the owner's secret vault by passing caller with the owner's address.

#[view]
@> public fun get_secret (caller: address):String acquires Vault{
assert! (caller == @owner,NOT_OWNER);
let vault = borrow_global<Vault >(@owner);
vault.secret
}

Risk

Likelihood:

  • Occurs if any non owner user calls get_secret() and passes the owner's address in caller.

Impact:

  • Any user can read the owner's secret vault.

Proof of Concept

#[test(owner = @0xcc, user = @0x123)]
fun test_anyone_can_read_owner_secret(owner: &signer, user: &signer) acquires Vault{
use aptos_framework::account;
// Set up test environment
account::create_account_for_test(signer::address_of(owner));
account::create_account_for_test(signer::address_of(user));
let owner_secret = b"owner secret";
set_secret(owner, owner_secret);
let get_secret_result = get_secret(@owner);
assert!(get_secret_result == string::utf8(owner_secret), 4);
}

On line 12, any user can call get_secret() and pass in the address of the owner.

Run with

aptos move test --filter test_anyone_can_read_owner_secret

Output

INCLUDING DEPENDENCY AptosFramework
INCLUDING DEPENDENCY AptosStdlib
INCLUDING DEPENDENCY MoveStdlib
BUILDING aptos-secret-vault
Running Move unit tests
[ PASS ] 0x234::vault::test_anyone_can_read_owner_secret
Test result: OK. Total tests: 1; passed: 1; failed: 0
{
"Result": "Success"
}

Recommended Mitigation

Enforce that the originating transaction came from the owner by passing in a signer and checking that their address is the module owner.

- #[view]
- public fun get_secret (caller: address):String acquires Vault{
+ public(friend) fun get_secret (caller: &signer):String acquires Vault{
- assert! (caller == @owner,NOT_OWNER);
+ assert! (signer::address_of(caller) == @owner,NOT_OWNER);
let vault = borrow_global<Vault >(@owner);
vault.secret
}
Updates

Lead Judging Commences

bube Lead Judge 19 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.