Glamorous Plum Baboon
High
The lack of proper access control in the LiquidationLogic:executeLiquidationCall
function will cause an unauthorized liquidation for protocol users as malicious actors will call the function with malicious parameters to liquidate collateral without permission.
In LiquidationLogic.sol:executeLiquidationCall
function lacks an access control mechanism, which will cause a potential security vulnerability. Specifically, the function does not check whether the caller has the necessary permissions, allowing any address to invoke it and potentially execute malicious liquidation actions. This oversight could lead to unauthorized users performing liquidations, impacting the protocol's security.
For the Lack of Access Control vulnerability in the executeLiquidationCall
function, the following internal pre-conditions would need to be met in order for the attack path or vulnerability to be exploited:
- Any external actor needs to call
executeLiquidationCall
without proper authorization to setparams.user
to be any user. - Any external actor needs to call
executeLiquidationCall
to setparams.collateralAsset
andparams.debtAsset
to be valid collateral and debt assets within the system, without verifying if they have the permission to execute the liquidation. - Any external actor needs to call
executeLiquidationCall
to setparams.debtToCover
to be at most the amount that is actually owed (or even beyond the user's debt). - Any external actor needs to call
executeLiquidationCall
to bypass access control and modify liquidation parameters without authentication.
For the Lack of Access Control vulnerability in the executeLiquidationCall
function, the following external pre-conditions would need to be met in order for the attack path or vulnerability to be exploited:
- Any external user or malicious actor needs to have the ability to interact with the contract by calling the
executeLiquidationCall
function, without any restrictions such as authentication or authorization checks. - External entities (such as a malicious user or bot) need to be able to provide parameters like
params.user
,params.collateralAsset
, andparams.debtAsset
to execute a liquidation on a user without verifying their authority or permission to do so. - External interactions such as external price feeds or oracle updates may feed in manipulated or false data, enabling an attacker to influence liquidation calculations if no validation or access control is present on who can call the liquidation function.
- A malicious actor needs to exploit the ability to call the function with manipulated parameters, potentially triggering a liquidation event on an innocent user or themselves by bypassing proper authorization checks.
The attack path for the Lack of Access Control vulnerability in the executeLiquidationCall
function:
- Malicious User calls the
executeLiquidationCall
function on the smart contract, without any authentication or access control mechanisms restricting the caller. - The Malicious User provides manipulated parameters in the function call, such as their own address as
params.user
, and chooses arbitrary assets forparams.collateralAsset
andparams.debtAsset
, bypassing any validation checks that would normally prevent unauthorized access. - The smart contract executes the function with the parameters provided by the malicious actor, proceeding with the liquidation process, which includes calling internal functions like
_calculateAvailableCollateralToLiquidate
,_burnDebtTokens
, and transferring collateral and debt assets. - The malicious actor successfully triggers a liquidation of a user’s collateral, potentially liquidating assets they don’t own or performing an undesired liquidation event.
- The smart contract does not perform proper validation to ensure the caller is authorized, so the attack goes unchecked and could lead to significant financial loss for the victim or the protocol.
In this attack, the attacker exploits the lack of access control, bypassing any authorization checks, and is able to cause liquidations that should only be allowed for authorized roles.
The affected party (the protocol) suffers an approximate loss from the mishandling of collateral and debt due to unauthorized liquidation, leading to potential financial risks, manipulation of liquidation events, or loss of funds. The attacker gains the opportunity to profit from the unauthorized liquidation process
// Assuming the LiquidationLogic contract and related contracts are already deployed
// Exploiting the executeLiquidationCall function without permission contract MaliciousActor { address liquidationLogicAddress; // Address of the LiquidationLogic contract address targetUser; // The user whose assets are to be liquidated address collateralAsset; // Asset being used as collateral address debtAsset; // Debt the user owes uint256 debtToCover; // Amount of debt to liquidate bool receiveAToken; // Whether to receive aTokens or burn collateral
// Assume LiquidationCallParams structure is properly constructed
struct ExecuteLiquidationCallParams {
address user;
address collateralAsset;
address debtAsset;
uint256 debtToCover;
bool receiveAToken;
uint256 reservesCount;
uint8 userEModeCategory;
address priceOracle;
address priceOracleSentinel;
}
// Function to exploit the vulnerability
function exploitLiquidation() external {
// Constructing the malicious parameters
ExecuteLiquidationCallParams memory params = ExecuteLiquidationCallParams({
user: targetUser, // The victim's address
collateralAsset: collateralAsset, // The asset to be liquidated
debtAsset: debtAsset, // The debt asset to be liquidated
debtToCover: debtToCover, // The debt amount to be liquidated
receiveAToken: receiveAToken, // Whether to receive aTokens
reservesCount: 2, // Number of reserves, assuming 2 for this example
userEModeCategory: 0, // User's EMode category, set to 0 (default)
priceOracle: address(0), // Oracle for price, assuming a mock address
priceOracleSentinel: address(0) // Sentinel for price oracle checks
});
// Calling the executeLiquidationCall function on the LiquidationLogic contract
(bool success, ) = liquidationLogicAddress.call(
abi.encodeWithSignature("executeLiquidationCall(address,address,address,address,uint256,bool,uint256,uint8,address,address)",
params.user,
params.collateralAsset,
params.debtAsset,
params.debtToCover,
params.receiveAToken,
params.reservesCount,
params.userEModeCategory,
params.priceOracle,
params.priceOracleSentinel
));
// If the function executes, the malicious actor successfully triggered a liquidation
require(success, "Liquidation failed");
}
}
Results of the Attack: Target User: The collateral assets of the target user would be liquidated, resulting in a potential loss of their funds.
Attacker: If the attacker successfully triggers the liquidation, they may profit from the collateral liquidation (if allowed by the contract’s logic). Additionally, the attacker can manipulate liquidation parameters to their advantage.
Use OpenZeppelin’s AccessControl for Role-based Access If you require multiple roles to access different functions (e.g., admin, manager), AccessControl allows you to assign specific roles to addresses and restrict function execution accordingly
2, Use OpenZeppelin’s AccessControl or Ownable OpenZeppelin’s smart contract libraries are well-established and widely used. The AccessControl contract is a robust solution for managing roles, while the Ownable contract is a simpler solution for managing an owner of the contract.