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

Unrestricted Access to inherit() Function

Summary

The inherit() function allows any address to call it after the 90-day inactivity period, potentially leading to unauthorized ownership transfer. If only one beneficiary exists, an attacker can call inherit() first and take ownership of the contract, bypassing the rightful heir. This completely breaks the inheritance mechanism, allowing malicious actors to seize control of the contract and its assets.

Vulnerability Details

The inherit() function does not check if msg.sender is a valid beneficiary before assigning ownership. This means that anyone can call the function after 90 days and take control of the contract.

If there is only one beneficiary, the function blindly assigns ownership to the first caller, allowing an attacker to steal the entire estate.

If there are multiple beneficiaries, the function sets isInherited = true without verifying the caller, which, while less severe, still allows unauthorized users to initiate inheritance improperly.

Vulnerable Code:

function inherit() external {
if (block.timestamp < getDeadline()) {
revert InactivityPeriodNotLongEnough();
}
if (beneficiaries.length == 1) {
owner = msg.sender; // No check if msg.sender is the actual beneficiary
_setDeadline();
} else if (beneficiaries.length > 1) {
isInherited = true; // No check on msg.sender, allowing unauthorized calls
} else {
revert InvalidBeneficiaries();
}
}

Impact

The flaw in inherit() allows anyone to claim ownership after 90 days, bypassing the intended beneficiaries. If there is only one beneficiary, an attacker can steal the entire estate, resulting in permanent fund loss. Even with multiple beneficiaries, unauthorized users could disrupt the inheritance process. If the original owner later regains access, they may find their contract and assets already stolen, making recovery impossible.

Proof of Concept (PoC)

  1. Deploy the InheritanceManager contract.

  2. Add one beneficiary (e.g., 0xBeneficiary).

  3. Wait 90 days for the inactivity period to expire.

  4. Attacker (e.g., 0xAttacker) calls inherit() before the rightful beneficiary.

  5. The contract assigns ownership to 0xAttacker, not 0xBeneficiary.

  6. Rightful heir loses control, and the attacker gains access to all assets.

Tools Used

  • Manual review

Recommendations

Modify the inherit() function to verify that msg.sender is a listed beneficiary before allowing inheritance:

function inherit() external {
if (block.timestamp < getDeadline()) {
revert InactivityPeriodNotLongEnough();
}
if (beneficiaries.length == 0) {
revert InvalidBeneficiaries();
}
// Ensure only a beneficiary can call this function
bool isBeneficiary = false;
for (uint256 i = 0; i < beneficiaries.length; i++) {
if (msg.sender == beneficiaries[i]) {
isBeneficiary = true;
break;
}
}
require(isBeneficiary, "Not a beneficiary");
if (beneficiaries.length == 1) {
owner = msg.sender;
_setDeadline();
} else {
isInherited = true;
}
}
Updates

Lead Judging Commences

0xtimefliez Lead Judge 6 months ago
Submission Judgement Published
Validated
Assigned finding tags:

Inherit depends on msg.sender so anyone can claim the contract

Support

FAQs

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