Back to Blog

Защита экосистемы Solana (4) — Валидация аккаунтов

April 1, 2022
5 min read

0. Обзор

1. Обзор

В предыдущем блоге мы обсудили, как обновлять программу. В этой статье мы рассмотрим проблемы, связанные с управлением доступом, — одну из наиболее распространённых и базовых тем безопасности в области DeFi.

2. Инструкции

В Solana каждая программа экспортирует единственную точку входа entrypoint, которая определяется с помощью entrypoint!. В отличие от Ethereum, клиенты могут вызывать только одну функцию, определённую как точка входа, которая обычно называется process_instruction. Функция точки входа принимает три параметра: идентификатор программы смарт-контракта, аккаунты, с которыми программа будет работать, и данные инструкции. Данные инструкции определяют, какая именно инструкция будет вызвана. На рисунке ниже показан пример. При распаковке данных инструкции выбираются различные инструкции (например, Lock, Unlock). Таким образом, инструкции, доступные из точки входа, открыты для всех и могут быть выполнены с указанными данными инструкции.

3. Валидация аккаунтов

Как уже упоминалось, программа получает аккаунты, которые ей необходимо читать или записывать. Такой подход порождает два вопроса. Для аккаунтов, предназначенных для чтения: как гарантировать, что данные, хранящиеся в аккаунтах, являются доверенными? Для аккаунтов, предназначенных для записи: как гарантировать, что только привилегированные пользователи могут вызывать инструкции для записи в аккаунты? Далее мы иллюстрируем проблему управления доступом. Весь тестовый код можно найти здесь.

3.1 Обзор кода (PrivilegeOwner)

Сначала мы определяем две структуры: Door и Config. Только аккаунт с ключом (строка 17), указанным в структуре door, может открыть созданную door. Однако дверь не может быть открыта, когда состояние системы заблокировано, что задаётся структурой Config (строка 81).

Как уже упоминалось, аккаунт Config определяет, может ли быть открыта дверь. В данном случае в программе должен существовать только один аккаунт Config. Для этого мы используем PDA для хранения данных Config. После инициализации аккаунта Config мы устанавливаем атрибут is_initialized в значение true, чтобы он не мог быть повторно инициализирован злоумышленниками (строки 108–110).

Инструкция Open() используется для открытия дверей. Инструкция получает несколько аккаунтов, включая аккаунт двери, которую необходимо открыть, аккаунт config и аккаунт owner, намеревающийся открыть door. Чтобы гарантировать, что дверь принадлежит программе и конфигурация является действительной, мы проверяем владельца аккаунта door и аккаунта config (строки 204–205). Это предотвращает передачу поддельных аккаунтов злоумышленниками. Это отвечает на наш первый вопрос. Чтобы гарантировать доверенность читаемого аккаунта, необходимо проверить его владельца! Обратите внимание, что только владелец аккаунта door может открыть дверь. В этом случае мы проверяем, является ли аккаунт owner реальным владельцем door, и что не менее важно, авторизована ли инструкция владельцем (строки 217–219).

В функции validate_owner() мы сначала проверяем, совпадают ли публичные ключи двух аккаунтов, а затем проверяем подпись владельца. Это отвечает на второй вопрос: чтобы гарантировать, что только привилегированные пользователи могут вызывать инструкцию open, необходимо проверить владельца и подписанта аккаунта. Инструкция close аналогична open, подробности можно найти в коде.

Мы развернули программу в тестовой сети, и её можно найти по следующей ссылке.

https://explorer.solana.com/address/2Q7FFMWCthBvc6ubLQRx9TRswvaimmd66VaCAfHwsYuC?cluster=testnet

Все тестовые транзакции перечислены ниже. Весь процесс транзакций выглядит следующим образом: AllocatePDA()-> InitializeDoor()-> InitializeConfig()-> Unlock() -> Open() -> Close().

https://explorer.solana.com/tx/2X9CyMrHTNEvbzXTE95gem2j8spnvsQsabFeSpV8hiNpYjiQPPzLRqt5KN86ZYRjnQvydvs7y5eUjJK7no8knDhk?cluster=testnet
https://explorer.solana.com/tx/2XfVWiXeQeHbpqAEYm3AH2RU6hunnqtr155EC4EAM5Bq9VVZNP6QocAav9cPjEQdJFcQrbsSSxiKadr4HPMov8pz?cluster=testnet
https://explorer.solana.com/tx/5Em41sg7yFXeNpnEJnhUQJanfLWKwjMqiBeNAqEEzFrSN9P8zKKafcv5F7RKT2pseB171qeoa8Uz4fKgazzayCnW?cluster=testnet
https://explorer.solana.com/tx/2PMtzpSgjnKDLGmRWBdUSFBPimWnudCPekUYbWzPzokENFYa4N4ab4HCtynfGrzswFPTgGYKHU8PccUMHv3mXHkR?cluster=testnet
https://explorer.solana.com/tx/3kviP9MqkWGMV4yA7k7yPQ5BGfXmcYLcctmY1u2D7n56eT1nx8jMtDumkUNJy8yA3KkmzrmfQLjqpigc8ehGZzBN?cluster=testnet
https://explorer.solana.com/tx/38iEaJBzuGMLbfcszdVB8pkniezH8JrA3XGq7JdADZTQ4hNQC82GSTUA2bmcypdVy3t7htWnUzkZ4F8EakmNvqz8?cluster=testnet

3.2 Атакующая транзакция

Чтобы показать важность проверки владельца и проверки подписанта, рассмотрим два сценария атаки.

Первый сценарий

Первый сценарий: владелец «двери» пытается открыть её, когда config заблокирован. Для этого мы создаём поддельный аккаунт config в другой программе и присваиваем атрибуту is_lock значение false. Код пользовательской программы показан ниже.

Мы отправляем транзакцию для создания поддельного аккаунта конфигурации, публичный ключ поддельного аккаунта config: 2MtSrbWp24VjPZQcSUkiWrvNro7qqKemVCsh3Yxc8LTy.

https://explorer.solana.com/tx/2qSyrL5gdQXmgGCFzmzMm1StFQRkDgWpss9A9jV11q2fgDGM5C1XRuXvbX1N5Dt3q2pRqnmyXHVtXGF5dqadAzpJ?cluster=testnet

После создания поддельного аккаунта config мы передаём его в программу (строка 423).

Результат показан ниже: в журнале выводится сообщение incorrect program id for instruction, что означает: владельцем аккаунта config должна быть программа. Таким образом, злоумышленник не может обойти эту проверку.

Второй сценарий

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

В этом случае мы передаём реальный аккаунт владельца в программу (строка 419) и отправляем транзакцию. Результат показан ниже.

Выводится сообщение Signature verification failed, что означает: реальный владелец должен подписать транзакцию для открытия двери, поэтому наша вторая атака также завершается неудачей.

4. Заключение

В Solana инструкции реализуют заданную логику на основе различных аккаунтов, которые передаются клиентами или другими программами. Поэтому правильная проверка аккаунтов имеет исключительно важное значение.

В этой статье мы рассмотрели, как правильно проверять аккаунты, и на двух сценариях атак продемонстрировали важность этих проверок. Следите за обновлениями — впереди ещё много интересных материалов.

Читайте другие статьи этой серии:


О компании BlockSec

BlockSec — pioneering компания в области безопасности блокчейна, основанная в 2021 году группой всемирно признанных экспертов по безопасности. Компания стремится повысить уровень безопасности и удобства использования формирующегося мира Web3 с целью содействия его массовому принятию. Для этого BlockSec предоставляет услуги аудита безопасности смарт-контрактов и EVM-цепочек, платформу Phalcon для обеспечения безопасной разработки и проактивного блокирования угроз, платформу MetaSleuth для отслеживания и расследования движения средств, а также расширение MetaSuites для эффективной работы разработчиков web3 в криптопространстве.

На сегодняшний день компания обслужила более 300 уважаемых клиентов, таких как MetaMask, Uniswap Foundation, Compound, Forta и PancakeSwap, и привлекла десятки миллионов долларов США в двух раундах финансирования от ведущих инвесторов, включая Matrix Partners, Vitalbridge Capital и Fenbushi Capital.

Официальный сайт: https://blocksec.com/

Официальный аккаунт в Twitter: https://twitter.com/BlockSecTeam

Sign up for the latest updates
~$5.98M Потеряно: Aztec, Raydium и другие | Еженедельник BlockSec
Security Insights

~$5.98M Потеряно: Aztec, Raydium и другие | Еженедельник BlockSec

Еженедельный отчёт о безопасности блокчейна (8–15 июня 2026 г.): 4 инцидента в Ethereum и Solana, общие потери ~$5,98 млн. Aztec Connect: отсутствие валидации входных данных привело к рассинхронизации rollup и L1. Raydium: уязвимость в AMM v3 позволила дренировать 4 пула.

Санкции OFAC против картеля Синалоа: отслеживание средств в блокчейне

Санкции OFAC против картеля Синалоа: отслеживание средств в блокчейне

OFAC ввёл санкции против сети картеля Синалоа за отмывание доходов от фентанила. Мы отследили шесть адресов в MetaSleuth: средства проходят почти исключительно через депозитные адреса централизованных бирж.

Анализ уязвимости Zcash Orchard | Еженедельник BlockSec
Security Insights

Анализ уязвимости Zcash Orchard | Еженедельник BlockSec

Критическая уязвимость в цепи Orchard Zcash: отсутствие ограничения равенства в гаджете ECC halo2 позволяло незаметно подделывать ZEC через двойное расходование. Уязвимость существовала 4+ лет, обнаружена ИИ-аудитом (Anthropic Opus 4.8, исследователь Тейлор Хорнби), устранена экстренным обновлением NU6.2.