--- title: "Access Control(访问控制)" type: concept tags: [blockchain, security, smart-contract, access-control] sources: [blockchain-security-auditor] last_updated: 2026-05-30 --- ## Aliases - Access Control - 访问控制 / 权限控制 ## Definition 访问控制(Access Control)定义谁可以执行合约中的哪些操作。访问控制缺陷是智能合约最常见的高危漏洞类别之一,错误的权限配置可直接导致资金被盗或协议被永久阻塞。 ## Key Vulnerability Classes ### 1. Missing Access Modifier(缺失访问修饰符) ```solidity // VULNERABLE: withdraw() 没有访问控制,任何人都能调用 function withdraw() external { uint256 amount = balances[msg.sender]; (bool success,) = msg.sender.call{value: amount}(""); require(success); balances[msg.sender] = 0; } ``` ### 2. Wrong Access Modifier(错误的访问修饰符) ```solidity // VULNERABLE: 应该是 onlyOwner,但误写成 external // 导致任何人都能调用紧急停止 function emergencyStop() external { paused = true; } ``` ### 3. Unprotected initialization(未保护的初始化) ```solidity // VULNERABLE: initialize() 没有 initializer 修饰符 // 攻击者可抢先调用,劫持合约 function initialize(address _owner) external { owner = _owner; } ``` ### 4. Proxy Storage Collision(代理存储冲突) 升级型代理合约中,新实现版本的存储布局与旧版本不兼容,导致状态变量被覆盖: ```solidity // Implementation V1 uint256 public totalValue; // slot 0 // Implementation V2 — 新增变量导致 slot 0 被覆盖 address public newAdmin; // slot 0 ← 覆盖了 totalValue! uint256 public totalValue; // slot 1 ``` ### 5. Role Renunciation Hijack(角色放弃劫持) 允许 admin 放弃角色后无人能恢复,导致协议永久不可升级。 ## Audit Checklist - [ ] 所有特权函数都有显式访问修饰符 - [ ] Admin 角色不能自我授予(需要多签或时间锁) - [ ] `initialize()` 只能调用一次(initializer 修饰符) - [ ] 实现合约构造函数中有 `_disableInitializers()` - [ ] `_authorizeUpgrade()` 受 owner/多签/时间锁保护 - [ ] 存储布局在版本间兼容(无 slot 碰撞) - [ ] 无 `delegatecall` 到用户可控地址 ## Severity Classification - **Critical**:缺失关键特权函数的访问控制,可直接导致资金损失 - **High**:条件性权限提升(需要特定状态),或协议可被 admin 永久阻塞 - **Medium**:缺失非关键函数的访问控制 - **Low**:缺少事件日志、代码规范问题 ## Related Concepts - [[Reentrancy]]:缺失访问控制会加剧重入攻击影响 - [[Proxy-Upgrade]]:代理升级模式引入额外访问控制风险 - [[OpenZeppelin]] 的 AccessControl 库是标准安全实现