Ownership Vulnerabilities
id: LS04H
title: Ownership Vulnerabilities
baseSeverity: H
category: access-control
language: solidity
blockchain: [ethereum]
impact: Unauthorized or irreversible control of privileged operations
status: draft
complexity: medium
attack_vector: external
mitigation_difficulty: easy
versions: [">=0.4.0", "<0.8.21"]
cwe: CWE-284
swc: SWC-100
π Description
- Ownership vulnerabilities occur when smart contracts fail to properly assign, restrict, or validate the
owneror admin role, allowing unauthorized actors to gain privileged accessβor leaving no one able to manage the contract. - This commonly includes uninitialized
owner, wrong visibility on admin-only functions, or incorrect use of access control modifiers.
π¨ Vulnerable Code
contract InsecureAdmin {
address public owner;
function initialize() public {
owner = msg.sender; // β Can be called by anyone at any time
}
function mint(address to, uint256 amount) public {
require(msg.sender == owner, "Not authorized");
// mint logic
}
}
π§ͺ Exploit Scenario
Step-by-step exploit process:
- Contract is deployed but initialize() is never called.
- Attacker calls initialize() and sets themselves as owner.
- Now attacker can call mint() and create unlimited tokens.
- If immutable storage is used or token is deployed via a factory, this may not be reversible.
Assumptions:
- Improper handling during ownership transfers can result in unauthorized access or permanent loss of control over the contract.
- Ownership is not properly set during deployment or proxy usage.
β Fixed Code
import "@openzeppelin/contracts/access/Ownable.sol";
contract SecureAdmin is Ownable {
constructor() {
transferOwnership(msg.sender);
}
function mint(address to, uint256 amount) external onlyOwner {
// mint logic
}
}
π§ Contextual Severity
- context: "Default"
severity: H
reasoning: "Ownership flaws often result in full control loss over critical protocol operations."
- context: "DAO with on-chain governance overrides"
severity: M
reasoning: "Governance can limit damage if owner functions are rarely used or gated by proposals."
- context: "Private contracts or low-value assets"
severity: L
reasoning: "Low impact if the contract is not externally accessible or not holding valuable assets."
π‘οΈ Prevention
Primary Defenses
- Use OpenZeppelinβs Ownable or AccessControl to enforce proper admin rights.
- Always assign owner at deployment (constructor) or restrict initialize() with onlyOnce.
- In upgradeable contracts, use initializer modifier from OpenZeppelin Upgradeable Libraries.
Additional Safeguards
- Include emergency admin rotation or multisig-based recovery.
- Log ownership transfers with OwnershipTransferred events.
- Do not expose transferOwnership() without onlyOwner.
Detection Methods
- Slither: uninitialized-state, missing-authorization, unprotected-function.
- Manual review of all external/public functions that modify critical state.
- Use Hardhat plugins like hardhat-upgrades for initializer checks.
π°οΈ Historical Exploits
- Name: Bancor Network Hack
- Date: 2018-07-09
- Loss: Approximately $13.5 million
- Post-mortem: Link to post-mortem
π Further Reading
- SWC-115: Authorization Through tx.origin β SWC Registry
- OpenZeppelin Docs: AccessControl
- SigmaPrime: Solidity Security Pitfalls
β Vulnerability Report
id: LS04H
title: Ownership Vulnerabilities
severity: H
score:
impact: 5
exploitability: 4
reachability: 4
complexity: 2
detectability: 3
finalScore: 4.2
π Justifications & Analysis
- Impact: Full takeover of protocol via unrestricted ownership assignment or transfer.
- Exploitability: Common if initialize logic is public or not called.
- Reachability: Most admin logic is accessible in public methods.
- Complexity: Basic scripting or contract call can trigger exploit.
- Detectability: Easily found with tools like Slither, but often missed in upgradeable contracts.