Default Visibility Exploit Generator
Overview
The default visibility exploit generator validates findings from the default_visibility, visibility_missing, and related detectors by classifying the type of exposed function from the finding description and producing a targeted proof of concept. This vulnerability is specific to Solidity contracts compiled with versions before 0.5.0, where omitting a visibility modifier caused functions to default to public.
Two canonical historical exploits demonstrate the impact. Rubixi (2016): A contract was renamed from DynamicPyramid to Rubixi but the constructor function name was not updated, causing the old DynamicPyramid() function to become a regular public function (Solidity 0.4.x used function-name constructors). Attackers called it to claim ownership. The Parity Wallet hack also involved an initialization function (initWallet) that was publicly accessible due to insufficient visibility controls.
Note: Exploit generation in Sigvex is for vulnerability validation purposes only.
Attack Scenario
Public initialization function:
- A contract has
function initOwner(address _owner)without a visibility modifier. - In Solidity 0.4.x, this defaults to
public. Attackers can call it at any time. - The attacker calls
initOwner(attackerAddress)after deployment. - Owner is now the attacker. All
onlyOwnerfunctions are accessible to the attacker. - The attacker calls
withdraw()to drain all contract ETH.
Public destructor:
- A contract has
function kill()without visibility, defaulting topublic. - Any address can call
kill(), triggeringselfdestruct(owner). - The contract is permanently destroyed and its bytecode erased.
Public admin functions:
- Internal helper functions (
resetOwner(),updateThreshold()) lack visibility. - Attackers call them directly to modify critical state variables.
- Combined with ownership reset and threshold manipulation, full fund extraction follows.
Exploit Mechanics
The generator classifies the vulnerability type from the finding description:
| Description contains | Vulnerability type | Severity |
|---|---|---|
| “constructor”, “init”, “setup” | public_initialization |
Critical: anyone can become owner |
| “owner”, “admin” | public_admin_function |
High: unauthorized admin access |
| “destroy”, “kill” | public_destructor |
Critical: anyone can destroy contract |
| (other) | unspecified_visibility |
Medium: unintended exposure |
Evidence collected includes: original owner address, attacker address, contract balance, and vulnerability type. Estimated gas: 40,000.
The PoC covers four vulnerability patterns using Solidity 0.4.24 syntax:
// VULNERABLE (Solidity 0.4.x): No visibility — defaults to PUBLIC
contract VulnerableInit {
address owner;
function initOwner(address _owner) { // Public by default!
owner = _owner;
}
}
// EXPLOIT
contract InitExploit {
function attack(VulnerableInit target) public {
target.initOwner(address(this)); // Become owner
target.withdraw(); // Drain funds
}
}
Remediation
- Detector: Default Visibility Detector
- Remediation Guide: Default Visibility Remediation
The simplest fix is to upgrade to Solidity 0.5.0 or later, which requires explicit visibility on all functions at compile time:
// Solidity 0.5.0+: Compiler requires explicit visibility
// This fails to compile without a modifier:
// function initOwner(address _owner) { ... } // Error!
// Correct: Use internal for setup-only functions
function _initOwner(address _owner) internal { ... }
// Correct: Use private for helpers
function _computeReward() private returns (uint256) { ... }
// Correct: Use external for public API
function withdraw() external onlyOwner { ... }
For contracts that cannot be recompiled, deploy a new contract with corrected visibility. For upgradeable proxies, update the implementation to Solidity 0.5.0+.
Naming conventions help prevent accidental exposure: prefix _internal or __private functions accordingly, and use static analysis tools (a static-analysis tool, a linter) that flag missing visibility.
References
- SWC-100: Function Default Visibility
- SWC-118: Incorrect Constructor Name
- Solidity 0.5.0 Breaking Changes
- Rubixi Contract Exploit (2016)