За прошедшую неделю (10.08.2026 - 16.08.2026) в центре внимания оказались 5 заметных инцидентов безопасности с общими потерями примерно $47 млн.
| Дата | Инцидент | Тип | Оценочные потери |
|---|---|---|---|
| 2026/08/10 | Coinsbuy | Компрометация приватного ключа | ~$7.9M |
| 2026/08/10 | Unknown Whale Wallet | Компрометация приватного ключа | ~$25M |
| 2026/08/12 | Harmony | Проблема валидации | Неизвестно* |
| 2026/08/13 | Kite | Компрометация приватного ключа | ~$14M |
| 2026/08/15 | Fox | Изъян бизнес-логики | ~$117K |
*Harmony сообщила о подтверждённом первом раунде эмиссии 4 млрд ONE и о более широкой реконструкции, согласно которой было создано примерно 3.01 трлн ONE, из которых примерно 2.385 трлн ONE были переведены [1]. При цене до инцидента ~$0.001183 номинальная стоимость поддельных токенов составляет ~$3.56 млрд, однако это примерно в 200 раз превышает общее предложение ONE и значительно превышает рыночную капитализацию токена, поэтому такие потери не являются ни реализуемыми, ни подтверждёнными реализованными. С тех пор Harmony откатила блокчейн до контрольной точки, предшествовавшей атаке, отбросив поддельное состояние [2]. Поэтому Harmony исключена из общей суммы потерь.
Причины выбора
- Harmony: Выбрана, поскольку изъян в реализации защиты от повторного воспроизведения на уровне блокчейна позволил осуществить несанкционированную эмиссию нативного токена в огромных масштабах во всей экосистеме Harmony. В ходе расследования была выявлена отдельная уязвимость проверки кворума на этапе до стейкинга, хотя её роль в эксплойте не подтверждена.
Лучший аудитор безопасности для Web3
Проверяйте дизайн, код и бизнес-логику перед запуском
Главное событие недели: Harmony
Harmony оказалась в центре внимания на этой неделе, поскольку изъян находился в самой реализации блокчейна, а не в прикладном контракте — необычно опасный режим сбоя, поскольку он может привести к инфляции базового актива целого Layer-1.
12 августа 2026 года Harmony, шардированный блокчейн Layer-1, подверглась несанкционированной эмиссии своего нативного токена ONE из-за уязвимости повторного воспроизведения межшардовых квитанций. Целевые шарды идентифицировали уже использованную квитанцию по полям, не покрытым подписью исходного комитета, поэтому злоумышленник мог повторно предъявить подлинную, ранее зачисленную квитанцию, изменив только эти поля, и получить повторное зачисление без соответствующего списания на исходном шарде. Harmony проводит сверку подтверждённой первой волны эмиссии в размере 4 млрд ONE с более широкой реконструкцией, согласно которой было создано примерно 3.01 трлн ONE, из которых примерно 2.385 трлн ONE были переведены кошельком с поддельной эмиссией; ни одна из этих сумм не является подтверждённым реализованным убытком, и окончательное воздействие всё ещё зависит от отката и сверки с биржами [1][2]. В ходе расследования Harmony выявила отдельную уязвимость проверки кворума на этапе до стейкинга, хотя не подтвердила, полагался ли эксплойт на неё.
Предыстория
Harmony — это шардированный блокчейн Layer-1. Каждый шард поддерживает своё независимое состояние, поэтому исходный шард не может напрямую изменять аккаунт на целевом шарде. Для перемещения средств между шардами Harmony использует асинхронную схему на основе квитанций: исходный шард списывает средства с отправителя и формирует межшардовую квитанцию, а целевой шард впоследствии зачисляет средства получателю.
Межшардовая квитанция фиксирует сам перевод:
type CXReceipt struct {
TxHash common.Hash
From common.Address
To *common.Address
ShardID uint32
ToShardID uint32
Amount *big.Int
}
Целевой шард не доверяет голой квитанции. Квитанция передаётся внутри CXReceiptsProof, который содержит доказательство Меркла, заголовок исходного блока и подпись фиксации исходного комитета над этим заголовком:
type CXMerkleProof struct {
BlockNum *big.Int
BlockHash common.Hash
ShardID uint32
CXReceiptHash common.Hash
ShardIDs []uint32
CXShardHashes []common.Hash
}
type CXReceiptsProof struct {
Receipts CXReceipts
MerkleProof *CXMerkleProof
Header *block.Header
CommitSig []byte
CommitBitmap []byte
}
Обычный путь проверки валидирует доказательство относительно подписанного исходного заголовка и подписи его комитета:
VerifyIncomingReceipts()
-> IsSpent()
-> ValidateCXReceiptsProof()
-> VerifyHeaderSignature()
-> verifySignature()
-> DecodeSigBitmap()
-> IsQuorumAchievedByMask()
-> aggSig.VerifyHash()
Поскольку исходный шард выполняет списание ровно один раз, целевой шард обязан гарантировать, что каждая межшардовая квитанция используется только один раз.
Анализ уязвимости
Путь межшардовых расчётов содержал две проблемы: слабость защиты от повторного воспроизведения в способе идентификации использованной квитанции и слабость проверки кворума на этапе до стейкинга.
Повторное воспроизведение межшардовых квитанций
Защита от повторного воспроизведения записывала и искала маркер «использовано» квитанции, но её ключ формировался из двух изменяемых полей доказательства Меркла:
CXMerkleProof.ShardID
CXMerkleProof.BlockNum
Хардфорк Bloom усилил эту защиту в основной сети на эпохе 2964 (13 июля 2026 года), под контролем флага IsCXMerkleProofReplayFixEpoch [3]: для доказательства, чей подписанный Header.Epoch() соответствует этой эпохе или более поздней, IsSpent() и WriteCXReceiptsProofSpent() формируют ключ маркера «использовано» из подписанного исходного заголовка (Header.ShardID и Header.Number) вместо этих двух полей. Однако усиленное формирование ключа так и не было применено ретроактивно — для доказательства, чей Header.Epoch() предшествовал форку, обе функции сохраняли устаревший резервный вариант с MerkleProof.ShardID и MerkleProof.BlockNum, которые ValidateCXReceiptsProof() для этих эпох никогда не привязывал к подписанному заголовку.
Эти два поля находятся за пределами подписи фиксации, которая покрывает только исходный Header. Изменение Header привело бы к сбою VerifyHeaderSignature(), но изменение MerkleProof.ShardID или MerkleProof.BlockNum не нарушает никакой проверки вообще — ни подпись заголовка, ни валидацию доказательства, которая для этих эпох никогда не связывала их обратно с Header. Поскольку устаревший ключ маркера «использовано» формировался из этих неаутентифицированных полей, идентичность квитанции для целей защиты от повторного воспроизведения оказалась отделена от подписи, аутентифицировавшей остальную часть доказательства: два доказательства с одинаковым подписанным заголовком и квитанциями, но разными значениями MerkleProof.ShardID или MerkleProof.BlockNum, считались различными для целей отслеживания использования.

Проверка кворума на этапе до стейкинга
Вторая уязвимость затрагивала проверку кворума на этапе до стейкинга. Логика uniformVerifier.IsQuorumAchievedByMask() сравнивала порог с
len(mask.Publics)
рассматривая это значение как количество подписавших. Но mask.Publics — это полный список публичных ключей комитета для шарда и эпохи, а не набор валидаторов, фактически подписавших; этот набор представлен битовой маской подписавших. В результате пустая битовая маска подписавших могла всё же преодолеть порог кворума, поскольку проверка измеряла размер комитета, а не количество установленных битов маски. В сочетании с единичной (нулевой) агрегированной BLS-подписью это могло создать видимость достаточного кворума у заголовка источника эпохи до стейкинга.

Анализ атаки
Злоумышленник начал с подлинной, уже обработанной межшардовой квитанции из блока исходного шарда, предшествовавшего хардфорку, а затем воспроизвёл её, изменив только неаутентифицированную идентичность доказательства. Поддельные ONE были эмитированы на четыре кошелька злоумышленника. Следующий анализ основан на транзакциях 0xf3d4e8b1...8242c7f и 0x9a756ef9...b0a4d678.
-
Шаг 1: Злоумышленник получил действительное историческое
CXReceiptsProofиз блока исходного шарда до хардфорка. Доказательство содержало действительные квитанции, действительный заголовок исходного блока и действительную подпись фиксации исходного комитета. -
Шаг 2: Целевой шард уже использовал эту квитанцию один раз и записал её маркер «использовано», сформированный из полей доказательства Меркла.
-
Шаг 3: Злоумышленник изменил только неаутентифицированные поля идентичности доказательства, оставив подписанный заголовок и все поля, покрытые подписью, нетронутыми:
MerkleProof.ShardID MerkleProof.BlockNum -
Шаг 4: Изменённое доказательство было отправлено как входящая квитанция в более позднем блоке целевого шарда.
IsSpent()сформировал ключ маркера «использовано» из изменённых полей и не нашёл предыдущий маркер, поэтому квитанция выглядела неиспользованной. -
Шаг 5:
ValidateCXReceiptsProof()всё же принял доказательство, поскольку изменённые поля идентичности не были покрыты подписью, а все аутентифицированные поля остались неизменными: хэш заголовка и хэш исходящей квитанции, хэш блока и хэш квитанции в доказательстве Меркла, хэш квитанций, а также подпись фиксации и битовая маска. -
Шаг 6:
ApplyIncomingReceipt()выполнился на целевом шарде и повторно зачислил получателю средства черезdb.AddBalance(*cx.To, cx.Amount). Соответствующего списания на исходном шарде не произошло, поскольку исходная межшардовая транзакция уже была выполнена ровно один раз, что привело к инфляции нативногоONEна целевом шарде.
Заключение
Первопричина, подтверждённая проектом, заключалась в отказе защиты от повторного воспроизведения на уровне протокола: идентичность состояния использования межшардовой квитанции формировалась из неаутентифицированных полей доказательства, а не из подписанного исходного заголовка, поэтому уже обработанная квитанция могла быть зачислена повторно. Harmony также подтвердила отдельную уязвимость проверки кворума на этапе до стейкинга, хотя публичные раскрытия не устанавливают, использовал ли злоумышленник её в данном случае.
Патчи закрывают оба пробела [4][5][6]. В более широком смысле, реализация блокчейна должна аутентифицировать каждое поле, используемое для идентификации уже использованного состояния, и должна оценивать кворум по валидаторам, фактически подписавшим, а не по всему комитету.
Начните работу с Phalcon Explorer
Погружайтесь в транзакции, чтобы действовать разумно
Попробовать бесплатноИсточники
- [1] Обновление по инциденту Harmony
- [2] План отката Harmony
- [3] Хардфорк Harmony Bloom (PR #5053)
- [4] Коммит 61afbf6: исправление ключа маркера «использовано» CX-квитанции
- [5] Коммит 7515262: исправление подсчёта битовой маски кворума
- [6] Harmony PR #5101
О компании BlockSec
BlockSec — это полнофункциональный поставщик услуг безопасности блокчейна и криптовалютного комплаенса. Мы создаём продукты и сервисы, которые помогают клиентам проводить аудит кода (включая смарт-контракты, блокчейн и кошельки), пресекать атаки в реальном времени, анализировать инциденты, отслеживать незаконные средства и выполнять обязательства AML/CFT на протяжении всего жизненного цикла протоколов и платформ.
BlockSec опубликовала множество научных работ по безопасности блокчейна на престижных конференциях, сообщила о нескольких атаках нулевого дня на DeFi-приложения, заблокировала множество взломов, спасая более 20 миллионов долларов, и обеспечила защиту криптовалют на миллиарды долларов.
-
Официальный сайт: https://blocksec.com/
-
Официальный аккаунт в Twitter: https://twitter.com/BlockSecTeam



