Overview of shaping overflow

Overflow principle

Integer variables in computers have upper and lower bounds. If an out-of-bounds occurs in arithmetic operations, that is, beyond the maximum range of the integer type, the number will be like the hour hand on the dial from 12 to 1, from a maximum value to a minimum value Or directly return to zero. This kind of out-of-bounds situation is very common in traditional software programs, but whether there are security risks depends on the program context. Some overflows are benign (such as tcp serial numbers, etc.), or even deliberately introduced (for example, as hash operation, etc.). 

The Ethereum Virtual Machine (EVM) specifies a fixed-size data type for integers. This means that an integer variable can only have a certain range of numbers. For example: a uint8 can only be stored in the range [0,255]. If you try to store it 256 to a uint8 will become 0. If you don't pay attention, as long as you do not check the user input and perform calculations, the numbers will exceed the allowable range of the data type in which they are stored.

Overflow example

Sell ​​high and close low (CVE-2018-11811)

Type description: The administrator creates overflow loopholes by modifying the parameters in the contract, resulting in users not receiving ETH (or receiving a very small amount of ETH) after the user withdraws and transfers the token, causing economic losses to the user. 

Vulnerability example: contract Internet Node Token (INT) 

Contract address:

https://cn.etherscan.com/address/0x0b76544f6c413a555f309bf76260d1e02377c02a#code

Vulnerability location: L179

Vulnerability hazard: After the user withdraws the coin, he cannot get the corresponding amount of ETH; 

Vulnerability principle: After the sellPrice is modified to a carefully constructed large number, the result of the amount sellPrice may be greater than the maximum value of the integer variable (uint256), an integer overflow occurs, and it becomes a minimum value or even zero. In the program semantics, this value is used to calculate the amount of ETH that the user should withdraw, and it is verified at L179, but after the value is overflowed to a minimum value, it can escape the verification of L179 and cause the user to sell Only a small amount (or even no) ETH can be obtained after the token.

Underflow accumulation (CVE-2018-11687)

Type description: Under certain conditions, the administrator can create underflow by calling the leaky coin issuing function in the contract, so as to achieve an arbitrary increase in the balance of his own account. 

Vulnerability example: Bitcoin Red (BTCR) contract 

Contract address:

https://cn.etherscan.com/address/0x6aac8cb9861e42bf8259f5abdc6ae3ae89909e11#code

Vulnerability location: L45

Vulnerability hazard: The administrator has performed a normal operation of issuing coins to an address, and has actually secretly modified the balance of his account to a very large number; 

Vulnerability principle: The original intention of the distributeBTR() function is that the administrator distributes a certain amount of tokens to the specified address and reduces the number of corresponding tokens from its own account. The operation to reduce the balance of the administrator account is balances[owner] -= 2000 108, and the result of the operation will be stored in balances[owner], which is an unsigned integer type. When the administrator's balance itself is less than 2000 * 108, the subtraction calculation result is a negative value, which is interpreted as an unsigned integer, which is a maximum value.

Minting at will (CVE-2018-11812)

Type description: When the administrator calls the minting function to add tokens to a certain address, the overflow vulnerability can break through the function’s limitation that the function can only increase tokens, and actually reduce the number of tokens in the address, thereby realizing arbitrary tampering (increase) of any account balance Or reduce).

Vulnerability example: contract PolyAi (AI) 

Contract address:
https://cn.etherscan.com/address/0x5121e348e897daef1eef23959ab290e5557cf274#code

Vulnerability location: L136

Vulnerability hazards: administrators can bypass contract restrictions and arbitrarily tamper with the token balance of all addresses; 

Vulnerability principle: By constructing an extremely large mintedAmount, the attacker causes an integer overflow of balanceOf[target] + mintedAmount, and the calculation result becomes a minimum value.

Excess minting (CVE-2018-11809)

Type description: By constructing malicious parameters, the administrator can bypass the upper limit of token issuance specified in the program and achieve excess coinage. The contract Playkey (PKT) has such vulnerabilities, causing the minting limit in the contract to be in vain, thus issuing any number of tokens. In addition, we also found that Nexxus (NXX) and Fujinto (NTO) two contracts have similar vulnerabilities. These two contracts do not have a coin cap limit, but the same method can overflow one of the contracts to record the total amount of issued coins (totalSupply ) To make it inconsistent with the total number of coins actually circulating in the market. 

Vulnerability example: Contract Playkey (PKT)

Contract address:
https://cn.etherscan.com/address/0x2604fa406be957e542beb89e6754fcde6815e83f#code

Vulnerability location: line L241 marked in red

Vulnerability hazard: the administrator can tamper with the total supply of issued coins to any value, and bypass the minting limit in the contract to issue tokens in excess; 

Vulnerability principle: _value is set to a carefully constructed maximum value when the function is called, so that the calculation result of totalSupply + _value overflows and is less than tokenLimit, thus easily bypassing the minting limit detection in line L237.

Overallocation (CVE-2018-11810)

Type description: The administrator bypasses the maximum limit for issuing coins to a single address in the contract by creating overflow, and can allocate excess tokens to the specified address, making the limit for issuing a single address invalid. 

Vulnerability example: contract LGO (LGO) 

Contract address:
https://cn.etherscan.com/address/0x123ab195dd38b1b40510d467a6a359b201af056f#code

Vulnerability location: line L286 marked in red

Vulnerability hazard: The administrator bypasses the single address issuance limit specified in the contract and allocates excess tokens to the specified address; 

Vulnerability principle: A very large _amount can cause an integer overflow in the arithmetic addition operation holdersAllocatedAmount + _amount to become a minimum value, thereby bypassing the detection of L286.

Over-purchase of coins (CVE-2018-11809)

Vulnerability description: If buyers have enough ETH, they can create overflow by sending a large number of tokens, thereby bypassing the ICO token issuance limit and reaching over-purchase tokens. 

Vulnerability example: contract EthLend (LEND) 

Contract address:
https://cn.etherscan.com/address/0x80fB784B7eD66730e8b1DBd9820aFD29931aab03#code

Vulnerability location: line L236 marked in red

Vulnerability hazard: The caller bypassed the upper limit of the ICO token capacity stipulated in the contract and obtained over-purchase coins; 

Vulnerability principle: a very large _newTokens can cause an integer overflow in the arithmetic addition operation totalSoldTokens + newTokens to become a minimum value, thereby bypassing the detection of L236.

Overflow debugging

Subtraction overflow

The case code is as follows:


pragma solidity ^0.4.22;

contract TokenExample {
    address public owner;
    mapping(address => uint256) public balances;
    mapping(address =>mapping(address =>uint256)) public allowed;
    
    event Transfer(address _from,address _to,uint256 _value);
    
    modifier onlyOwner{
        require(msg.sender == owner);
        _;
    }
    
    constructor() public {
        owner = msg.sender;
        balances[owner] = 2000*10**8;
    }
    
    function distribute(address[] addresses) public onlyOwner{
        for(uint i=0;i < addresses.length;i++){
            balances[owner] -= 2000*10**8;
            balances[addresses[i]] +=2000*10**8;
            emit Transfer(owner,addresses[i],2000*10**8);
        }
    }
}

As shown in the figure above, the function of the distribute function in the smart contract is to transfer tokens from the owner account to the specified address list, but when subtracting the account of balance[owner], the SafeMath function is not used for numerical calculations Operation, and did not judge whether the owner of the contract has enough tokens, directly subtract the owner in a cycle, here if the total amount of tokens transferred out is greater than the owner’s account balance, then balance[owner] will underflow. It becomes a very large value, let's demonstrate the operation in remix:

Compile the contract

Deployment contract

Underflow operation

Call the distribute function to pass in the address array: ["0x14723a09acff6d2a60dcdf7aa4aff308fddc160c","0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"], use the owner to send tokens to these two addresses respectively. Owner's balance before execution:

Execute the distribute function:

The transaction log records are as follows:

Owner's balance after execution:

It can be seen from the above results that after the owner of the contract executes the distribute function, the transfer operation should make the contract owner's tokens decrease, but the contract owner's tokens have increased instead of decreasing, so the "underflow" is here. Does exist.

Addition overflow 

Case: GEMCHAIN

Contract address:
https://cn.etherscan.com/address/0xfb340423dfac531b801d7586c98fe31e12a32f31#code

As shown in the above figure, the mintToken function in the smart contract is used to issue additional tokens, but in the process of additional token issuance, the SafeMath function is not used for numerical operations for addition operations, and require is not used to check whether overflow occurs. Therefore, there is an overflow risk here. If the owner of the contract issues a larger amount of mintedAmount to the target, the overflow problem will occur. The demo using remix is ​​as follows:

Compile the contract

Deployment contract

Overflow operation

The first coin: 

First, we call the mintToken function to mint coins at the address "0x14723a09acff6d2a60dcdf7aa4aff308fddc160c", the number of minted coins "0x8000000000000000000000000000000000000000000000000000000000000000" is 2 to the 255th power

Transaction log:

The balance of the address "0x14723a09acff6d2a60dcdf7aa4aff308fddc160c" after minting is:

In order to make it overflow, we also need to mint coins to the address "0x14723a09acff6d2a60dcdf7aa4aff308fddc160c". The number of minted coins is still: "0x8000000000000000000000000000000000000000000000000000000000000000", which is 2 to the 255th power. The purpose is to overflow the 255th power of 2 + the 255th power of 2. The maximum range of uint256 is exceeded. See the operation in detail below

The second coin:

Transaction log:

Check balance:

From the above results, we can find that overflow has indeed occurred! It is conceivable that if the owner of the contract mints coins to a certain address without verifying the overflow problem, then if the address overflows, the number of tokens will change, and there will be a decrease from time to time (because of overflow) .

Special case

Sometimes you will find that although we see the risk of integer overflow in a contract, for example, in the transfer function, require is not used for overflow checking, and the SafeMath function is not used for numerical calculation protection, but the contract has already The total amount of tokens (totalSupply) is specified, and there is no mint token (mintToken) to add tokens. Then the contract is generally safe and there is no integer overflow. Why do you say that? Because it will never happen that the sum of two values ​​exceeds uint256, but in this case, you should focus on the problem of "multiplication overflow" or "subtraction underflow" to find out whether the audit is true There is no "integer overflow" problem. 

Overflow defense

So how to prevent this integer overflow problem? The official recommendation is to use the SafeMath function library provided by OpenZepplin for numerical operations. Using the SafeMath library function can effectively check and prevent overflow problems. The SafeMath function library source code is as follows:

https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/math/SignedSafeMath.sol


// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/**
 * @title SignedSafeMath
 * @dev Signed math operations that revert on error.
 */
library SignedSafeMath {
    /**
     * @dev Returns the multiplication of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(int256 a, int256 b) internal pure returns (int256) {
        return a * b;
    }

    /**
     * @dev Returns the integer division of two signed integers. Reverts on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator.
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(int256 a, int256 b) internal pure returns (int256) {
        return a / b;
    }

    /**
     * @dev Returns the subtraction of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(int256 a, int256 b) internal pure returns (int256) {
        return a - b;
    }

    /**
     * @dev Returns the addition of two signed integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(int256 a, int256 b) internal pure returns (int256) {
        return a + b;
    }
}

Examples of smart contracts that apply SafeMath functions: 

https://etherscan.io/address/0xB8c77482e45F1F44dE1745F52C74426C631bDD52#code

It can be seen that in the above smart contract, the SafeMath function is used for numerical operations, and require is also used to protect against overflow verification, which is generally safer.

Overflow list

https://github.com/sec-bit/awesome-buggy-erc20-tokens/blob/59e167f74a8d7cf48eadf25a75c65e461450aea0/raw/totalsupply-overflow.txt

https://github.com/peckshield/vuln_disclosure/blob/7a1e99695945220f4bbc10100f72fa7ecb9e0a79/tradeTrap.csv

https://github.com/BlockChainsSecurity/EtherTokens/blob/6e1e0952bc2a4b213cdc6db6ba7a855d9c776242/GEMCHAIN/mint%20integer%20overflow.md

https://github.com/dwfault/AirTokens/blob/aff7102887096a6c8d384820835818f445f3401f/Link_Platform__LNK_/mint%20integer%20overflow.md

Summary at the end of the article

The root cause of the integer overflow problem is that the developer of the contract did not consider the "integer overflow" problem when developing the contract. As auditors, we should stay awake when we see the contract. We should adopt "integer overflow" when we see the contract. Debug and verify” method to eliminate doubts, and in the audit process, you must be very careful and careful. Don’t let go of any possible problems, such as the permissions and logic of modifiers/modifiers. Deal with problems and so on. 

Reference link

https://www.anquanke.com/post/id/147913

This article was first published on the WeChat public account "Seven Pointed Star Laboratory", please pay attention to get more exciting content:

 

 

 

Guess you like

Origin blog.csdn.net/Fly_hps/article/details/114901467