The verifyMerkleProof function should correctly verify the validity of the provided Merkle proofs
If the proofs are valid, the function should return the storage root hash without reverting.
It should ensure that the account proof and storage proof are well-formed, consistent, and correspond to the expected values.
The edge case is the verifyMerkleProof function may accept invalid Merkle proofs that do not conform to the expected structure or integrity.
Users can manipulate the account proof or storage proof to bypass the verification checks and submit proofs that do not correspond to the actual state of the contract and this can lead to the acceptance of invalid state transitions, compromising the integrity of the Taiko protocol.
Impact
The acceptance of invalid proofs undermines the integrity and trustworthiness of the Taiko protocol, as the verified state may not reflect the true state of the contracts.
Users can submit invalid proofs, leading to the acceptance of incorrect state transitions and corrupting the overall state of the system.
Tools Used
Manual Review
Recommended Mitigation Steps
Implement rate limiting, transaction fees, spam detection, reputation-based prioritization, dynamic rate adjustment, and permissioning to mitigate excessive block proposals.
function verifyMerkleProof(
bytes32 _rootHash,
address _addr,
bytes32 _slot,
bytes32 _value,
bytes[] memory _accountProof,
bytes[] memory _storageProof
)
internal
pure
returns (bytes32 storageRoot_)
{
if (_accountProof.length != 0) {
// Enhanced validation of account proof
+ require(_accountProof.length >= 2, "Invalid account proof length");
+ require(_accountProof[0].length == 32, "Invalid account proof hash length");
// Add more validation checks based on the specific requirements
+ bytes memory rlpAccount =
+ SecureMerkleTrie.get(abi.encodePacked(_addr), _accountProof, _rootHash);
if (rlpAccount.length == 0) revert LTP_INVALID_ACCOUNT_PROOF();
RLPReader.RLPItem[] memory accountState = RLPReader.readList(rlpAccount);
storageRoot_ =
bytes32(RLPReader.readBytes(accountState[_ACCOUNT_FIELD_INDEX_STORAGE_HASH]));
} else {
storageRoot_ = _rootHash;
}
// Enhanced validation of storage proof
+ require(_storageProof.length >= 2, "Invalid storage proof length");
+ require(_storageProof[0].length == 32, "Invalid storage proof hash length");
// Add more validation checks based on the specific requirements
bool verified = SecureMerkleTrie.verifyInclusionProof(
bytes.concat(_slot), RLPWriter.writeUint(uint256(_value)), _storageProof, storageRoot_
);
if (!verified) revert LTP_INVALID_INCLUSION_PROOF();
}
Lines of code
https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibTrieProof.sol#L34-L66 https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibTrieProof.sol#L46-L58
Vulnerability details
Description
The
verifyMerkleProof
function in theLibTrieProof
library is responsible for verifying the validity of a Merkle proof in the Taiko protocol._rootHash
: The Merkle root hash of the state tree or the account tree._addr
: The address of the contract._slot
: The storage slot in the contract._value
: The expected value to be verified._accountProof
: The Merkle proof for the account._storageProof
: The Merkle proof for the storage slot.Code snippet: https://github.com/code-423n4/2024-03-taiko/blob/f58384f44dbf4c6535264a472322322705133b11/packages/protocol/contracts/libs/LibTrieProof.sol#L34-L66
The function does not perform adequate checks on the structure and integrity of the account proof (
_accountProof
) and storage proof (_storageProof
).users can craft specially designed Merkle proofs that exploit these validation gaps to bypass the verification process and submit invalid proofs.
In the following lines of code: #L46-L58
The
verifyMerkleProof
function should correctly verify the validity of the provided Merkle proofsIf the proofs are valid, the function should return the storage root hash without reverting.
It should ensure that the account proof and storage proof are well-formed, consistent, and correspond to the expected values.
The edge case is the
verifyMerkleProof
function may accept invalid Merkle proofs that do not conform to the expected structure or integrity.Users can manipulate the account proof or storage proof to bypass the verification checks and submit proofs that do not correspond to the actual state of the contract and this can lead to the acceptance of invalid state transitions, compromising the integrity of the Taiko protocol.
Impact
The acceptance of invalid proofs undermines the integrity and trustworthiness of the Taiko protocol, as the verified state may not reflect the true state of the contracts.
Users can submit invalid proofs, leading to the acceptance of incorrect state transitions and corrupting the overall state of the system.
Tools Used
Manual Review
Recommended Mitigation Steps
Implement rate limiting, transaction fees, spam detection, reputation-based prioritization, dynamic rate adjustment, and permissioning to mitigate excessive block proposals.
Assessed type
Invalid Validation