DeFiHardhatFoundry
250,000 USDC
View results
Submission Details
Severity: high
Invalid

Blueprint Data Manipulation in LibTractor.sol

Summary

The LibTractor.sol library in the Beanstalk project contains a security vulnerability related to blueprint data validation. Attackers can forge blueprint data or signatures to execute unauthorized actions, causing severe consequences for the system.

Vulnerability Details

The LibTractor.sol library uses the Requisition structure to store information about a blueprint, including the blueprint data (data), blueprint hash (blueprintHash), and signature (signature). However, the integrity verification of the blueprint data is only based on comparing the blueprintHash with the hash recalculated from the blueprint.data.

modifier verifyRequisition(LibTractor.Requisition calldata requisition) {
bytes32 blueprintHash = LibTractor._getBlueprintHash(requisition.blueprint);
require(blueprintHash == requisition.blueprintHash, "TractorFacet: invalid hash");
// ... (signature verification)
}

Attackers can exploit this vulnerability by:

  • Creating a Requisition with malicious blueprint.data.

  • Calculating the corresponding blueprintHash for the malicious blueprint.data.

  • Forging a signature to bypass the signature check in the verifyRequisition modifier.

  • Calling the tractor function in TractorFacet.sol with the forged Requisition.

The contract will execute the calls in the malicious blueprint.data, which can cause unauthorized actions such as transferring tokens, changing contract state, or performing other attacks.

Impact

Attackers can transfer user or contract tokens to their own accounts.

Tools Used

Manual Code Review

Recommendations

Use EIP-712 signatures: Instead of just checking the hash of the blueprint data, use EIP-712 signatures to verify the integrity of the data and ensure that the data is not tampered with.

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
// ... other imports ...
library LibTractor {
// ... (Other LibTractor definitions) ...
// Add data type for EIP-712
bytes32 public constant REQUISITION_TYPEHASH = keccak256(
"Requisition(Blueprint blueprint,bytes32 blueprintHash)"
);
struct Requisition {
Blueprint blueprint;
bytes32 blueprintHash;
}
function _getRequisitionHash(Requisition calldata requisition)
internal
view
returns (bytes32)
{
return _hashTypedDataV4(
keccak256(
abi.encode(
REQUISITION_TYPEHASH,
_getBlueprintHash(requisition.blueprint),
requisition.blueprintHash
)
)
);
}
function _verifyRequisition(Requisition calldata requisition) internal view {
bytes32 blueprintHash = _getBlueprintHash(requisition.blueprint);
// Check the hash of the blueprint
require(blueprintHash == requisition.blueprintHash, "TractorFacet: invalid blueprint hash");
// Check EIP-712 signature
bytes32 digest = _getRequisitionHash(requisition);
address recoveredSigner = ECDSA.recover(digest, requisition.signature);
require(recoveredSigner == requisition.blueprint.publisher, "TractorFacet: invalid signature");
}
// ... (Other LibTractor functions) ...
}

Usage in TractorFacet.sol

modifier verifyRequisition(LibTractor.Requisition calldata requisition) {
LibTractor._verifyRequisition(requisition); // Use the new function
_;
}
Updates

Lead Judging Commences

inallhonesty Lead Judge about 1 year ago
Submission Judgement Published
Invalidated
Reason: Incorrect statement

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.