Beginner FriendlyGameFi
100 EXP
View results
Submission Details
Severity: high
Valid

Owner Check Bypass Through Direct Function Call

Owner Check Bypass Through Direct Function Call

Description

  • The Pizza Drop contract allows the owner to register users for APT rewards through the register_pizza_lover function.

  • The register_pizza_lover function calls a separate entry function get_random_slice. The get_random_slice function lacks owner checks, allowing any user to bypass authorization and register themselves directly by calling this function.

// Owner-protected registration function
entry fun register_pizza_lover(owner: &signer, user: address) acquires ModuleData, State {
@> assert!(signer::address_of(owner) == state.owner, E_NOT_OWNER);
get_random_slice(user); // Calls internal function
}
// But this function is directly callable without checks
entry fun get_random_slice(user_addr: address) acquires ModuleData, State {
let state = borrow_global_mut<State>(get_resource_address());
let random_val = randomness::u64_range(0, 5);
let random_amount = 100 + random_val;
table::add(&mut state.users_claimed_amount, user_addr, random_amount);
}

Risk

Likelihood:

  • The get_random_slice function is directly callable through Aptos CLI or explorer

  • Users can easily discover this bypass through blockchain explorers

Impact:

  • Any user can register themselves for rewards

  • Owner's control over registration is completely bypassed

  • Airdrop access control is effectively non-existent

  • Attack can claim rewards without authorization on as many addresses as he wants

Proof of Concept

The following CLI commands demonstrate how any user can bypass the owner check and register themselves:

# Directly call get_random_slice to register ourselves
$ aptos move run --function-id 0x323e6...23f5f::airdrop::get_random_slice --profile user --args address:0x123
Transaction submitted: https://explorer.aptoslabs.com/txn/0xea24cb8b3b5f3fbbe5ed8703e4eacc6b96d8ea1ad1e91bc655de22a218e97b4b?network=devnet
{
"Result": {
"success": true,
"vm_status": "Executed successfully"
}
}
# Verify we're registered by checking our reward amount
$ aptos move view --function-id 0x323e6...23f5f::airdrop::get_claimed_amount --args address:0x123
{
"Result": [
"300"
]
}

This shows that:

  1. Attacker can directly call get_random_slice through CLI or on the explorer

  2. The transaction succeeds without any owner checks

  3. Registered addresses are allocated a claim amount

  4. The owner's authorization is completely bypassed

An attack can do this as many times as he would like, spamming the airdrop contract and effectively draining it.

Recommended Mitigation

Make get_random_slice private to prevent direct external calls and remove #[randomness] attribute from this function:

- #[randomness]
- entry fun get_random_slice(user_addr: address) acquires ModuleData, State {
+ fun get_random_slice(user_addr: address) acquires ModuleData, State {
let state = borrow_global_mut<State>(get_resource_address());
let random_val = randomness::u64_range(0, 5);
let random_amount = 100 + random_val;
table::add(&mut state.users_claimed_amount, user_addr, random_amount);
}

Add #[randomness] attribute to the register_pizza_lover function, as this is the entry function exposing the randomness.

+ #[randomness]
public entry fun register_pizza_lover(owner: &signer, user: address) acquires ModuleData, State {

This ensures that:

  1. Only the module's own functions can call get_random_slice

  2. All registration must go through the owner-checked register_pizza_lover

  3. External calls through CLI or contracts are prevented

  4. The owner's control over registration is properly enforced

Most importantly, this fix ensures that the airdrop's access control cannot be bypassed, maintaining the owner's exclusive ability to register users for rewards.

Updates

Appeal created

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

Anyone can call `get_random_slice` function

Support

FAQs

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