지난 한 주(2026/08/10 - 2026/08/16) 동안 총 손실액 약 4,700만 달러에 달하는 다음 5건의 주요 보안 사건이 발생했습니다.
| 날짜 | 사건 | 유형 | 추정 손실액 |
|---|---|---|---|
| 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는 확인된 첫 번째 웨이브에서 40억 ONE이 발행되었으며, 광범위한 재구성 결과 약 3.01조 ONE이 위조 발행되었고 이 중 약 2.385조 ONE이 전송된 것으로 보고했습니다 [1]. 사건 발생 전 가격인 약 $0.001183 기준으로 위조 발행된 금액의 명목 가치는 약 35.6억 달러에 달하지만, 이는 ONE의 총 공급량의 약 200배에 해당하며 토큰의 시가총액을 크게 초과하는 수치이므로 실현 가능하거나 실현된 손실로 확인된 것은 아닙니다. Harmony는 이후 체인을 공격 이전 체크포인트로 롤백하여 위조된 상태를 폐기했습니다 [2]. 따라서 Harmony는 총 손실액 집계에서 제외되었습니다.
선정 사유
- Harmony: 체인 구현상의 재전송 방지(replay-protection) 결함으로 인해 Harmony 생태계 전반에 걸쳐 대규모의 무단 네이티브 토큰 발행이 가능해졌기 때문에 선정되었습니다. 조사 과정에서 별도의 사전 스테이킹(pre-staking) 정족수(quorum) 검증 취약점도 확인되었으나, 이 취약점이 실제 공격에서 어떤 역할을 했는지는 확인되지 않았습니다.
Best Security Auditor for Web3
Validate design, code, and business logic before launch
이번 주 주요 사건: Harmony
이번 주는 Harmony를 집중 조명합니다. 해당 결함이 애플리케이션 컨트랙트가 아닌 체인 구현 자체에 존재했기 때문이며, 이는 레이어1 전체의 기초 자산을 인플레이션시킬 수 있다는 점에서 이례적으로 파급력이 큰 실패 유형입니다.
2026년 8월 12일, 샤딩(sharded) 레이어1 블록체인인 Harmony는 크로스샤드 영수증 재전송(replay) 결함을 통해 네이티브 토큰인 ONE이 무단으로 발행되는 피해를 입었습니다. 대상 샤드(destination shard)는 소스 위원회(source committee)의 서명 범위에 포함되지 않은 필드를 사용하여 이미 소비된 영수증을 식별하고 있었기 때문에, 공격자는 해당 필드만 변조하여 정상적으로 이전에 입금 처리된 영수증을 다시 제출하고 소스 샤드에서의 대응 차감 없이 재차 입금 처리를 받을 수 있었습니다. Harmony는 확인된 첫 번째 웨이브에서의 40억 ONE 발행과, 광범위한 재구성을 통해 확인된 약 3.01조 ONE의 위조 발행 및 위조 발행 지갑에서 이체된 약 2.385조 ONE을 대사(reconciling)하고 있습니다. 이 수치들은 어느 것도 실현된 손실로 확인된 것은 아니며, 최종 영향은 롤백 및 거래소 대사 작업에 따라 달라질 수 있습니다 [1][2]. 조사 과정에서 Harmony는 별도의 사전 스테이킹(pre-staking) 정족수(quorum) 검증 결함도 확인했으나, 이번 공격이 이 결함에 의존했는지는 확인하지 않았습니다.
배경
Harmony는 샤딩(sharded) 레이어1 블록체인입니다. 각 샤드는 독립적인 상태를 유지하므로, 소스 샤드가 대상 샤드의 계정을 직접 수정할 수 없습니다. 샤드 간 가치 이동을 위해 Harmony는 비동기식 영수증 기반 설계를 사용합니다. 즉, 소스 샤드가 발신자의 잔액을 차감하고 크로스샤드 영수증을 발행하면, 대상 샤드가 이후 수신자에게 입금 처리를 합니다.
크로스샤드 영수증은 이체 자체를 기록합니다.
type CXReceipt struct {
TxHash common.Hash
From common.Address
To *common.Address
ShardID uint32
ToShardID uint32
Amount *big.Int
}
대상 샤드는 영수증 자체를 그대로 신뢰하지 않습니다. 영수증은 머클 증명(Merkle proof), 소스 블록 헤더, 그리고 해당 헤더에 대한 소스 위원회의 커밋 서명을 포함하는 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()
소스 샤드는 차감(debit)을 정확히 한 번만 수행하므로, 대상 샤드는 각 크로스샤드 영수증이 오직 한 번만 소비되도록 보장해야 합니다.
취약점 분석
크로스샤드 정산(settlement) 경로에는 두 가지 문제가 있었습니다. 소비된 영수증을 식별하는 방식에서의 재전송 방지 취약점과, 사전 스테이킹(pre-staking) 정족수(quorum) 검증 취약점입니다.
크로스샤드 영수증 재전송(Replay)
재전송 방지 로직은 영수증의 "소비됨" 마커를 기록하고 조회했지만, 그 키는 머클 증명의 두 가변 필드에서 파생되었습니다.
CXMerkleProof.ShardID
CXMerkleProof.BlockNum
Bloom 하드포크는 2026년 7월 13일 에포크(epoch) 2964에서 메인넷에 이를 강화했으며, IsCXMerkleProofReplayFixEpoch로 게이팅되었습니다 [3]. 서명된 Header.Epoch()가 해당 에포크 이상인 증명의 경우, IsSpent()와 WriteCXReceiptsProofSpent()는 위의 두 필드 대신 서명된 소스 헤더(Header.ShardID와 Header.Number)에서 소비됨 마커 키를 파생합니다. 그러나 이 강화된 키 생성 방식은 소급 적용되지 않았습니다. Header.Epoch()가 해당 포크 이전인 증명의 경우, 두 함수 모두 여전히 레거시 방식대로 MerkleProof.ShardID와 MerkleProof.BlockNum으로 폴백(fallback)했으며, ValidateCXReceiptsProof()는 이 에포크들에 대해 해당 필드들을 서명된 헤더에 결코 결부시키지 않았습니다.
이 두 필드는 소스 Header만을 포함하는 커밋 서명(commit signature)의 범위 밖에 있습니다. Header를 변조하면 VerifyHeaderSignature()에서 실패하지만, MerkleProof.ShardID나 MerkleProof.BlockNum을 변조해도 어떤 검증도 통과하지 못하게 되지 않았습니다 — 헤더 서명 검증도, 그리고 이 에포크들에 대해서는 해당 필드들을 Header와 결부시키지 않은 증명 검증도 마찬가지였습니다. 레거시 소비됨 마커 키가 이러한 인증되지 않은 필드에서 파생되었기 때문에, 영수증의 재전송 방지 식별자는 증명의 나머지 부분을 인증하는 서명과 분리되어 있었습니다. 동일한 서명된 헤더와 영수증을 담고 있지만 MerkleProof.ShardID나 MerkleProof.BlockNum 값이 다른 두 증명은 소비됨 추적 목적에서 서로 다른 것으로 취급되었습니다.

사전 스테이킹(Pre-Staking) 정족수(Quorum) 검증
두 번째 결함은 사전 스테이킹 정족수 검증에 영향을 미쳤습니다. uniformVerifier.IsQuorumAchievedByMask() 로직은 임계값을 다음 값과 비교했습니다.
len(mask.Publics)
이를 서명자 수로 간주한 것입니다. 그러나 mask.Publics는 특정 샤드와 에포크에 대한 위원회 전체 공개키 목록이지, 실제로 서명한 검증인(validator) 집합이 아닙니다. 실제 서명한 집합은 서명자 비트맵(signer bitmap)으로 표현됩니다. 그 결과, 서명자 비트맵이 비어 있어도 정족수 임계값을 통과할 수 있었습니다. 이는 해당 검증이 활성화된 비트맵 비트 수가 아니라 위원회 크기를 측정했기 때문입니다. 여기에 항등원(전부 0으로 이루어진) 집계 BLS 서명이 결합되면, 사전 스테이킹 시대의 소스 헤더가 충분한 정족수를 갖춘 것처럼 보이게 만들 수 있었습니다.

공격 분석
공격자는 하드포크 이전의 소스 샤드 블록에서 나온 정상적이고 이미 처리된 크로스샤드 영수증에서 출발한 뒤, 인증되지 않은 증명 식별자만 변조하여 이를 재전송했습니다. 위조 발행된 ONE은 4개의 공격자 지갑으로 발행되었습니다. 다음 분석은 트랜잭션 0xf3d4e8b1...8242c7f와 0x9a756ef9...b0a4d678를 기반으로 합니다.
-
1단계: 공격자는 하드포크 이전 소스 샤드 블록에서 유효한 과거
CXReceiptsProof를 획득했습니다. 이 증명에는 유효한 영수증, 유효한 소스 블록 헤더, 그리고 유효한 소스 위원회 커밋 서명이 포함되어 있었습니다. -
2단계: 대상 샤드는 이미 이 영수증을 한 번 소비했으며, 머클 증명 필드에서 파생된 키로 소비됨 마커를 기록해둔 상태였습니다.
-
3단계: 공격자는 서명된 헤더와 서명 범위에 포함되는 모든 필드는 그대로 둔 채, 인증되지 않은 증명 식별자 필드만 변조했습니다.
MerkleProof.ShardID MerkleProof.BlockNum -
4단계: 변조된 증명은 이후 대상 샤드 블록에서 수신 영수증으로 제출되었습니다.
IsSpent()는 변조된 필드에서 소비됨 마커 키를 파생했고 이전 마커를 찾지 못했으므로, 해당 영수증은 아직 소비되지 않은 것으로 보였습니다. -
5단계:
ValidateCXReceiptsProof()는 여전히 해당 증명을 수용했습니다. 변조된 식별자 필드는 서명 범위에 포함되지 않았던 반면, 서명 범위에 포함되는 모든 필드는 그대로 유지되었기 때문입니다: 헤더 해시와 아웃고잉(outgoing) 영수증 해시, 머클 증명의 블록 해시와 영수증 해시, 영수증 전체 해시, 그리고 커밋 서명과 비트맵. -
6단계:
ApplyIncomingReceipt()가 대상 샤드에서 실행되어db.AddBalance(*cx.To, cx.Amount)를 통해 수신자에게 다시 입금 처리되었습니다. 원본 크로스샤드 트랜잭션이 이미 정확히 한 번 실행되었기 때문에 소스 샤드에서는 이에 대응하는 차감이 발생하지 않았고, 그 결과 대상 샤드에서 네이티브ONE의 인플레이션이 발생했습니다.
결론
프로젝트 측이 확인한 근본 원인은 프로토콜 수준의 재전송 방지 실패였습니다. 크로스샤드 영수증의 소비 상태 식별자가 서명된 소스 헤더가 아니라 인증되지 않은 증명 필드에서 파생되었기 때문에, 이미 처리된 영수증이 두 번째로 입금 처리될 수 있었습니다. Harmony는 또한 별도의 사전 스테이킹 정족수 검증 결함도 확인했지만, 공개된 정보로는 공격자가 이번 사건에서 이를 실제로 활용했는지는 확인되지 않습니다.
패치는 두 취약점을 모두 해결했습니다 [4][5][6]. 더 넓게 보면, 체인 구현체는 이미 소비된 상태를 식별하는 데 사용하는 모든 필드를 반드시 인증해야 하며, 정족수는 전체 위원회가 아니라 실제로 서명한 검증인을 기준으로 판단해야 합니다.
참고 자료
- [1] Harmony 사건 업데이트
- [2] Harmony 롤백 계획
- [3] Harmony Bloom 하드포크 (PR #5053)
- [4] 커밋 61afbf6: CX 영수증 소비됨 마커 키 수정
- [5] 커밋 7515262: 정족수 비트맵 계산 수정
- [6] Harmony PR #5101
BlockSec 소개
BlockSec은 풀스택 블록체인 보안 및 암호화폐 컴플라이언스 제공업체입니다. 저희는 프로토콜 및 플랫폼의 전체 생애주기에 걸쳐 고객이 코드 감사(스마트 컨트랙트, 블록체인, 지갑 포함)를 수행하고, 실시간으로 공격을 차단하고, 사건을 분석하고, 불법 자금을 추적하며, AML/CFT 의무를 준수할 수 있도록 돕는 제품과 서비스를 구축합니다.
BlockSec은 저명한 학술대회에 다수의 블록체인 보안 논문을 발표했으며, 여러 DeFi 애플리케이션의 제로데이 공격을 신고했고, 다수의 해킹을 차단하여 2,000만 달러 이상을 구제했으며, 수십억 달러 규모의 암호화폐를 보호해왔습니다.
-
공식 웹사이트: https://blocksec.com/
-
공식 트위터 계정: https://twitter.com/BlockSecTeam



