Solidity Security By Example #01: Integer Underflow
Originally published in Valix Consulting’s Medium.
Smart contract security is one of the biggest impediments toward the mass adoption of the blockchain. For this reason, we are proud to present this series of articles regarding Solidity smart contract security to educate and improve the knowledge in this domain to the public.
Integer underflow, one of the most commonly known issues in the smart contract security field, will be explained in this article. Enjoy reading. 😊
You can find all related source code at 👉 https://github.com/serial-coder/solidity-security-by-example/tree/main/01_integer_underflow.
Disclaimer:
The smart contracts in this article are used to demonstrate vulnerability issues only. Some contracts are vulnerable, some are simplified for minimal, some contain malicious code. Hence, do not use the source code in this article in your production.
Nonetheless, feel free to contact Valix Consulting for your smart contract consulting and auditing services. 🕵
Table of Contents
The Dependency
The following is the ReentrancyGuard
abstract contract required by the InsecureEtherVault
and FixedEtherVault
contracts.
|
|
The ReentrancyGuard
contains the noReentrant
modifier that is used to prevent reentrancy attacks. We will explain the reentrancy attacks in the upcoming articles of this series. Stay tuned! 🤳
The Vulnerability
The below shows the InsecureEtherVault
contract, providing a simple vault in which users can deposit Ethers, withdraw Ethers, and check their balances.
Surely, the InsecureEtherVault
contract is vulnerable to integer underflow. But, could you ever capture the issue? 👀
|
|
The integer underflow occurs in lines 14 and 16 in the withdraw
function.
Imagine if the attacker’s balance is 5, but he passes the _amount
of 10 into the function. What would happen?
Figure 1 pictures how the underflow occurs. In the case of 5 - 10, the computed value would circle forward to 2²⁵⁶ - 5, as you can see.
Gotcha! 🙀 That is why the require(balance — _amount >= 0, “Insufficient balance”);
statement would be bypassed since the balance — _amount
would result in the underflow, making the computed value ≥ 0.
Consequently, the attacker can drain all Ethers locked in the contract with a single withdrawal transaction.
Possible Attacks
-
Attacker balance manipulation
-
Draining all Ethers in a single transaction
The Attack
|
|
The above code is the Attack
contract in which an attacker can drain all Ethers locked in the InsecureEtherVault
contract by invoking the Attack.attack()
function.
Intriguingly 👽, the attacker can steal all locked Ethers without depositing any penny to the InsecureEtherVault
contract. The attack was made in favor of the underflow issue.
Actually, the attacker does not need to deploy any contract to attack the
InsecureEtherVault
because they can directly callInsecureEtherVault.withdraw(InsecureEtherVault.getEtherBalance())
right away.
The result of the attack is shown in Figure 2. As you can see, the attacker stole 45 Ethers (10 and 35 Ethers were deposited by User1 and User2, respectively) from the InsecureEtherVault
contract. 🤑
Regarding the result of the underflow, the Attack
contract’s balance recorded by the InsecureEtherVault
contract was manipulated enormously. 😈
The Solutions
There are two preventive solutions to fix the underflow issue. 👨🔧
-
Applying the standard OpenZeppelin’s SafeMath library for arithmetic operations (for the Solidity below v0.8)
-
Using the Solidity v0.8+ (Solidity v0.8+ came up with the built-in underflow and overflow detection mechanism on arithmetic operations)
|
|
The FixedEtherVault
contract above is the fixed version of the InsecureEtherVault
. The contract applies the SafeMath library to prevent any underflow or overflow issues in lines 28, 33, and 35.
Nevertheless, the library used in the code is just a simplified version for brevity’s sake. Please refer to this link for the latest OpenZeppelin’s SafeMath library.
Summary
In this article, you have learned the integer underflow vulnerability in the smart contract, how an attacker exploits it, and how to fix it. We hope you find this article useful. And, see you in the following articles.
Again, you can find all related source code at 👉 https://github.com/serial-coder/solidity-security-by-example/tree/main/01_integer_underflow.
Author Details
Phuwanai Thummavet (serial-coder), Lead Blockchain Security Auditor and Consultant | Blockchain Architect and Developer.
See the author’s profile.
About Valix Consulting
Valix Consulting is a blockchain and smart contract security firm offering a wide range of cybersecurity consulting services. Our specialists, combined with technical expertise with industry knowledge and support staff, strive to deliver consistently superior quality services.
For any business inquiries, please get in touch with us via Twitter, Facebook, or info@valix.io.
Originally published in Valix Consulting’s Medium.