
Привет, Хабр!
Я Дмитрий, в прошлом разработчик смарт-контрактов (с 2017 года), с 2022 года работаю аудитором смарт-контрактов. Эта статья для тех, кто так или иначе интересуется информационной безопасностью и непосредственно аудитом смарт-контрактов (да и процессом аудита в целом).
По итогам аудита могут возникнуть два серьезных вопроса: «Почему мы ничего не успели?» и «Почему мы ничего не нашли?». И самая страшная ситуация, когда оба эти вопроса возникают одновременно. Опишем это одним емким словом: «Провал».
Как попытаться предотвратить появление этих вопросов? Чтобы ответить на этот вопрос, попробую сначала описать сам процесс. Зачем вообще описывать аудит как процесс? Потому что «провал» часто происходит не при поиске уязвимостей, и не при использовании инструментов, а именно в организационной части.
Естественно, всё зависит от целей и объема конкретного аудита, но если где-то и описывают типовой процесс поиска уязвимостей, то чаще всего он состоит из следующих шагов:

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

Я сознательно опускаю моменты, связанные с оценкой объема аудита (будь то репозиторий или смарт-контракты, уже развернутые в сети), составлением коммерческого предложения, определением сроков и подписанием договора (т.е. опускаю этап переговоров). И начну сразу с момента, когда клиент и исполнитель (т.е. мы) договорились о проведении аудита.

Начальный этап
И прежде чем приступить к анализу системы смарт-контрактов, с нашей стороны (т.е. со стороны исполнителя) должен быть назначен ответственный за проведение аудита. Это самое первое, что необходимо сделать на старте. Ответственным может быть тимлид, опытный аудитор или проектный менеджер, главное, чтобы он понимал сам процесс.
Также ещё до начала аудита желательно определить каналы коммуникации с клиентом (его представителем или разработчиками), будь то чат в мессенджере или, например, какой-то конкретный кабинет на территории клиента, где будут проводиться рабочие встречи.
Рекомендую проговорить и зафиксировать где-то в чате или на бумаге информацию о целях, объеме, критериях и методах аудита, а также составе аудиторской группы.
Отдельный важный вопрос — доступ к инфраструктуре, где исполняются смарт-контракты. Необходимо уточнить специфику исполняемой среды, будь то приватный или публичный блокчейн, программное обеспечение узлов или прекомпилированные смарт-контракты, которые могут быть специфическими для конкретного блокчейна. Всё необходимо уточнить! И лучше сделать это «на берегу».
О чем еще иногда забывают в процессе аудита? Это непосредственное его влияние на процессы клиента.
Пример. Аудиторы в процессе своей деятельности задают вопросы разработчикам, а у тех в это время «упал продакшен» и они судорожно ищут причину. Поэтому в идеале иметь гибкий график проведения аудита с заранее выделенными «окнами» для коммуникации с разработчиками или представителем клиента. Без обратной связи со стороны разработчиков может пострадать качество аудита (а мы ведь хотим, чтобы аудит прошёл хорошо!).
Квалифицированные аудиторы также знают о существовании соглашения о неразглашении (aka NDA). В идеальном мире еще до аудита между клиентом и исполнителем согласованы все параметры конфиденциальности и обязательно утверждён порядок раскрытия найденных уязвимостей.
И вишенкой на торте начального этапа является уточнение со стороны аудиторов на какой части системы необходимо сделать акцент. Если система состоит из двух модулей, и один из них с полной документацией, покрытый тестами, а второй «доделали только вчера», то логично сделать упор на «новом» модуле, особенно в местах, где он взаимодействует со «старым».
А теперь к тому, о чём некоторые в силу обстоятельств боятся говорить. Ответственный за аудит ещё на начальном этапе должен определить, возможен ли аудит вообще? Можно ли достичь поставленных целей, хотя бы теоретически? Если аудит не осуществим (например, объем кратно увеличился), или есть существенные препоны, которые могут повлиять на качество аудита, лучше обо всём этом сообщить заранее, а для некоторых организаций это делается исключительно в письменной форме. Это может привести к конфликту, но мы же говорим о том, как НЕ провалить аудит.
Из личной практики.
Вы с командой приезжаете на территорию клиента, где присутствует пропускной режим, и обнаруживаете, что список допущенных лиц неактуальный! И два аудитора из пяти не могут пройти через контрольно-пропускной пункт… Хорошо, если вы приехали на две недели и за полдня этот вопрос решили, а если на два дня? Подобные вопросы всегда стоит решать заранее. А ещё лучше вообще не допускать подобных промашек.
Кратко резюмируем вышесказанное. По итогу начальный этап выглядит следующим образом:
Назначен ответственный за аудит;
Определён порядок взаимодействия с разработчиками и/или клиентом;
Уточнены и подтверждены цели и объём аудита;
Согласованы параметры конфиденциальности;
Обеспечен доступ к инфраструктуре (в случае необходимости) и решены организационные вопросы.
Вернемся к нашей таблице, и добавим туда новые данные.

Подготовительный этап
Если детали начального этапа утрясли, видимых препятствий нет, поздравляю! Мы можем начинать. Начинать сам аудит? Нет! Начинать готовиться к аудиту, т.е. теперь несколько слов про подготовительный этап аудита.
В первую очередь необходимо уточнить, есть ли помимо кода документация, и если ответ «Да», то уточнить, в каком виде. Наличие документации – обоюдоострый меч: вы можете поверить, что там всё правда, и это будет фатальной ошибкой. Иметь представление о содержании документации может оказаться полезным для уточнения работы конкретных смарт-контрактов, их функций и параметров. Также очень важен объём документации, если аудит длится неделю, а документации только для чтения на месяц… надеяться, что вы сможете в неё погрузиться, – нонсенс. Особое внимание надо уделить схемам и диаграммам, если таковые присутствуют. Краткую выжимку от ИИ рекомендовать не могу, он может упустить важные детали.
Если кодовая база со смарт-контрактами уже проходила аудит, желательно иметь на руках отчёты о предыдущих проверках. Это может помочь с векторами атак и дать понимание, на что был сделан упор предыдущей аудиторской группой.
На начальном этапе один из фокусов был на доступе к инфраструктуре, на данном этапе этот фокус смещается непосредственно в сторону устройства этой инфраструктуры. Теперь нужно не просто уточнить среду исполнения смарт-контрактов (включая прекомпилированные смарт-контракты, консенсус-сети, приватность или публичность блокчейна и т. д.), но также оценить связанные с этим риски и возможности.
В первую очередь нам нужно утвердить состав аудиторской группы и её общую компетентность. Далее выбираем подходящие методы для аудита и прикидываем, как можно повысить его эффективность. Например, кодовая база содержит несколько математических библиотек, отличное место для фазинга, и, соответственно, в состав аудиторской группы включаем специалиста, знающего фазинг как свои пять пальцев.
Далее стоит составить план-график аудита, собственно подробность плана должна отражать область и сложность аудита. Ещё один вопрос, который закрывает план-график, – распределение задач между аудиторами. Казалось бы, это понятно любому, тем более если аудиторская группа мала и состоит только из опытных специалистов, они в состоянии разобраться сами. Но при длительном аудите и когда команда аудиторов состоит из пяти и более экспертов, вопросу о распределении задач нужно уделить особое внимание.
Что ещё желательно учесть в плане? Рабочие встречи. В идеальном мире общение с разработчиками доступно круглые сутки, они доброжелательны и по первому зову мчатся отвечать на ваши вопросы. Но в реальности желательно согласовать и добавить в план-график рабочие встречи. В процессе аудита собирайте вопросы от экспертов, и когда их будет достаточное количество, адресуйте всю пачку разработчикам для комментариев. Делать это можно и вживую, и онлайн, и в гибридном формате. Также важно напомнить, что клиент хочет видеть, за что он заплатил, ещё до итогового отчета, поэтому — больше вопросов и больше эффективных рабочих встреч!
Если требуется, то план-график аудита надо показать клиенту или его представителю. Все возникшие вопросы в отношении такого плана лучше разрешить в самом начале.
Чего в плане может не хватать? Гибкости. Это очень важно при длительных аудитах. В процессе аудита могут вскрыться новые обстоятельства, которые не были известны заранее и могут повлиять на результат. Важно оперативно на них реагировать.
Из личной практики.
Большой протокол, представляющий собой кредитную платформу, состоящую из десятков смарт-контрактов, кучи параметров, модули взаимодействия с децентрализованными обменниками и мостами… Через неделю поиска уязвимостей стало ясно, что критических уязвимостей слишком много, они были оперативно предоставлены клиенту. Ребята отреагировали положительно. А ещё через неделю аудиторская группа предоставила новый набор подтверждённых уязвимостей, демонстрирующих принципиальные недочёты архитектуры… Разработанный протокол из-за нюансов блокчейна был нежизнеспособен. Проект пришлось закрыть, но клиент оказался понимающим и остался благодарен, т.к. риски потери средств и репутации в публичном поле для него были выше, чем «негативное» заключение аудита.
Более простой пример неожиданностей: как-то нас посадили в кабинет, где весь день не было электричества из-за каких-то внешних работ, а ноутбуки были заряжены не у всех... В итоге пару часов пришлось просто ждать, когда включат электричество.
Ещё один вопрос, который я не разобрал, но который также должен быть отображен в плане — критерии уязвимости. В зависимости от клиента, условий и целей аудита критерии могут быть разными. Например: «Ребят, ищите только криты, это промежуточная версия».
Заключительная стадия данного этапа – подготовка специализированных инструментов и программного обеспечения. Члены аудиторской группы исходя из своих задач должны подготовить необходимые инструменты (например, чек-листы или базу известных уязвимостей) и собственно специализированное программное обеспечение (например, статические анализаторы, инструменты для формальной верификации или рабочую локальную LLM).
Напоследок скажу про два небольших кейса, которые встречаются в моей практике крайне редко, но о которых стоит упомянуть. Первый связан с определением рабочего языка взаимодействия (например, русский или английский) и язык отчёта (они тоже могут различаться). А второй кейс касается координации с деятельностью других аудиторов в случае совместного аудита или параллельной проверки.
Резюмируем чек-лист для подготовительного этапа.
Проверить наличие, объем и качество документации (включая схемы, диаграммы и предыдущие аудиторские отчеты);
Уточнить характеристики, параметры среды исполнения смарт-контрактов и ее устройство;
Составить детальный план-график, утвердить состав аудиторской группы и распределить задачи;
Задать критерии для уязвимостей;
Подготовить специализированные инструменты и ПО.
Вернемся к общей схеме и обновим ее.

Основной этап
Обычно сам процесс аудирования кодовой базы осуществляется в строго определенной последовательности

Но данная последовательность может меняться в зависимости от обстоятельств конкретного аудита.
Повторюсь, что в первую очередь необходимо распределить обязанности между членами аудиторской группы. Если специалист один, то он как человек-оркестр выполняет все работы самостоятельно. Если аудиторов несколько, то высока вероятность дублирования работ: например, каждый запустил статический анализатор Slither и все получили один и тот же отчёт.
Аудит как процесс предъявляет определенные требования к концентрации, поэтому если есть внешние наблюдатели или сопровождающие, желательно снизить их влияние на аудиторскую группу. Возможно, это звучит слишком обыденно, но: не мешайте людям работать! Если вы на территории клиента, и в соседнем кабинете штробят стены под розетки – поздравляю! В данном случае итоговый результат будет ниже. Ответственный за аудит должен максимально обеспечить надлежащие условия для проведения работ, и вот тут сопровождающие и наблюдатели могут оказаться очень полезны.
Обязанности между аудиторами распределены, условия обеспечены – настало время первой рабочей встречи. Она может проходить оффлайн и онлайн где-то в чате или с помощью видеоконференции. Онлайн встречаться проще, но так или иначе необходимо представить клиенту членов аудиторской группы и разъяснить их функции. Снова представим идеальный мир, где на встрече помимо CEO или его представителя присутствуют разработчики, которые готовы ответить на любые вопросы… Далее представляется план аудита, задача согласовать и зафиксировать в плане все промежуточные рабочие встречи, и, самое главное, порядок информирования клиента и разработчиков о ходе аудита и найденных уязвимостях.
Далее выскажу тезис об обмене информации. Он необязательный для аудиторской группы (в связи с тем, что процессы, стили и виды аудита бывают разные), но рекомендуется периодически собираться для обмена информацией, чтобы понимать, как движется поиск уязвимостей и, в случае необходимости, перераспределить задания между членами аудиторской группы. Для клиента средства обмена информацией могут варьироваться от чатика в мессенджере до специальных защищённых каналов связи, этот момент тоже необходимо проговорить и утвердить.
Отдельно стоит сказать о значимых уязвимостях. Такие уязвимости должны быть переданы без задержки клиенту и, если необходимо, разработчикам. Естественно кроме случаев, когда было проговорено, что не надо никого беспокоить: «Все баги, даже критические, покажите через три недели».
Одна из самых неприятных ситуаций, которая может произойти на проекте – невозможность выполнить поставленные задачи в срок. В таких случаях руководителю аудита следует сообщить об этом клиенту заранее, чтобы определить, что делать дальше. Чтобы не сгущать краски, скажу, что это может быть не только прекращение аудита, а лишь изменение плана, увеличение срока или перенос аудита на другие даты.
Три подхода к аудиту
Пришло время поговорить про подходы к поиску багов. Выделю три основных: это методы «белого ящика», «черного ящика» и «серого ящика».
Но прежде чем перейти к подходам, вспомним, что типовое блокчейн-приложение состоит как минимум из четырёх зависимых частей:
Блокчейн-платформа (как среда исполнения смарт-контрактов) может содержать уязвимости криптографии, консенсуса, журналирования, доступа к управлению узлом, управления ключами узла;
Смарт-контракты могут содержать уязвимости логики исполнения бизнес-процесса, технической реализации бизнес-процесса;
Бизнес-приложение может содержать уязвимости управления ключами, искажения данных перед отправкой в смарт-контракты или после нее;
Организационный уровень может содержать особенности, влияющие на доступ участников к артефактам блокчейн-приложения и обновления исходного кода.
Немного про «белый ящик»
В данном подходе имеется доступ ко всем частям проекта, кодовой базе и проектной документации. Цель аудитора чаще всего состоит в том, чтобы определить уязвимости до запуска проекта или до обновления продукта с новой функциональностью.
Порядок действий при данном подходе состоит из трех шагов и выглядит следующим образом:
На первом шаге выполняются следующие действия:
Обзор архитектуры проекта;
Анализ проектной документации;
Общий анализ кода;
Обратное проектирование для анализа архитектуры проекта исключительно на основе исходного кода;
Разработка независимой точки зрения на архитектуру проекта;
Выявление любых логических недостатков в проектировании.
Цель данного шага в том, чтобы понять общую структуру проекта и выявить потенциальные риски безопасности.
На втором шаге мы выполняем следующие действия:
Основной анализ кода с учетом хакерских техник;
Выявление уязвимостей;
Разработка доказательств концепции (Proof-of-Concept, PoC);
Проведение фазинг-тестирования;
Использование инструментов формальной верификации;
Анализ тестовых примеров и комментариев в коде.
Основная цель данного шага это выявить и устранить большинство уязвимостей, включая уникальные для распределённых систем (aka блокчейн).
На третьем шаге мы выполняем:
Проведение ручной проверки кода с использованием внутренних и внешних контрольных списков;
Использование инструментов статического анализа и баз данных уязвимостей.
Тут главная цель – обеспечить всесторонний охват известных векторов атак.
Как видим, данный подход годится, когда у вас всё есть (и код, и документация), а самое главное, есть время на выполнение всех действий.
Немного про «чёрный ящик»
При данном подходе проверка начинается с запроса всех доступных данных и адресов смарт-контрактов в блокчейне (aka распределенный реестр). Кода нет! Точнее у вас есть только байткод, развернутый в сети.
Порядок действий в данном случае на бумаге выглядит гораздо проще:
Декомпиляция кода узла или смарт-контрактов;
Реконструкция исходного кода из декомпилированного вида;
Применение типовых сценариев запуска узлов и использования смарт-контрактов.
Но может случиться, как в поговорке: гладко было на бумаге, но забыли про овраги. Данный подход крайне трудоёмкий и требует больше времени для проверки. Всесторонняя проверка в данном случае не всегда бывает возможна, поэтому рекомендую ограничиться применением типовых сценариев.
Немного про «серый ящик»
Самый частый и практичный вариант. При таком подходе аудитор имеет частичный доступ к информации о проекте (например, ограниченный доступ к исходному коду, документации, конфигурациям, тестовой среде или API) и ограничен во времени. Данный подход включает в себя совокупность подходов «чёрного» и «белого ящиков», но в условиях ограничений. Естественно такой подход больше тяготеет к «белому», так как у нас хоть что-то есть на руках.
Основная цель при данном подходе – определить уязвимости при ограниченном знании архитектуры и логики проекта. Найти атаки, максимально приближенные к реальным условиям и сценариям. Чаще всего проверяются вектора атак со стороны привилегированного пользователя, интегратора или обычного пользователя.
Порядок действий (возможно, что-то придется пропустить из-за нехватки времени):
Анализ предоставленной документации и архитектуры;
Анализ доступных частей исходного кода;
Анализ конфигураций тестовой среды;
Изучение ограничений хранилища данных и внешних систем;
Моделирование атак с учётом известной архитектуры;
Анализ сетевого взаимодействия и API;
Попытки эскалации привилегий с использованием представленных ролей;
Применение типичных и комбинированных сценариев эксплуатации.
В реальной жизни аудитора чаще всего встречается «серый ящик», в жизни хакера «чёрный ящик», а руководитель аудита мечтает о «белом ящике».
Поиск уязвимостей
После выбора подхода можно приступать непосредственно к аудиту, именно в смысле поиска уязвимостей. Анализ документации может помочь найти подходящие вектора атак, а найденные расхождения документации с текущим состоянием системы также могут быть зафиксированы в некотором смысле как уязвимости, и информация о них должна быть передана клиенту.
Непосредственно анализ смарт-контрактов может быть проведён с использованием следующих методов (не вдаваясь в детали, т.к. это выходит за пределы данной статьи):
Анализ кода;
Анализ документации;
Обратное проектирование архитектуры проекта исключительно на основе исходного кода;
Фазинг-тестирование;
Статический анализ;
Формальная верификация;
Мутационное тестирование;
Анализ тестовых примеров и параметров использования;
Использование баз данных уязвимостей;
Использование контрольных списков (т.н. чек-листов);
Использование ИИ и помощников на его основе.
Важный вопрос, который необходимо поднять – регистрация и подтверждение уязвимостей, как минимум для уязвимостей высокого уровня опасности. Аудитор должен предоставлять т.н. «PoC» (Proof-of-Concept) в качестве доказательства и примера эксплуатации найденной уязвимости, т.к. в противном случае может произойти неприятная ситуация и уязвимость не будет подтверждена со стороны клиента или разработчиков с формулировкой «Да не может быть!».
Далее каждый аудитор формирует список найденных уязвимостей, не забывая выставлять уровень критичности уязвимости к каждой находке (напомню, что критерии оценки уязвимостей были утверждены на более раннем этапе). Вообще, если говорить непосредственно о критериях, то уязвимости могут классифицироваться в зависимости от среды работы смарт-контрактов и её рисков. Эта оценка может разниться от аудита к аудиту.
На этом основной этап проекта завершен, резюмируем его в виде чек-листа:
Распределить обязанности между аудиторами и обеспечить условия для проведения аудита;
Представить клиенту план работ, самих аудиторов, разъяснив их функции;
Определить порядок взаимодействия с клиентом и разработчиками в части обмена информации;
Выбрать подход к аудиту с учётом целей, доступного времени и прочих обстоятельств;
Провести поиск и сформировать список найденных уязвимостей.
И снова добавим всё описанное в нашу таблицу:

Завершающий этап
Начинается завершающий этап с подготовки к заключительной встрече, т.е. готовимся демонстрировать найденные баги!
Для этого команде аудиторов необходимо рассмотреть все найденные уязвимости и в процессе обсуждения откинуть невалидные баги, убрать дубликаты, при необходимости объединить уязвимости в одну, а также подготовить рекомендации по устранению данных уязвимостей, если это возможно (в последнее время входит в обиход модное слово «митигирование», что означает «снижение риска уязвимости»).
Наконец приступаем к итоговому отчету! В нем желательно отразить все этапы аудита, сделать описание архитектуры системы, добавить описание рисков, которые были обнаружены в процессе, а также добавить информацию про использованные инструменты и их артефакты, и конечно же не забыть про список найденных уязвимостей.
Самый ответственный момент, который все ждут, настал! Это проведение заключительной рабочей встречи с демонстрацией найденных уязвимостей.
Понятно, что такая встреча не всегда возможна и спустя какое-то время клиент просто получит предварительную версию заключения по аудиту. В данном случае на предварительный отчёт накладывается больше требований: всё должно быть тщательно задокументировано (подробно описаны уязвимости и последствия, ссылки на строки кода, инструкции по запуску PoC, описание настроек среды к найденным уязвимостям и т.д.).
Процесс демонстрации и обсуждения найденных уязвимостей может быть разный, поэтому не буду заострять на этом внимание, скажу лишь, что в случае критических уязвимостей (если они были найдены в ходе работ) важно составить план действий по их устранению и проговорить возможные последствия неправильных исправлений этих уязвимостей. Вообще исправление уязвимостей и проверка этих исправлений может проходить как в рамках текущего аудита, так и быть основанием для проведения нового.
В некоторых случаях, если того требует клиент или это регламентируется вашими рабочими процессами, заключительная рабочая встреча может быть официальной, с ведением протокола, регистрацией присутствующих и с сохранением их списка.
После получения обратной связи начинается подготовка финальной версии отчета. Она в обязательном порядке должна содержать конкретные сведения об объеме, целях, сроках аудита, его результате с итоговым заключением и выводами, а также с информацией об исполнителе и клиенте. А самое главное… дисклеймер, что аудит не содержит гарантий относительно полезности, безопасности и пригодности бизнес-модели, нормативно-правового режима для бизнес-модели, а также любых других заявлений о соответствии смарт-контрактов своему назначению или об отсутствии в них ошибок.
В конце остается только разослать отчет заинтересованным лицам и опубликовать этот отчет в сети! Если это возможно, т.к. важно не забывать о конфиденциальности.
Резюмируем заключительный этап в чек-лист:
Подготовить список уязвимостей с рекомендациями по их устранению;
Подготовить предварительный итоговый отчет;
Провести заключительную рабочую встречу и/или предоставить предварительную версию заключения по аудиту;
Подготовить финальную версию отчета и передать его клиенту;
Дать знать миру о ваших успехах (т.е. опубликовать отчет) и готовиться к новому аудиту!
Резюмируем все данные в одной таблице.

Если вы дочитали до конца, буду рад любым комментариям и замечаниям по теме, очень хочется сделать процесс аудита лучше! Всем успехов!
