Broken Authorization in Smart Contracts
Writing correct authorization controls is critical when developing smart contracts. Access control governs balance transfer, token mint, votes, and many other things.
A malicious actor exploiting authorization weaknesses may be able to affect the integrity and availability of the contract, even going so far as to conduct unauthorized withdrawals.
Function Default Visibility
Visibility specifiers determine whether a user can invoke a given function. However, when this specifier is not explicitly applied, the visibility defaults to public
, thus allowing unauthorized users to call the function.
This vulnerability has been exploited in a real-world attack in what is understood to be the first Parity multi-sig hack when an attacker was able to reset the ownership of the contract and drain $31M worth of Ether from three wallets.
Vulnerable Example
The following vulnerable contract is meant to transfer the balance to winners with a specific address only. Instead, it allows anyone to directly invoke the _sendWinnings()
function and withdraw the balance.
/*
* @source: https://github.com/sigp/solidity-security-blog#visibility
* @author: SigmaPrime
* Modified by Gerhard Wagner
*/
pragma solidity ^0.4.24;
contract HashForEther {
function withdrawWinnings() {
// Winner if the last 8 hex characters of the address are 0.
require(uint32(msg.sender) == 0);
_sendWinnings();
}
function _sendWinnings() {
msg.sender.transfer(this.balance);
}
}
Fixed Example
Explicitly set the internal
visibility specifier to protect the vulnerable function so that it can only be accessed internally, i.e., from within the current contract or contracts deriving from it.
function _sendWinnings() internal{
msg.sender.transfer(this.balance);
}
Prevention
Functions can be specified as being either external
, public
, internal
or private
. Developers must make an informed, conscious decision about which visibility type is appropriate for which function, taking into account the high stakes when opening a function to public
.
Incorrect Constructor Name
Incorrect Constructor Name vulnerabilities occur when a particular type of special function, known as a constructor, is named incorrectly or is left with the same name following a contract name change. If this disparity between contract name and constructor name occurs in development, the constructor will revert to having runtime, normal functions.
This vulnerability affected Solidity version before 0.4.22, while more recent versions require the constructor to be defined with the constructor
keyword, effectively mitigating this vulnerability.
The exploit of this vulnerability results in a publicly callable function and allows malicious actors to perform unintended or unauthorized actions.
This vulnerability has been exploited in a real-world attack against the Rubixi contract, resulting in the contract fee being stolen because anyone was able to become the owner of the contract… and someone did.
Vulnerable example
The following vulnerable contract designates the address which initializes it as the contract’s owner. This is a common pattern adopted to grant special privileges, such as the ability to withdraw contract funds.
/*
* @source: https://github.com/crytic/not-so-smart-contracts/blob/master/wrong_constructor_name/incorrect_constructor.sol
*/
pragma solidity ^0.4.15;
contract Missing{
address private owner;
modifier onlyowner {
require(msg.sender==owner);
_;
}
// The name of the constructor should be Missing
// Anyone can call the IamMissing once the contract is deployed
function IamMissing()
public
{
owner = msg.sender;
}
function withdraw()
public
onlyowner
{
owner.transfer(this.balance);
}
}
Fixed example
Developers should rewrite the contract to use the constructor
keyword.
constructor() public
{
owner = msg.sender;
}
Prevention
Use constructor
instead of a named constructor to prevent this issue.
References
Solidity - Visibility and Getters Solidity Security Blog - Default Visibilities Smart Contract Weakness Classification and Test Cases - Function Default Visibility DASP - Access Control Solidity - Creating Contracts Ethereum Blog - Thinking About Smart Contract Security