Уязвимость внешнего вызова в смарт-контрактах
Уязвимость внешнего вызова в смарт-контрактах

Внешний вызов:

При разработке смарт-контрактов вызов ненадежных внешних контрактов является распространенной угрозой безопасности. Это связано с тем, что когда вы вызываете функцию другого контракта, вы фактически выполняете код этого контракта, что может привести к неожиданному поведению, включая вредоносное поведение. Ниже я приведу пример, чтобы проиллюстрировать этот риск и предложить соответствующие стратегии его смягчения.

Пример уязвимого контракта

Предположим, у нас есть смарт-контракт, который позволяет пользователям выполнять определенную задачу, например погашение токенов, путем вызова внешнего контракта. Здесь мы предполагаем, что внешний контракт предоставляет функцию TransferFrom для перевода токенов с одного аккаунта на другой.

Язык кода:javascript
копировать
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ExternalCallVulnerable {
    address public externalTokenContract;

    constructor(address _externalTokenContract) {
        externalTokenContract = _externalTokenContract;
    }

    function exchangeTokens(uint256 amount) public {
        IERC20(externalTokenContract).transferFrom(msg.sender, address(this), amount);
    }
}

В этом контракте функция ExchangeTokens вызывает функцию TransferFrom внешнего контракта. Однако здесь есть потенциальная проблема: внешний контракт может содержать вредоносный код, либо его логика может не соответствовать ожиданиям, что приведет к потере средств или другим нежелательным последствиям.

Демонстрация атаки

Злоумышленник может развернуть вредоносный контракт токена ERC20 и передать этот адрес контракта нашему контракту. Вредоносный контракт может содержать дополнительную логику в функции TransferFrom, например, вызов других функций нашего контракта при передаче токенов или выполнение каких-либо несанкционированных операций.

Язык кода:javascript
копировать
// Пример вредоносного контракта
contract MaliciousToken is IERC20 {
    function transferFrom(address, address, uint256) public override returns (bool) {
        // Обычная логика передачи токена...

        // Выполнять дополнительные вредоносные действия, такие как вызов другой функции в контракте.
        ExternalCallVulnerable(0x...).someUnsafeFunction();

        return true;
    }
}

Когда пользователь пытается обменять токены во вредоносном контракте через наш контракт, будет вызвана функция TransferFrom вредоносного контракта для выполнения вредоносных операций.

решение

Чтобы снизить риски, вызванные внешними вызовами, мы можем принять следующие меры:

  • 1、проверка код: выполнить тщательную проверку внешнего контракта, прежде чем разрешить его вызов. кода, убедитесь, что его логика соответствует ожиданиям и не содержит вредоносного кода.
  • 2、Механизм белого список: Разрешено вызывать только список проверенных, доверенных контрактов. Таким образом, даже если появится новый вредоносный контракт, его нельзя будет вызвать через наш контракт.
  • 3、Используйте безопасные библиотеки: воспользуйтесь преимуществами стандартизированного интерфейса в библиотеках безопасности, таких как OpenZeppelin, в которых обычно уже учтены проблемы безопасности и совместимости.
  • 4、Ограничить глубину Вызов: избегайте повторного вызова других внешних контрактов при вызове внешних контрактов, чтобы предотвратить атаки, вызванные рекурсивными вызовами.
  • 5、Мониторинг событий и обработка Исключения: при вызове внешнего контракта отслеживайте возвращаемое значение и исключение, чтобы убедиться, что вызов успешен и не происходит аномального поведения.

Вот пример улучшенного контракта, реализующего механизм белого списка:

Язык кода:javascript
копировать
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IERC20 {
    function transferFrom(address, address, uint256) external returns (bool);
}

contract SafeExternalCall {
    mapping(address => bool) public approvedContracts;
    address public externalTokenContract;

    constructor(address _externalTokenContract) {
        approveContract(_externalTokenContract);
        externalTokenContract = _externalTokenContract;
    }

    function exchangeTokens(uint256 amount) public {
        require(approvedContracts[externalTokenContract], "Contract not approved");
        IERC20(externalTokenContract).transferFrom(msg.sender, address(this), amount);
    }

    function approveContract(address contractAddress) public {
        approvedContracts[contractAddress] = true;
    }
}

При разработке смарт-контрактов вызов ненадежных внешних контрактов является распространенной угрозой безопасности. Это связано с тем, что когда вы вызываете функцию другого контракта, вы фактически выполняете код этого контракта, что может привести к неожиданному поведению, включая вредоносное поведение. Ниже я приведу пример, чтобы проиллюстрировать этот риск и предложить соответствующие стратегии его смягчения.

Пример уязвимого контракта

Предположим, у нас есть смарт-контракт,Он позволяет пользователям выполнять определенные задачи, вызывая внешний контракт.,Например, обмен токенов. здесь,Мы предполагаем, что внешний контракт обеспечиваетtransferFromфункция,Используется для перевода токенов с одного аккаунта на другой.

Язык кода:javascript
копировать
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

contract ExternalCallVulnerable {
    address public externalTokenContract;

    constructor(address _externalTokenContract) {
        externalTokenContract = _externalTokenContract;
    }

    function exchangeTokens(uint256 amount) public {
        IERC20(externalTokenContract).transferFrom(msg.sender, address(this), amount);
    }
}

в этом контракте,exchangeTokensфункция Называется внешний контрактtransferFromфункция。Однако,Здесь есть потенциальная проблема: внешние контракты могут содержать вредоносный код.,Или логика может не соответствовать ожиданиям,приводящие к потере средств или другим неблагоприятным последствиям.

Демонстрация атаки

Злоумышленник может развернуть вредоносный контракт токена ERC20.,и передать этот адрес контракта в наш контракт。Вредоносные контракты могут бытьtransferFromфункция Содержит дополнительную логику в,Например, при передаче токенов,Вызов другой функции в нашем контракте,Или выполнить какие-то несанкционированные операции.

Язык кода:javascript
копировать
// Пример вредоносного контракта
contract MaliciousToken is IERC20 {
    function transferFrom(address, address, uint256) public override returns (bool) {
        // Обычная логика передачи токена...

        // Выполнять дополнительные вредоносные действия, такие как вызов другой функции в контракте.
        ExternalCallVulnerable(0x...).someUnsafeFunction();

        return true;
    }
}

Когда пользователь пытается обменять токены из вредоносного контракта через наш контракт,вредоносный контрактtransferFromфункциябудет вызван,Выполнять вредоносные действия.

Улучшения безопасности

Чтобы снизить риски, вызванные внешними вызовами, мы можем принять следующие меры:

  1. проверка кода:прежде чем разрешить вызовы внешних контрактов,Дайте ему тщательную проверку кода, убедитесь, что его логика соответствует ожиданиям и не содержит вредоносного кода.
  2. Механизм белого списка:Только звонки аутентифицированным、Список доверенных контрактов。так,Даже если появится новый вредоносный контракт,Его также нельзя вызвать через наш контракт.
  3. Используйте безопасные библиотеки:Используйте, например.OpenZeppelinждать Безопасность Стандартизация в библиотекахинтерфейс,Эти интерфейсы обычно имеют в виду проблемы безопасности и совместимости.
  4. Ограничить глубину вызова:Избегайте повторного вызова других внешних контрактов при вызове внешнего контракта.,Для предотвращения атак, вызванных рекурсивными вызовами.
  5. Мониторинг событий и обработка исключений:При вызове внешнего контракта,Мониторинг возвращаемых значений и исключений,Убедитесь, что вызов успешен и не происходит необычного поведения.

Вот пример улучшенного контракта, реализующего механизм белого списка:

Язык кода:javascript
копировать
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

interface IERC20 {
    function transferFrom(address, address, uint256) external returns (bool);
}

contract SafeExternalCall {
    mapping(address => bool) public approvedContracts;
    address public externalTokenContract;

    constructor(address _externalTokenContract) {
        approveContract(_externalTokenContract);
        externalTokenContract = _externalTokenContract;
    }

    function exchangeTokens(uint256 amount) public {
        require(approvedContracts[externalTokenContract], "Contract not approved");
        IERC20(externalTokenContract).transferFrom(msg.sender, address(this), amount);
    }

    function approveContract(address contractAddress) public {
        approvedContracts[contractAddress] = true;
    }
}

В этом улучшенном контракте,Мы добавилиapprovedContractsкартографирование,Используется для хранения утвержденных адресов внешних контрактов. Только если адрес внешнего контракта внесен в белый список,Его можно вызвать через наш договор.

Благодаря этим улучшениям мы можем значительно снизить риски безопасности, связанные с вызовом ненадежных внешних контрактов. Однако в практических приложениях необходимо постоянно обращать внимание на новые угрозы безопасности и лучшие практики для поддержания безопасности контракта.

boy illustration
Неразрушающее увеличение изображений одним щелчком мыши, чтобы сделать их более четкими артефактами искусственного интеллекта, включая руководства по установке и использованию.
boy illustration
Копикодер: этот инструмент отлично работает с Cursor, Bolt и V0! Предоставьте более качественные подсказки для разработки интерфейса (создание навигационного веб-сайта с использованием искусственного интеллекта).
boy illustration
Новый бесплатный RooCline превосходит Cline v3.1? ! Быстрее, умнее и лучше вилка Cline! (Независимое программирование AI, порог 0)
boy illustration
Разработав более 10 проектов с помощью Cursor, я собрал 10 примеров и 60 подсказок.
boy illustration
Я потратил 72 часа на изучение курсорных агентов, и вот неоспоримые факты, которыми я должен поделиться!
boy illustration
Идеальная интеграция Cursor и DeepSeek API
boy illustration
DeepSeek V3 снижает затраты на обучение больших моделей
boy illustration
Артефакт, увеличивающий количество очков: на основе улучшения характеристик препятствия малым целям Yolov8 (SEAM, MultiSEAM).
boy illustration
DeepSeek V3 раскручивался уже три дня. Сегодня я попробовал самопровозглашенную модель «ChatGPT».
boy illustration
Open Devin — инженер-программист искусственного интеллекта с открытым исходным кодом, который меньше программирует и больше создает.
boy illustration
Эксклюзивное оригинальное улучшение YOLOv8: собственная разработка SPPF | SPPF сочетается с воспринимаемой большой сверткой ядра UniRepLK, а свертка с большим ядром + без расширения улучшает восприимчивое поле
boy illustration
Популярное и подробное объяснение DeepSeek-V3: от его появления до преимуществ и сравнения с GPT-4o.
boy illustration
9 основных словесных инструкций по доработке академических работ с помощью ChatGPT, эффективных и практичных, которые стоит собрать
boy illustration
Вызовите deepseek в vscode для реализации программирования с помощью искусственного интеллекта.
boy illustration
Познакомьтесь с принципами сверточных нейронных сетей (CNN) в одной статье (суперподробно)
boy illustration
50,3 тыс. звезд! Immich: автономное решение для резервного копирования фотографий и видео, которое экономит деньги и избавляет от беспокойства.
boy illustration
Cloud Native|Практика: установка Dashbaord для K8s, графика неплохая
boy illustration
Краткий обзор статьи — использование синтетических данных при обучении больших моделей и оптимизации производительности
boy illustration
MiniPerplx: новая поисковая система искусственного интеллекта с открытым исходным кодом, спонсируемая xAI и Vercel.
boy illustration
Конструкция сервиса Synology Drive сочетает проникновение в интрасеть и синхронизацию папок заметок Obsidian в облаке.
boy illustration
Центр конфигурации————Накос
boy illustration
Начинаем с нуля при разработке в облаке Copilot: начать разработку с минимальным использованием кода стало проще
boy illustration
[Серия Docker] Docker создает мультиплатформенные образы: практика архитектуры Arm64
boy illustration
Обновление новых возможностей coze | Я использовал coze для создания апплета помощника по исправлению домашних заданий по математике
boy illustration
Советы по развертыванию Nginx: практическое создание статических веб-сайтов на облачных серверах
boy illustration
Feiniu fnos использует Docker для развертывания личного блокнота Notepad
boy illustration
Сверточная нейронная сеть VGG реализует классификацию изображений Cifar10 — практический опыт Pytorch
boy illustration
Начало работы с EdgeonePages — новым недорогим решением для хостинга веб-сайтов
boy illustration
[Зона легкого облачного игрового сервера] Управление игровыми архивами
boy illustration
Развертывание SpringCloud-проекта на базе Docker и Docker-Compose