The functions withdrawInheritedFunds
and buyOutEstateNFT
do not use the nonReentrant modifier, leaving them open to potential reentrancy attacks. In these functions, funds (ETH or ERC20 tokens) are sent to each beneficiary in a loop. If any beneficiary is a malicious contract with a fallback function that reenters the withdrawal function, the attacker can manipulate the flow and potentially drain more funds than intended. This vulnerability poses both technical and economic risks.
Affected Functions:
withdrawInheritedFunds(address _asset)
buyOutEstateNFT(uint256 _nftID)
Issue:
Neither function is protected by a reentrancy guard (nonReentrant modifier). When transferring funds in a loop, if a beneficiary is a malicious contract, its fallback function may trigger a reentrant call back into the withdrawal function. This reentrancy may allow the malicious beneficiary to receive funds repeatedly before the state is updated, resulting in an over-withdrawal.
The core issue is the omission of the nonReentrant modifier on functions that perform external calls in a loop. Without this guard, there is no protection against recursive calls triggered by a malicious beneficiary’s fallback function during fund transfers.
Impact:
An attacker controlling a beneficiary contract can reenter the withdrawal function, disrupting the intended sequential distribution of funds.
Foundry:
Below is a Foundry test that demonstrates the vulnerability. The test deploys a malicious beneficiary contract with a fallback function that reenters the withdrawInheritedFunds
function. The output provided simulates the vulnerability being exploited.
When running the above test with Foundry (forge test --match-path test/ReentrancyTest.t.sol
), the output :
Immediate Fix:
Add the nonReentrant
modifier to both withdrawInheritedFunds
and buyOutEstateNFT
functions. For example:
The contest is live. Earn rewards by submitting a finding.
This is your time to appeal against judgements on your submissions.
Appeals are being carefully reviewed by our judges.