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

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

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

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

Предположим, у нас есть смарт-контракт, который позволяет пользователям выполнять определенную задачу, например погашение токенов, путем вызова внешнего контракта. Здесь мы предполагаем, что внешний контракт предоставляет функцию 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
Углубленный анализ переполнения памяти CUDA: OutOfMemoryError: CUDA не хватает памяти. Попыталась выделить 3,21 Ги Б (GPU 0; всего 8,00 Ги Б).
boy illustration
[Решено] ошибка установки conda. Среда решения: не удалось выполнить первоначальное зависание. Повторная попытка с помощью файла (графическое руководство).
boy illustration
Прочитайте нейросетевую модель Трансформера в одной статье
boy illustration
.ART Теплые зимние предложения уже открыты
boy illustration
Сравнительная таблица описания кодов ошибок Amap
boy illustration
Уведомление о последних правилах Points Mall в декабре 2022 года.
boy illustration
Даже новички могут быстро приступить к работе с легким сервером приложений.
boy illustration
Взгляд на RSAC 2024|Защита конфиденциальности в эпоху больших моделей
boy illustration
Вы используете ИИ каждый день и до сих пор не знаете, как ИИ дает обратную связь? Одна статья для понимания реализации в коде Python общих функций потерь генеративных моделей + анализ принципов расчета.
boy illustration
Используйте (внутренний) почтовый ящик для образовательных учреждений, чтобы использовать Microsoft Family Bucket (1T дискового пространства на одном диске и версию Office 365 для образовательных учреждений)
boy illustration
Руководство по началу работы с оперативным проектом (7) Практическое сочетание оперативного письма — оперативного письма на основе интеллектуальной системы вопросов и ответов службы поддержки клиентов
boy illustration
[docker] Версия сервера «Чтение 3» — создайте свою собственную программу чтения веб-текста
boy illustration
Обзор Cloud-init и этапы создания в рамках PVE
boy illustration
Корпоративные пользователи используют пакет регистрационных ресурсов для регистрации ICP для веб-сайта и активации оплаты WeChat H5 (с кодом платежного узла версии API V3)
boy illustration
Подробное объяснение таких показателей производительности с высоким уровнем параллелизма, как QPS, TPS, RT и пропускная способность.
boy illustration
Удачи в конкурсе Python Essay Challenge, станьте первым, кто испытает новую функцию сообщества [Запускать блоки кода онлайн] и выиграйте множество изысканных подарков!
boy illustration
[Техническая посадка травы] Кровавая рвота и отделка позволяют вам необычным образом ощипывать гусиные перья! Не распространяйте информацию! ! !
boy illustration
[Официальное ограниченное по времени мероприятие] Сейчас ноябрь, напишите и получите приз
boy illustration
Прочтите это в одной статье: Учебник для няни по созданию сервера Huanshou Parlu на базе CVM-сервера.
boy illustration
Cloud Native | Что такое CRD (настраиваемые определения ресурсов) в K8s?
boy illustration
Как использовать Cloudflare CDN для настройки узла (CF самостоятельно выбирает IP) Гонконг, Китай/Азия узел/сводка и рекомендации внутреннего высокоскоростного IP-сегмента
boy illustration
Дополнительные правила вознаграждения амбассадоров акции в марте 2023 г.
boy illustration
Можно ли открыть частный сервер Phantom Beast Palu одним щелчком мыши? Супер простой урок для начинающих! (Прилагается метод обновления сервера)
boy illustration
[Играйте с Phantom Beast Palu] Обновите игровой сервер Phantom Beast Pallu одним щелчком мыши
boy illustration
Maotouhu делится: последний доступный внутри страны адрес склада исходного образа Docker 2024 года (обновлено 1 декабря)
boy illustration
Кодирование Base64 в MultipartFile
boy illustration
5 точек расширения SpringBoot, супер практично!
boy illustration
Глубокое понимание сопоставления индексов Elasticsearch.
boy illustration
15 рекомендуемых платформ разработки с нулевым кодом корпоративного уровня. Всегда найдется та, которая вам понравится.
boy illustration
Аннотация EasyExcel позволяет экспортировать с сохранением двух десятичных знаков.