Descripción general del desbordamiento de modelado

Principio de desbordamiento

Las variables enteras en las computadoras tienen límites superior e inferior. Si ocurre un fuera de límites en las operaciones aritméticas, es decir, más allá del rango máximo del tipo entero, el número será como la manecilla de la hora en el dial de 12 a 1, de un valor máximo a un valor mínimo O volver directamente a cero. Este tipo de situación fuera de límites es muy común en los programas de software tradicionales, pero si existen riesgos de seguridad depende del contexto del programa. Algunos desbordamientos son benignos (como tcp números de serie, etc.), o incluso introducidos deliberadamente (por ejemplo, como operación hash, etc.). 

La máquina virtual Ethereum (EVM) especifica un tipo de datos de tamaño fijo para enteros. Esto significa que una variable entera solo puede tener un cierto rango de números. Por ejemplo: un uint8 solo se puede almacenar en el rango [0,255]. Si intente almacenarlo de 256 a un uint8 se convertirá en 0. Si no presta atención, siempre y cuando no verifique la entrada del usuario y realice cálculos, los números excederán el rango permitido del tipo de datos en el que están almacenados .

Instancia de desbordamiento

Vender alto y cierre bajo (CVE-2018-11811)

Descripción del tipo: el administrador crea lagunas de desbordamiento al modificar los parámetros en el contrato, lo que hace que los usuarios no reciban ETH (o reciban una cantidad muy pequeña de ETH) después de que el usuario retira y transfiere el token, lo que provoca pérdidas económicas para el usuario. 

Ejemplo de vulnerabilidad: contrato de token de nodo de Internet (INT) 

Dirección del contrato:

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

Ubicación de la vulnerabilidad: L179

Peligro de vulnerabilidad: después de que el usuario retira la moneda, no puede obtener la cantidad correspondiente de ETH; 

Principio de vulnerabilidad: después de que sellPrice se modifica a un número grande cuidadosamente construido, el resultado de la cantidad sellPrice puede ser mayor que el valor máximo de la variable entera (uint256), se produce un desbordamiento de enteros y se convierte en un valor mínimo o incluso en cero. . En la semántica del programa, este valor se usa para calcular la cantidad de ETH que el usuario debe retirar y se verifica en L179, pero después de que el valor se desborda a un valor mínimo, puede escapar de la verificación de L179 y causar que el usuario para vender Solo se puede obtener una pequeña cantidad (o incluso ninguna) de ETH después del token.

Acumulación de subdesbordamiento (CVE-2018-11687)

Descripción del tipo: bajo ciertas condiciones, el administrador puede crear subdesbordamiento llamando a la función de emisión de monedas con fugas en el contrato, para lograr un aumento arbitrario en el saldo de su propia cuenta. 

Ejemplo de vulnerabilidad: contrato Bitcoin Red (BTCR) 

Dirección del contrato:

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

Ubicación de la vulnerabilidad: L45

Peligro de vulnerabilidad: el administrador ha realizado una operación normal de emisión de monedas a una dirección y, de hecho, ha modificado secretamente el saldo de su cuenta a un número muy grande; 

Principio de vulnerabilidad: la intención original de la función distribuirBTR () es que el administrador distribuya una cierta cantidad de tokens a la dirección especificada y reduzca el número de tokens correspondientes de su propia cuenta. La operación para reducir el saldo de la cuenta del administrador es saldos [propietario] - = 2000 108, y el resultado de la operación se almacenará en saldos [propietario], que es un tipo entero sin signo. Cuando el saldo del administrador en sí es inferior a 2000 * 108, el resultado del cálculo de la resta es un valor negativo, que se interpreta como un número entero sin signo, que es un valor máximo.

Acuñación a voluntad (CVE-2018-11812)

Descripción del tipo: cuando el administrador llama a la función de acuñación para agregar tokens a una determinada dirección, la vulnerabilidad de desbordamiento puede romper la limitación de la función de que la función solo puede aumentar los tokens y, de hecho, reducir la cantidad de tokens en la dirección, realizando así una manipulación arbitraria. (aumentar o reducir).

Ejemplo de vulnerabilidad: contrato PolyAi (AI) 

Dirección del contrato:
https://cn.etherscan.com/address/0x5121e348e897daef1eef23959ab290e5557cf274#code

Ubicación de la vulnerabilidad: L136

Riesgos de vulnerabilidad: los administradores pueden eludir las restricciones contractuales y alterar arbitrariamente el saldo de tokens de todas las direcciones; 

Principio de vulnerabilidad: al construir un mintedAmount extremadamente grande, el atacante provoca un desbordamiento de enteros de balanceOf [target] + mintedAmount, y el resultado del cálculo se convierte en un valor mínimo.

Exceso de acuñación (CVE-2018-11809)

Descripción del tipo: al construir parámetros maliciosos, el administrador puede eludir el límite superior de emisión de tokens especificado en el programa y lograr un exceso de monedas. El contrato Playkey (PKT) tiene tales vulnerabilidades, lo que hace que el límite de acuñación en el contrato sea en vano, emitiendo así cualquier número de tokens. Además, también encontramos que los dos contratos de Nexxus (NXX) y Fujinto (NTO) tienen vulnerabilidades similares. Estos dos contratos no tienen un límite de límite de monedas, pero el mismo método puede desbordar uno de los contratos para registrar la cantidad total de emitidos. monedas (totalSupply) Para que sea incompatible con el número total de monedas que circulan realmente en el mercado. 

Ejemplo de vulnerabilidad: Contract Playkey (PKT)

Dirección del contrato:
https://cn.etherscan.com/address/0x2604fa406be957e542beb89e6754fcde6815e83f#code

Ubicación de la vulnerabilidad: línea L241 marcada en rojo

Riesgo de vulnerabilidad: el administrador puede alterar el suministro total de monedas emitidas a cualquier valor y evitar el límite de acuñación en el contrato para emitir tokens en exceso; 

Principio de vulnerabilidad: _value se establece en un valor máximo cuidadosamente construido cuando se llama a la función, de modo que el resultado del cálculo de totalSupply + _value se desborda y es menor que tokenLimit, evitando así fácilmente la detección del límite de acuñación en la línea L237.

Sobreasignación (CVE-2018-11810)

Descripción del tipo: el administrador pasa por alto el límite máximo para emitir monedas a una sola dirección en el contrato creando un desbordamiento, y puede asignar tokens en exceso a la dirección especificada, haciendo que el límite para emitir una sola dirección sea inválido. 

Ejemplo de vulnerabilidad: contrato LGO (LGO) 

Dirección del contrato:
https://cn.etherscan.com/address/0x123ab195dd38b1b40510d467a6a359b201af056f#code

Ubicación de la vulnerabilidad: línea L286 marcada en rojo

Peligro de vulnerabilidad: el administrador omite el límite de emisión de una sola dirección especificado en el contrato y asigna tokens en exceso a la dirección especificada; 

Principio de vulnerabilidad: una cantidad _muy grande puede provocar un desbordamiento de enteros en la operación de suma aritmética holderAllocatedAmount + _amount para convertirse en un valor mínimo, evitando así la detección de L286.

Sobrecompra de monedas (CVE-2018-11809)

Descripción de la vulnerabilidad: si los compradores tienen suficiente ETH, pueden crear un desbordamiento enviando una gran cantidad de tokens, evitando así el límite de emisión de tokens de ICO y alcanzando tokens de compra excesiva. 

Ejemplo de vulnerabilidad: contrato EthLend (LEND) 

Dirección del contrato:
https://cn.etherscan.com/address/0x80fB784B7eD66730e8b1DBd9820aFD29931aab03#code

Ubicación de la vulnerabilidad: línea L236 marcada en rojo

Peligro de vulnerabilidad: la persona que llama pasó por alto el límite superior de la capacidad del token de ICO estipulado en el contrato y obtuvo monedas de sobrecompra; 

Principio de vulnerabilidad: un _newTokens muy grande puede provocar un desbordamiento de enteros en la operación de suma aritmética totalSoldTokens + newTokens para convertirse en un valor mínimo, evitando así la detección de L236.

Depuración de desbordamiento

Desbordamiento de resta

El código del caso es el siguiente:


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);
        }
    }
}

Como se muestra en la figura anterior, la función de la función de distribución en el contrato inteligente es transferir tokens de la cuenta del propietario a la lista de direcciones especificada, pero al restar la cuenta del saldo [propietario], la función SafeMath no se usa para números cálculos de la Operación, y no juzgó si el propietario del contrato tiene suficientes tokens, reste directamente al propietario en un ciclo, aquí si la cantidad total de tokens transferidos es mayor que el saldo de la cuenta del propietario, entonces el saldo [propietario] se desbordará. Se convierte en un valor muy grande, demostremos la operación en remix:

Compilar el contrato

Contrato de despliegue

Operación de subdesbordamiento

Llame a la función de distribución para pasar la matriz de direcciones: ["0x14723a09acff6d2a60dcdf7aa4aff308fddc160c", "0x4b0897b0513fdc7c541b6d9d7e929c4e5364d2db"], utilice el propietario para enviar tokens respectivamente a estas dos direcciones. Saldo del propietario antes de la ejecución:

Ejecute la función distribuir:

Los registros del registro de transacciones son los siguientes:

Saldo del propietario después de la ejecución:

Se puede ver en los resultados anteriores que después de que el propietario del contrato ejecuta la función de distribución, la operación de transferencia debe hacer que los tokens del propietario del contrato disminuyan, pero los tokens del propietario del contrato han aumentado en lugar de disminuir, por lo que el "subdesbordamiento" está aquí. Existe.

Desbordamiento de adición 

Caso: GEMCHAIN

Dirección del contrato:
https://cn.etherscan.com/address/0xfb340423dfac531b801d7586c98fe31e12a32f31#code

Como se muestra en la figura anterior, la función mintToken en el contrato inteligente se usa para emitir tokens adicionales, pero durante el proceso de emisión de tokens adicionales, la función SafeMath no se usa para operaciones numéricas para operaciones de adición, y require no se usa para verificar si se produce un desbordamiento. Por lo tanto, existe un riesgo de desbordamiento aquí. Si el propietario del contrato emite una cantidad mayor de MontedAmount al objetivo, se producirá el problema de desbordamiento. La demostración con remix es la siguiente:

Compilar el contrato

Contrato de despliegue

Operación de desbordamiento

La primera moneda: 

Primero, llamamos a la función mintToken para acuñar monedas en la dirección "0x14723a09acff6d2a60dcdf7aa4aff308fddc160c", el número de monedas acuñadas "0x80000000000000000000000000000000000000000000000000000000000000000000" es 2 elevado a 255.

Registro de transacciones:

El saldo de la dirección "0x14723a09acff6d2a60dcdf7aa4aff308fddc160c" después de la acuñación es:

Para que se desborde, también necesitamos acuñar monedas a la dirección "0x14723a09acff6d2a60dcdf7aa4aff308fddc160c". El número de monedas acuñadas sigue siendo: "0x80000000000000000000000000000000000000000000000000000000000000000000", que es 2 elevado a 255. + la potencia 255 de 2. Se supera el rango máximo de uint256. Ver la operación en detalle a continuación

La segunda moneda:

Registro de transacciones:

Consultar saldo:

De los resultados anteriores, podemos encontrar que efectivamente se ha producido un desbordamiento. Es concebible que si el propietario del contrato acuña monedas a una determinada dirección sin verificar el problema de desbordamiento, entonces si la dirección se desborda, la cantidad de tokens cambiará y habrá una disminución de vez en cuando (debido al desbordamiento) .

Caso especial

A veces encontrará que, aunque vemos el riesgo de desbordamiento de enteros en un contrato, por ejemplo, en la función de transferencia, require no se usa para la verificación de desbordamiento, y la función SafeMath no se usa para la protección de cálculo numérico, pero el contrato ya lo ha hecho. Se especifica la cantidad total de tokens (totalSupply) y no hay ningún token de menta (mintToken) para agregar tokens. Entonces el contrato es generalmente seguro y no hay desbordamiento de enteros. ¿Por qué dices eso? Porque nunca sucederá que la suma de dos valores exceda a uint256, pero en este caso, debe enfocarse en el problema de "desbordamiento de multiplicación" o "desbordamiento de resta" para averiguar si la auditoría es verdadera. No hay "entero "problema de desbordamiento". 

Defensa de desbordamiento

Entonces, ¿cómo evitar este problema de desbordamiento de enteros? La recomendación oficial es utilizar la biblioteca de funciones SafeMath proporcionada por OpenZepplin para operaciones numéricas. El uso de la función de biblioteca SafeMath puede verificar y prevenir problemas de desbordamiento de manera efectiva. El código fuente de la biblioteca de funciones SafeMath es el siguiente:

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;
    }
}

Ejemplos de contratos inteligentes que aplican funciones de SafeMath: 

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

Se puede ver que en el contrato inteligente anterior, la función SafeMath se usa para operaciones numéricas y require también se usa para proteger contra la verificación de desbordamiento, que generalmente es más segura.

Lista de desbordamiento

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

Resumen al final del artículo

La causa principal del problema de desbordamiento de enteros es que el desarrollador del contrato no consideró el problema de "desbordamiento de enteros" al desarrollar el contrato. Como auditores, debemos permanecer despiertos cuando vemos el contrato. Debemos adoptar el "desbordamiento de enteros" cuando vemos el contrato. Depurar y verificar "método para eliminar dudas, y en el proceso de auditoría, debe ser muy cuidadoso y cuidadoso. No suelte ningún problema posible, como los permisos y la lógica de los modificadores / modificadores. Oferta con problemas y así sucesivamente. 

Link de referencia

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

Este artículo se publicó por primera vez en la cuenta pública de WeChat "Seven Pointed Star Laboratory", preste atención para obtener contenido más interesante:

 

 

 

Supongo que te gusta

Origin blog.csdn.net/Fly_hps/article/details/114901467
Recomendado
Clasificación