The NativeMetaTransaction::executeMetaTransaction allows a user to specify any address as the userAddress instead of using msg.sender.
https://github.com/Cyfrin/2024-11-one-world/blob/1e872c7ab393c380010a507398d4b4caca1ae32b/contracts/meta-transaction/NativeMetaTransaction.sol#L33-L39
Also, ecrecover is used to verify metatransaction signer's signature instead of openzepplin ECDSA library.
https://github.com/Cyfrin/2024-11-one-world/blob/1e872c7ab393c380010a507398d4b4caca1ae32b/contracts/meta-transaction/NativeMetaTransaction.sol#L100
ecrecover is vulnerable to signature malleability attack in which users' signatures can be replayed to sign data and the signatures will be valid.
Combining these two vulnerabilities, a malicious user can call some functions in the contract using any desired address. An attacker can exploit these vulnerabilities to steal funds from the EXTERNAL_CALLER role and DoS him/her in the process each time the EXTERNAL_CALLER role tries to use MembershipFactory::callExternalContract function to transfer a whitelisted ERC20 token. The details of the attack path is described in the attack path section below.
The NativeMetaTransaction::executeMetaTransaction allows a user to specify any address as the userAddress instead of using msg.sender.
https://github.com/Cyfrin/2024-11-one-world/blob/1e872c7ab393c380010a507398d4b4caca1ae32b/contracts/meta-transaction/NativeMetaTransaction.sol#L33-L39
s parameter in a signature has two valid points on the elliptic curve - one below n/2 and the other above n/2. An attacker using one of the valid (v, r and s combination) signatures can calculate the other valid signature on the other side of n/2.
This allows a malicious user to call some functions in the contract using any desired address.
Funds get stolen from the EXTERNAL_CALLER role wallet.
The EXTERNAL_CALLER ERC20 transfer transaction with MembershipFactory::callExternalContract will also fail causing denial of service.
An attacker use the previous signature of an EXTERNAL_CALLER role wallet to calculate another valid signature;
the attacker observes the EXTERNAL_CALLER role wallet approval transaction for the MembershipFactory::callExternalContract function to spend a whitelisted currency on its behalf in the mempool;
the attacker can quickly create a dao with the specified whitelisted currency and DAOConfig::tiers::price = EXTERNAL_CALLER wallet approved token value.
After the approval is executed, the attacker can now front-run the main EXTERNAL_CALLER transaction by sending a transaction to MembershipFactory::joinDAO through NativeMetaTransaction::executeMetaTransaction with EXTERNAL_CALLER wallet address as the userAddress and its replayed signature;
MembershipFactory::_msgSender will return EXTERNAL_CALLER address as the caller address (or _msgSender) and 80% of the approved tokens will be successfully transferred from the EXTERNAL_CALLER wallet to the attacker's specified daoMembershipAddress;
Since the MembershipERC1155 contract does not have ERC20 withdrawal function the stolen tokens will remain stuck in the contract.
The EXTERNAL_CALLER main transaction to use MembershipFactory::callExternalContract for a transfer will fail as the approval allowance has already being spent by the attacker.
Manual review
Refactor the NativeMetaTransaction::executeMetaTransaction as shown below and use Openzepplin ECDSA library instead of ecrecover to verify signatures.
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.