Detailed explanation of Ethereum smart contract vulnerabilities: integer overflow attack
01*01 buffer overflow incident
On April 22, 2018, hackers launched an attack on the BEC smart contract.
BEC tokens were sold on the market, BEC immediately depreciated sharply, and the value was almost zero, and the market fell apart in an instant.On April 25, 2018, the SMT project party discovered an abnormality in its transaction, and hackers used its function loopholes to create
65,133,050,195,990,400,000,000,000,000,000,000,000,000,000,000,000,000,000,000 + 50,659,039,041,325,800,000,000,000,000,000,000,000,000,000,000,000,000,000,000
SMT coins. Huobi Pro immediately suspended the deposit and withdrawal business of all currencies.
On December 27, 2018, the Ethereum smart contract Fountain (FNT) had an integer overflow vulnerability. Hackers used its function vulnerability to create SMT coins.
02*02 Introduction to integer overflow
Integer overflow principle
Since the underlying computer is binary, any decimal number will be encoded to binary. Overflow discards the most significant bit, resulting in an incorrect value.
For example, the maximum value of an eight-bit unsigned integer type is 255, which translates to binary is 1111 1111; when one is added again, all current 1s will become 0 and carry up. But since the positions that can be accommodated by this integer type are all 1, and then carry up, the highest bit will be discarded, so the binary becomes 0000 0000
Note: For signed integer types, the highest binary bit represents positive and negative. So this type of positive overflow will become a negative number instead of zero.
Integer overflow example (general programming language)
Integer overflow vulnerabilities caused by arithmetic are common in programming languages, and their types include the following three:
- Addition overflow
- Subtraction overflow
- Multiplication overflow
Let’s take the Kotlin programming language running on the JVM as an example to test for integer overflow.
The program will print out -9223372036854775808, which is actually not preventing integer overflow during compilation, because the compiler allowed the overflowed code to compile.
Of course, there are also programming languages that strictly check for integer overflow at compile time. For example, the most popular Rust programming language in the blockchain world:
Compile this code and you will get compilation errors.
Great, this effectively prevents compile-time overflow problems. So what if it’s runtime? Let’s try to read user input:
Run cargo r, type: 255, and get panic:
thread ‘main’ panicked at ‘attempt to add with overflow’
It can be seen that in debug mode, the overflow will panic directly, that is: the program crashes and stops working.
Run cargo r — release, enter: 255, print:
In summary, we have reached a conclusion: even if a program language that strictly checks for overflow during compile time, there will still be integer overflow problems. Integer overflow is like a curse, it will always appear at intervals and cannot be eliminated once and for all.
Integer Overflow in Smart Contracts (Solidity Language)
In the blockchain world, in the Solidity language of smart contracts, for versions below 0.8.0, there is also an integer overflow problem.
As with general-purpose programming languages, let’s first see if an overflow occurs during compile time:
The actual test, the test function will directly generate a compilation error. Let’s look at the runtime again:
According to actual measurement, the program will overflow during runtime. We recommend using the SafeMath library to solve the vulnerability overflow:
For versions above Solidity 0.8.0, the official has fixed this problem. So how exactly is it fixed? What happens to prevent overflow when it is about to overflow?
According to actual measurement, Solidity version 0.8 or higher will directly revert when overflow occurs during runtime.
It turned out that the way to fix it was to not allow overflow. int256 is large enough, as long as it is guaranteed that it cannot be used by hackers to create revenue out of thin air, we will succeed.
0x03 Vulnerable contracts, attack methods
Taking the BEC contract as an example, the contract address is:0xC5d105E63711398aF9bbff092d4B6769C82F793D
The address on etherscan is:https://etherscan.io/address/0xc5d105e63711398af9bbff092d4b6769c82f793d#code
The contract code with overflow vulnerability is as follows:
The contract version at that time was ^0.4.16, which was less than version 0.8, and the SafeMath library was not used, so there was an integer overflow problem.
The hacker passed in a very large value (here 2**255), and overflowed upward through multiplication, so that the amount (the total number of coins to be transferred) overflowed and became a small number or 0 (here it became 0) , thus bypassing the check code of balances[msg.sender] >= amount, making the malicious transfer of huge _value amount successful.
Malicious transfer records of actual attacks:https://etherscan.io/tx/0xad89ff16fd1ebe3a0a7cf4ed282302c06626c1af33221ebe0d3a470aba4a660f
In the case of Solidity version 0.8 and below, and the SafeMath library is not used: hackers often use overflow to construct a minimum/maximum value, thereby bypassing certain checks and making huge malicious transfers successful.
Of course, contract vulnerabilities are not limited to integer overflows. In addition to the developers themselves raising the awareness of security development, it is also very necessary to find a professional security team to conduct a comprehensive audit of the contract.