Skip to content

Latest commit

 

History

History
62 lines (39 loc) · 4.4 KB

File metadata and controls

62 lines (39 loc) · 4.4 KB

Energetic Opaque Elephant

Medium

Unprotected Internal Function _internalBond in DecentralizedIndex Contract

Summary

The _internalBond function in the DecentralizedIndex contract lacks proper access control, allowing it to be called by any address. This bypasses the intended access restrictions and could lead to unauthorized manipulation of bond operations, potentially compromising the integrity of the protocol.

Root Cause

The _internalBond function is declared as internal but does not have any access control mechanisms (such as a modifier) to restrict its callers. While internal functions are not directly callable externally, they can be called by other functions within the same contract or by derived contracts. In this case, the bond function in the WeightedIndex contract is intended to be the sole caller of _internalBond. However, any contract could inherits from DecentralizedIndex and call _internalBond.

Why Internal Functions Need Access Control:

Even though an internal function cannot be called directly from outside the contract, it can be called by any contract that inherits from the contract where it's defined. This is the most common and significant risk. A malicious actor could create a contract that inherits from your contract and then call the internal function. Additionally, while less common, it's possible that other functions within your contract (or derived contracts) might accidentally or unintentionally call an internal function in a way that was not intended. Access control helps prevent these kinds of bugs. Finally, you might decide to change the visibility of a function from internal to public or external in the future. If you haven't implemented access control, this change could inadvertently expose the function to unintended callers. Therefore, it's a general security principle to restrict access to sensitive functionality as much as possible, even if you think it's "internal." Defense in depth is crucial. Assume that any function could be called in an unintended way and protect it accordingly.

Internal Pre-conditions

No response

External Pre-conditions

No response

Attack Path

A malicious actor could create a new contract that inherits from DecentralizedIndex. The malicious contract could then call the _internalBond function directly, bypassing the intended validation and logic within the bond function of the WeightedIndex contract. Depending on the logic within _internalBond, this could lead to unauthorized bond operations, manipulation of internal state, or other unintended consequences.

Impact

  • Unauthorized Bond Operations: Users might be able to trigger bond operations without going through the intended bond function's checks and balances, potentially allowing them to mint tokens or access other functionality they shouldn't have.
  • State Manipulation: If _internalBond updates critical state variables, unauthorized calls could corrupt the contract's data, leading to unpredictable behaviour or financial loss for users.
  • Circumvention of Fees/Restrictions: The bond function likely handles fee calculations or other restrictions. Direct calls to _internalBond could bypass these, allowing users to avoid fees or restrictions.

PoC

No response

Mitigation

Implement a modifier, such as onlyBond, in the DecentralizedIndex contract to restrict access to the _internalBond function. The modifier should check if the direct caller is the WeightedIndex contract or any contract that inherits from it.

modifier onlyBond() {
    address caller = msg.sender;
    require(caller == address(this) || // Called directly by this contract
            (caller == address(weightedIndex)) || // Called by WeightedIndex
            (caller == address(podLarge)), // Called by TestWeightedIndex
            "Only bond functions can call this.");
    _;
}

function _internalBond() internal onlyBond {
    // ... your _internalBond logic ...
}

This ensures that only the intended bond function (or other allowed functions) can call _internalBond, preventing unauthorized access and maintaining the integrity of the bond process. It's crucial to apply this modifier to all internal functions that should only be accessible through specific external functions.