Part 2

Zaros
PerpetualsDEXFoundrySolidity
70,000 USDC
View results
Submission Details
Severity: high
Invalid

Lack of Validation in Branch Addition Function

Summary

The addBranch function in the proxy pattern implementation lacks validation to ensure that only trusted or authorized contracts are added as branches. This vulnerability allows an attacker to add a malicious contract as a branch, potentially leading to unauthorized actions and data manipulation within the system.

Vulnerability Details

The addBranch function is responsible for adding a new branch contract and mapping specific function selectors to it. However, it does not validate whether the provided branch address is a trusted or authorized contract. This oversight breaks the security guarantee of controlled contract delegation, as it permits an attacker to add a malicious contract as a branch.

By mapping specific function selectors to this malicious contract, the attacker can execute arbitrary code when these selectors are invoked, leading to unauthorized actions, data manipulation, or other malicious behaviors within the system.

The affected code in the RootUpgrade library responsible for adding branch contracts without validating trustworthiness:

function addBranch(Data storage self, address branch, bytes4[] memory selectors) internal {
// slither-disable-next-line unused-return
self.branches.add(branch);
uint256 cachedSelectorsLength = selectors.length;
for (uint256 i; i < cachedSelectorsLength; i++) {
bytes4 selector = selectors[i];
if (selector == bytes4(0)) {
revert Errors.SelectorIsZero();
}
if (self.selectorToBranch[selector] != address(0)) {
revert Errors.FunctionAlreadyExists(selector);
}
self.selectorToBranch[selector] = branch;
// slither-disable-next-line unused-return
self.branchSelectors[branch].add(selector);
}
}

Impact

High – This vulnerability allows an attacker to execute arbitrary code within the system by adding a malicious branch. The attacker can control critical functions, manipulate data, and potentially cause financial loss, undermining the integrity and security of the protocol.

Likelihood

High – The function is accessible within the upgrade process, and in the absence of internal validation, any attacker with sufficient access to the upgrade mechanism can exploit this vulnerability to inject a malicious branch.

POC

An attacker with access to the addBranch function can add a malicious contract as a branch by providing its address and mapping specific function selectors to it. When these selectors are invoked, they execute the attacker's contract code, leading to unauthorized actions and data manipulation.

// Malicious contract deployed by attacker
contract MaliciousBranch {
function execute() external {
// Malicious code execution
}
}
// Attacker's script
contract Exploit {
function exploit(address proxyAddress) external {
// Assume the attacker has gained access to call addBranch
address maliciousBranch = address(new MaliciousBranch());
bytes4[] memory selectors = new bytes4[](1);
selectors[0] = MaliciousBranch(maliciousBranch).execute.selector;
// Call the addBranch function with the malicious branch
Proxy(proxyAddress).addBranch(maliciousBranch, selectors);
}
}

Recommendations

Ensure only trusted or authorized contracts can be added as branches. This can be achieved by maintaining a whitelist of authorized contracts or implementing a role-based access control mechanism.

function addBranch(Data storage self, address branch, bytes4[] memory selectors) internal {
require(isAuthorizedBranch(branch), "Unauthorized branch");
// slither-disable-next-line unused-return
self.branches.add(branch);
uint256 cachedSelectorsLength = selectors.length;
for (uint256 i; i < cachedSelectorsLength; i++) {
bytes4 selector = selectors[i];
if (selector == bytes4(0)) {
revert Errors.SelectorIsZero();
}
if (self.selectorToBranch[selector] != address(0)) {
revert Errors.FunctionAlreadyExists(selector);
}
self.selectorToBranch[selector] = branch;
// slither-disable-next-line unused-return
self.branchSelectors[branch].add(selector);
}
}
function isAuthorizedBranch(address branch) internal view returns (bool) {
// Implement logic to check if the branch is authorized, e.g., by consulting a whitelist
return authorizedBranches[branch];
}
Updates

Lead Judging Commences

inallhonesty Lead Judge 4 months ago
Submission Judgement Published
Invalidated
Reason: Out of scope

Support

FAQs

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