Admin Key Misuse
id: LS50H
title: Admin Key Misuse
baseSeverity: H
category: access-control
language: solidity
blockchain: [ethereum]
impact: Unauthorized or excessive control over contract state or user funds
status: draft
complexity: low
attack_vector: internal
mitigation_difficulty: medium
versions: [">0.6.0", "<0.8.25"]
cwe: CWE-732
swc: SWC-136
๐ Description
- Admin Key Misuse occurs when privileged roles (e.g., owner, admin, governance) retain excessive control over critical protocol functions such as withdrawals, upgrades, minting, or configuration changes. This introduces a centralized trust risk, which:
- Violates user expectations in decentralized systems
- Allows the key holder to drain or manipulate funds
- Enables censorship, malicious upgrades, or protocol misuse
- This vulnerability is especially dangerous if the admin key is a single externally owned account (EOA), which can be compromised or abused with no recourse.
๐จ Vulnerable Code
contract Vault {
address public admin;
function withdrawAll() external {
require(msg.sender == admin, "Not admin");
payable(admin).transfer(address(this).balance); // โ admin can drain all funds at will
}
}
๐งช Exploit Scenario
Step-by-step exploit process:
- A DeFi project deploys a vault where admin retains full withdrawal rights.
- Users deposit millions in ETH assuming the system is decentralized.
- The admin key is either:
- Controlled by the core team
- Compromised via phishing or key leakage
- The key holder calls withdrawAll() and drains all funds to their wallet.
- Users have no on-chain recourse, and the protocol is effectively rug-pulled.
Assumptions:
- The admin is an EOA or has unverified custody practices.
- There are no time delays, multisigs, or DAO votes for sensitive actions.
- The function in question has real impact (e.g., fund flow, logic override, token minting).
โ Fixed Code
contract Vault is Ownable {
address public treasury;
constructor(address _treasury) {
treasury = _treasury;
}
function withdrawAll() external onlyOwner {
require(block.timestamp > withdrawUnlockTime, "Withdraw locked");
payable(treasury).transfer(address(this).balance);
}
}
๐งญ Contextual Severity
- context: "Default"
severity: H
reasoning: "Assumes any centralized admin control over critical assets."
- context: "Deployed DAO-governed protocol with timelock"
severity: M
reasoning: "Risk reduced by on-chain governance and execution delay."
- context: "Privately deployed contract for team operations"
severity: L
reasoning: "Impact limited to internal funds; users not affected."
๐ก๏ธ Prevention
Primary Defenses
- Use multisig wallets (e.g., Gnosis Safe) for any admin functionality
- Implement timelocks for high-impact functions (e.g., withdrawals, upgrades)
Additional Safeguards
- Transition to DAO-controlled governance modules post-deployment
- Emit events for admin-triggered actions and track via monitoring
- Limit privileges to specific contracts rather than global admin rights
Detection Methods
- Slither: unchecked-admin, unrestricted-withdrawal
- Manual review of onlyOwner, admin, governance roles across all functions
- Symbolic analysis of control flows affecting transfer, upgradeTo, mint, etc.
๐ฐ๏ธ Historical Exploits
- Name: Meerkat Finance Admin Key Exploit
- Date: 2021-03
- Loss: ~$31,000,000
- Post-mortem: Link to post-mortem
- Name: bZx Admin Key Compromise
- Date: 2021-11
- Loss: ~$55,000,000
- Post-mortem: Link to post-mortem
๐ Further Reading
- SWC-136: Unrestricted Critical Variable Update
- CWE-732: Incorrect Permission Assignment
- OpenZeppelin โ Ownable Best Practices
โ Vulnerability Report Template
id: LS50H
title: Admin Key Misuse
severity: H
score:
impact: 5
exploitability: 3
reachability: 4
complexity: 1
detectability: 4
finalScore: 4.1
๐ Justifications & Analysis
- Impact: Full fund loss or protocol control can be abused or stolen if admin misuses power.
- Exploitability: Requires admin key compromise or intentional abuseโrealistic and common.
- Reachability: Any contract with unrestricted admin access to core functions is affected.
- Complexity: Very lowโadmin simply triggers sensitive functions.
- Detectability: Static analysis and manual audit catch this easily, but detection โ prevention.