User could validate one action twice, using malleable hash
Summary
SignerValidator.sol validator use SignatureCheckerLib from solady package. This library dont check, that hash is malleable. Therefore, user could create second (different) signature(if he has one) and validata again his executed action. And get 2 rewards for 1 action.
SignerValidator contract calculate storage slot, usgin hash (as we know it could be different for the same values due to malleable attack) for storing bits (is incentive has validated or not).
function setOrThrow(IncentiveMap storage bitmap, bytes32 hash, uint256 incentive) internal {
bytes4 invalidSelector = BoostError.IncentiveToBig.selector;
bytes4 claimedSelector = BoostError.IncentiveClaimed.selector;
/// @solidity memory-safe-assembly
assembly {
if gt(incentive, 7) {
// if the incentive is larger the 7 (the highest bit index)
// we revert
mstore(0, invalidSelector)
mstore(4, incentive)
revert(0x00, 0x24)
}
mstore(0x20, bitmap.slot)
mstore(0x00, hash)
let storageSlot := keccak256(0x00, 0x40)
// toggle the value that was stored inline on stack with xor
let updatedStorageValue := xor(sload(storageSlot), shl(incentive, 1))
// isolate the toggled bit and see if it's been unset back to zero
let alreadySet := xor(1, shr(incentive, updatedStorageValue))
So, if user execute one action, get signature and call claimIncentive() twice with different hashes, he get 2 rewards.
Internal pre-conditions
Boost uses SignerValidator.sol as validator
External pre-conditions
No response
Attack Path
Creator create boost with validator SignerValidator.sol
User execute 1 action
User get signature
User call call claimIncentive() twice with different hashes
SovaSlava
Medium
User could validate one action twice, using malleable hash
Summary
SignerValidator.sol
validator use SignatureCheckerLib from solady package. This library dont check, that hash is malleable. Therefore, user could create second (different) signature(if he has one) and validata again his executed action. And get 2 rewards for 1 action.Root Cause
In 'SignerValidator.sol:6' uses library from solady package, which dont have protection from malleable attack. If you open code of this library, you can read aboit it in comment - https://github.com/Vectorized/solady/blob/362b2efd20f38aea7252b391e5e016633ff79641/src/utils/SignatureCheckerLib.sol#L23 https://github.com/sherlock-audit/2024-06-boost-aa-wallet/blob/main/boost-protocol/packages/evm/contracts/validators/SignerValidator.sol#L6
SignerValidator contract calculate storage slot, usgin hash (as we know it could be different for the same values due to malleable attack) for storing bits (is incentive has validated or not).
So, if user execute one action, get signature and call claimIncentive() twice with different hashes, he get 2 rewards.
Internal pre-conditions
Boost uses SignerValidator.sol as validator
External pre-conditions
No response
Attack Path
Creator create boost with validator SignerValidator.sol User execute 1 action User get signature User call call claimIncentive() twice with different hashes
Impact
User get 2 rewards for 1 action
PoC
No response
Mitigation
Use library from openzeppelin