Back to Blog

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

Code Auditing
June 10, 2026
10 min read
Key Insights

За прошедшую неделю (2026/06/01 - 2026/06/07) в блокчейн-экосистемах было зафиксировано несколько инцидентов, связанных с атаками. Основная тема отчёта этой недели — публичное раскрытие критической уязвимости корректности (soundness) в защищённом пуле Orchard сети Zcash, которая могла позволить незаметную подделку монет ZEC. Подтверждений эксплуатации уязвимости в сети не обнаружено, однако раскрытие спровоцировало экстренное обновление сети, а курс ZEC упал более чем на 40%.

Дата Инцидент Тип Оценочный ущерб
2026/06/04 Zcash Orchard Ошибка корректности ZK Эксплуатация не подтверждена

Best Security Auditor for Web3

Validate design, code, and business logic before launch

Главное событие недели: ошибка корректности в Zcash Orchard

Этот инцидент выбран главным событием недели, поскольку является одной из наиболее серьёзных ZK-уязвимостей, обнаруженных в рабочей среде. Отсутствующее ограничение схемы оставалось незамеченным более четырёх лет, несмотря на многочисленные аудиты, и в конечном счёте было обнаружено в ходе проверки безопасности с использованием ИИ. Класс уязвимостей (недостаточно ограниченные отношения в ZK-схемах) может присутствовать в любом протоколе, построенном на ZK-схемах.

4 июня 2026 года Zcash публично раскрыла критическую ошибку корректности в схеме защищённого пула Orchard [1]. Отсутствующее ограничение в схеме доказательства с нулевым разглашением нарушило криптографическую привязку, предотвращающую двойное расходование, что потенциально позволяло тратить одну и ту же защищённую ноту несколько раз без возможности обнаружения. Уязвимость существовала с момента активации Orchard в мае 2022 года и была обнаружена 29 мая 2026 года исследователем безопасности Тейлором Хорнби в ходе аудита с применением ИИ. Экстренное обновление сети (NU6.2) исправило схему 3 июня 2026 года. Свидетельств эксплуатации уязвимости не обнаружено.

Предыстория

Zcash — это блокчейн первого уровня с акцентом на конфиденциальность, нативным токеном которого является ZEC. В отличие от Bitcoin, где все детали транзакций общедоступны, Zcash поддерживает защищённые транзакции посредством доказательств с нулевым разглашением, скрывая адреса отправителей, адреса получателей и суммы транзакций. Zcash имеет несколько защищённых пулов, каждый из которых соответствует определённому поколению протокола конфиденциальности. Orchard — последнее поколение, активированное в мае 2022 года с обновлением сети NU5; для верификации транзакций оно использует систему доказательств с нулевым разглашением halo2 [2]. При совершении защищённой транзакции пользователь выступает в роли доказывающего: он формирует доказательство с нулевым разглашением, используя схему Orchard, которая подтверждает действительность транзакции — владение нотой, корректное получение нуллификатора и баланс сумм — без раскрытия каких-либо приватных данных. Узлы сети выступают верификаторами, проверяя доказательство без доступа к исходным данным. Схема Orchard определяет ограничения, которым должно удовлетворять каждое корректное доказательство. Уязвимость находится в реализации этой схемы и затрагивает четыре ключевых концепции Zcash: ключи, адреса, ноты и нуллификаторы.

Ключи. Иерархия ключей Zcash сложнее, чем у большинства блокчейнов. Из единственного ключа расходования (секрета кошелька) выводится несколько подключей: ask (секретный ключ авторизации расходования), nk (ключ получения нуллификатора) и rivk (рандомизатор). На их основе система вычисляет ak (публичный ключ авторизации) и ivk (ключ просмотра входящих, через ivk = Commit(ak, nk, rivk)). Ключ ivk используется для идентификации и получения входящих средств.

Адреса. Для создания адреса Orchard пользователь выбирает диверсификатор d (11-байтовое значение), который определяет диверсифицированную базовую точку g_d = DiversifyHash(d). Адрес представляет собой пару (d, pk_d), где диверсифицированный ключ передачи pk_d вычисляется как скалярное умножение на эллиптической кривой: pk_d = [ivk] g_d. Это означает, что адрес криптографически привязан к ключу просмотра пользователя.

Ноты. Нота — это запись об активе, представляющая полученные средства. В целях обеспечения конфиденциальности в сети хранится не сама нота, а её обязательство cm (криптографическое обязательство относительно содержимого ноты, включая pk_d, стоимость и другие данные). Нота заблокирована на адресе получателя.

Нуллификаторы. При расходовании ноты расходующий раскрывает нуллификатор nf, вычисленный из данных ноты и ключа нуллификатора nk: nf = Extract_P([(F_nk(ρ) + ψ) mod p]G + cm). Ключевое свойство безопасности состоит в том, что каждая нота должна порождать ровно один нуллификатор. После появления нуллификатора в сети соответствующая нота считается безвозвратно израсходованной. Если одна и та же нота могла бы порождать разные нуллификаторы, её можно было бы потратить несколько раз незаметно.

Цепочка привязки. Эти концепции связаны криптографической цепочкой привязки:

Выделенные красным узлы (pk_d, nk) — это точки, в которых уязвимость разрывает цепочку привязки: схема должна обеспечивать выполнение условия pk_d = [ivk] g_d, что привязывает расходующего к корректному ivk, а следовательно — к корректному nk для данной ноты. Если эта привязка нарушена, расходующий может подделать фиктивный ivk и тем самым использовать разные nk при каждом расходовании. Различные значения nk порождают разные нуллификаторы для одной и той же ноты, что позволяет осуществлять двойное расходование.

Как схема обеспечивает эту привязку. Отношение pk_d = [ivk] g_d представляет собой скалярное умножение на эллиптической кривой (Q = [k]P), реализованное с использованием алгоритма удвоения-и-сложения. В схеме с нулевым разглашением верификатор не выполняет алгоритм напрямую; вместо этого схема ограничивает каждый промежуточный шаг. Корректная схема скалярного умножения должна обеспечивать, в частности, что базовая точка внутреннего цикла равна предполагаемой входной базовой точке (P_loop = P_input). Без этого ограничения схема может доказывать факт выполнения корректного скалярного умножения, но с неправильной базовой точкой, что делает всю цепочку привязки бессмысленной.

Анализ уязвимости

Уязвимый гаджет ECC использовался в отношении скалярного умножения, обеспечивающем выполнение условия pk_d = [ivk] g_d, где Q = pk_d, k = ivk, а P = g_d. Уязвимый код находится в реализации скалярного умножения с переменным основанием в репозитории halo2 (incomplete.rs L309-L310):

// incomplete.rs (полный исходный код по ссылке выше)
298  for (row, k) in bits.iter().enumerate() {
299      // z_{i} = 2 * z_{i+1} + k_i
         ...
305      z = region.assign_advice(|| "z", self.z, row + offset, || z_val)?;
306      zs.push(Z(z.clone()));
307
308      // Присвоить `x_p`, `y_p`
309      region.assign_advice(|| "x_p", self.double_and_add.x_p, row + offset, || x_p)?;  // BUG
310      region.assign_advice(|| "y_p", self.y_p, row + offset, || y_p)?;                  // BUG
311
312      // Если бит установлен, использовать `y`; если не установлен — использовать `-y`
313      let y_p = y_p
314          .zip(k.as_ref())
315          .map(|(y_p, k)| if !k { -y_p } else { y_p });
316
317      // Вычислить и присвоить lambda1
318      let lambda1 = y_a.zip(y_p).zip(x_a.value()).zip(x_p)
             .map(|(((y_a, y_p), x_a), x_p)| (y_a - y_p) * (x_a - x_p).invert());
         ...
     }

В схеме с нулевым разглашением доказывающий заполняет значения всех ячеек; сама схема не может копировать или передавать значения между ячейками — она может лишь определять ограничения, которые верификатор проверяет. Две строки, помеченные BUG, используют assign_advice() для записи координат базовой точки x_p и y_p (приватных входных данных схемы, известных как значения свидетеля) в вспомогательные столбцы схемы (область приватных входных данных доказывающего). Эта функция записывает значение без создания ограничения, связывающего его с внешней базовой точкой. Отдельное ограничение обеспечивает равенство базовых значений во всех итерациях цикла — доказывающий не может использовать разные базовые точки в каждой итерации. Однако доказывающий может подставить произвольную единственную базовую точку для всех итераций, и схема её не отвергнет, поскольку ни одно ограничение не привязывает базовые значения цикла к реальной g_d, переданной извне.

Корректная функция — это copy_advice(), которая записывает значение и добавляет ограничение равенства (ограничение копирования), обеспечивающее его соответствие реальной базовой точке g_d. Поскольку g_d меняется для каждого адреса (выводится из диверсификатора каждого адреса), схема не может жёстко закодировать её — она должна ограничивать базовую точку цикла, чтобы та соответствовала g_d, вычисленной выше по цепочке.

В результате схема фактически не обеспечивала выполнения условия pk_d = [ivk] g_d. Злоумышленник, выступающий в роли доказывающего, мог подставить произвольную базовую точку внутри цикла (вместо корректной g_d), и схема всё равно принимала бы доказательство: внутренние вычисления оставались алгебраически самосогласованными, но более не были привязаны к диверсифицированной базовой точке, заданной протоколом. Эта дополнительная степень свободы позволяет доказывающему каждый раз выбирать другой nk, вычислять соответствующий ivk = Commit(ak, nk, rivk) и использовать неограниченное скалярное умножение для того, чтобы поддельный ivk прошёл проверку. Поскольку нуллификатор зависит от nk, каждое расходование даёт отличный нуллификатор:

та же нота N + nk_1 → nf_1
та же нота N + nk_2 → nf_2
где: nf_1 ≠ nf_2

Консенсус проверяет лишь то, появлялся ли нуллификатор ранее в сети. Поскольку каждое расходование порождает уникальный нуллификатор, неотличимый от легитимного, двойное расходование остаётся невидимым для сети.

Исправление [3] добавляет вызов copy_advice() в первой итерации цикла (row == 0), создавая ограничение копирования, которое привязывает базовую точку цикла к реальному base, переданному извне. В остальных итерациях по-прежнему используется assign_advice(), однако существующее ограничение согласованности между итерациями распространяет привязку на все из них.

Последствия и реакция

Сценарий эксплуатации. Злоумышленник, выступающий в роли доказывающего, мог использовать уязвимость для многократного расходования одной и той же ноты Orchard, каждый раз генерируя разный нуллификатор. Поскольку доказательство с нулевым разглашением скрывает приватные входные данные схемы, мошеннические нуллификаторы неотличимы от легитимных. Атака не оставляет однозначных криптографических доказательств в сети, что делает невозможным однозначное определение факта её осуществления.

Уязвимость существовала с момента активации Orchard в мае 2022 года (обновление NU5), что даёт общее окно воздействия более четырёх лет. Механизм учёта оборотов (turnstile) Zcash ограничивает объём поддельных средств, которые могут выйти из пула Orchard в прозрачные пулы или пул Sapling, ограничивая тем самым реальное воздействие на общее предложение. Тем не менее поддельные ноты могли существовать незамеченными внутри защищённого пула, а его свойства конфиденциальности делают криптографическое доказательство факта эксплуатации уязвимости невозможным.

Примечание: механизм turnstile срабатывает только тогда, когда общий объём оттоков превышает общий объём притоков для пула. Злоумышленник мог выводить поддельные средства небольшими суммами с течением времени, не достигая этого лимита. Расхождение стало бы очевидным лишь в том случае, если бы легитимные пользователи в совокупности попытались вывести больше средств, чем фактически содержит пул.

Обнаружение и реакция. Уязвимость была обнаружена 29 мая 2026 года исследователем безопасности Тейлором Хорнби (работающим по контракту с Shielded Labs) с использованием фреймворка аудита на основе ИИ с моделью Anthropic Opus 4.8, выпущенной днём ранее. Предыдущие аудиты той же схемы с более старыми моделями не выявили ошибку. Хорнби в тот же день сообщил о проблеме в ZODL. Экстренный мягкий форк 2 июня (UTC) временно отключил транзакции Orchard, а обновление сети NU6.2 от 3 июня (UTC, блок 3 364 600) ввело исправленную схему, восстановив функциональность Orchard [1]. После публичного раскрытия информации 4 июня курс ZEC упал более чем на 40%, а объём ликвидаций превысил 100 миллионов долларов [4].

Заключение

Уязвимость Zcash Orchard была вызвана отсутствующим ограничением равенства в схеме скалярного умножения, позволявшим доказывающему обходить привязку базовой точки и подделывать нуллификаторы для двойного расходования. В отличие от традиционных ошибок в смарт-контрактах, которые зачастую можно выявить в ходе проверки кода или тестирования, ошибка корректности в ZK-схеме требует понимания разрыва между тем, что схема фактически доказывает, и тем, что она должна доказывать, — тонкость, которая оставалась незамеченной более четырёх лет профессиональными аудитами экспертов-криптографов.

Библиотека halo2 используется в экосистеме ZKP повсеместно, и аналогичные недостаточно ограниченные отношения могут присутствовать в других проектах, построенных на этих криптографических строительных блоках. Протоколам, использующим доказательства с нулевым разглашением, следует реализовывать проверки целостности баланса (например, механизм turnstile) для ограничения потенциального воздействия необнаруженных ошибок корректности: без механизма turnstile Zcash поддельные средства, созданные внутри защищённого пула, могли бы свободно перетекать в общее предложение. Shielded Labs объявила о планах по формальной математической верификации схемы Orchard.

Это открытие является типичным примером рабочего процесса с участием человека: опытный исследователь безопасности создал фреймворк аудита и направлял исследование, тогда как ИИ взял на себя широкий охват проверки отдельных ограничений схемы. Ни один компонент в отдельности не был достаточен: предыдущие запуски с использованием только ИИ на более старых моделях упустили ошибку, и годы экспертной проверки людьми также её не выявили. Хорнби сам является экспертом по безопасности Zcash — предметная экспертиза была необходима для определения правильного охвата аудита, в рамках которого ИИ мог работать. Как показывают недавние исследования BlockSec [5], модели ИИ стремительно прогрессируют в области анализа безопасности, однако для указания ИИ на правильные цели и валидации его находок по-прежнему необходимо экспертное руководство. Интерактивное сотрудничество между экспертами и ИИ — а не опора исключительно на ИИ — является наиболее эффективной моделью работы.

Ссылки

  1. The Orchard counterfeiting vulnerability and next steps, Zcash Community Forum, June 4, 2026. Ссылка
  2. halo2: A zero-knowledge proof system, GitHub. Ссылка
  3. Fix: anchor scalar multiplication base point via copy constraint, halo2 GitHub. Ссылка
  4. Why ZEC fell 40% even after Zcash patched a shielded pool bug, CoinTelegraph, June 5, 2026. Ссылка
  5. Re-Evaluating EVMBench: Are AI Agents Ready for Smart Contract Security?, arXiv, 2026. Ссылка

Get Started with Phalcon Security

Detect every threat, alert what matters, and block attacks.

Try now for free

О компании BlockSec

BlockSec — поставщик комплексных решений в области безопасности блокчейна и криптовалютного соответствия нормативным требованиям. Мы создаём продукты и услуги, помогающие клиентам проводить аудит кода (включая смарт-контракты, блокчейн и кошельки), перехватывать атаки в режиме реального времени, анализировать инциденты, отслеживать незаконные средства и выполнять обязательства по ПОД/ФТ на протяжении всего жизненного цикла протоколов и платформ.

BlockSec опубликовала множество научных работ по безопасности блокчейна на престижных конференциях, сообщила о нескольких атаках типа «zero-day» на приложения DeFi, предотвратила несколько взломов и спасла более 20 миллионов долларов, а также обеспечила безопасность криптовалют на миллиарды долларов.

Best Security Auditor for Web3

Validate design, code, and business logic before launch. Aligned with the highest industry security standards.

BlockSec Audit