Back to Blog

하모니 크로스샤드 ONE 민팅 + 약 4,700만 달러 키 손실 | BlockSec

Code Auditing
August 19, 2026
7 min read
Key Insights
  • 이번 주에는 약 4,700만 달러 규모의 손실이 확인된 5건의 주요 보안 사고가 다뤄졌습니다. 이 중 세 건은 개인 키 유출로 사용자 자금이 직접 이동한 사고였으며(Unknown Whale Wallet 약 2,500만 달러, Kite 약 1,400만 달러, Coinsbuy 약 790만 달러), 이번 주 대표 사고인 Harmony는 체인 구현상의 결함으로 위조된 ONE에 대해 실현 가능하거나 확정된 손실 금액이 없습니다(표의 주석 참조).

  • Harmony의 목적지 샤드는 크로스 샤드 영수증의 "사용됨" 마커를 서명된 소스 블록 헤더가 아닌 인증되지 않은 증명 필드(MerkleProof.ShardIDMerkleProof.BlockNum)로부터 도출했습니다. 이로 인해 공격자는 이 필드들만 조작하여 이미 크레딧된 영수증을 재생(replay)시킬 수 있었고, 소스 샤드에서 이에 상응하는 차감 없이 네이티브 ONE을 발행할 수 있었습니다. 스테이킹 이전 단계에서 발생한 두 번째 결함인 쿼럼 검증 오류는 서명자 비트맵에서 실제로 활성화된 검증자 수가 아닌 전체 위원회 규모를 기준으로 계산되었습니다.

  • 체인 구현체는 이미 소비된 상태를 식별하는 데 사용하는 모든 필드를 인증해야 하며, 쿼럼 판단은 전체 위원회가 아닌 실제로 서명한 검증자를 기준으로 이루어져야 합니다.

지난 한 주(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.ShardIDHeader.Number)에서 소비됨 마커 키를 파생합니다. 그러나 이 강화된 키 생성 방식은 소급 적용되지 않았습니다. Header.Epoch()가 해당 포크 이전인 증명의 경우, 두 함수 모두 여전히 레거시 방식대로 MerkleProof.ShardIDMerkleProof.BlockNum으로 폴백(fallback)했으며, ValidateCXReceiptsProof()는 이 에포크들에 대해 해당 필드들을 서명된 헤더에 결코 결부시키지 않았습니다.

이 두 필드는 소스 Header만을 포함하는 커밋 서명(commit signature)의 범위 밖에 있습니다. Header를 변조하면 VerifyHeaderSignature()에서 실패하지만, MerkleProof.ShardIDMerkleProof.BlockNum을 변조해도 어떤 검증도 통과하지 못하게 되지 않았습니다 — 헤더 서명 검증도, 그리고 이 에포크들에 대해서는 해당 필드들을 Header와 결부시키지 않은 증명 검증도 마찬가지였습니다. 레거시 소비됨 마커 키가 이러한 인증되지 않은 필드에서 파생되었기 때문에, 영수증의 재전송 방지 식별자는 증명의 나머지 부분을 인증하는 서명과 분리되어 있었습니다. 동일한 서명된 헤더와 영수증을 담고 있지만 MerkleProof.ShardIDMerkleProof.BlockNum 값이 다른 두 증명은 소비됨 추적 목적에서 서로 다른 것으로 취급되었습니다.

사전 스테이킹(Pre-Staking) 정족수(Quorum) 검증

두 번째 결함은 사전 스테이킹 정족수 검증에 영향을 미쳤습니다. uniformVerifier.IsQuorumAchievedByMask() 로직은 임계값을 다음 값과 비교했습니다.

len(mask.Publics)

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

공격 분석

공격자는 하드포크 이전의 소스 샤드 블록에서 나온 정상적이고 이미 처리된 크로스샤드 영수증에서 출발한 뒤, 인증되지 않은 증명 식별자만 변조하여 이를 재전송했습니다. 위조 발행된 ONE은 4개의 공격자 지갑으로 발행되었습니다. 다음 분석은 트랜잭션 0xf3d4e8b1...8242c7f0x9a756ef9...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]. 더 넓게 보면, 체인 구현체는 이미 소비된 상태를 식별하는 데 사용하는 모든 필드를 반드시 인증해야 하며, 정족수는 전체 위원회가 아니라 실제로 서명한 검증인을 기준으로 판단해야 합니다.

Get Started with Phalcon Explorer

Dive into Transactions to Act Wisely

Try now for free

Get Started with Phalcon Security

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

Try now for free

참고 자료

BlockSec 소개

BlockSec은 풀스택 블록체인 보안 및 암호화폐 컴플라이언스 제공업체입니다. 저희는 프로토콜 및 플랫폼의 전체 생애주기에 걸쳐 고객이 코드 감사(스마트 컨트랙트, 블록체인, 지갑 포함)를 수행하고, 실시간으로 공격을 차단하고, 사건을 분석하고, 불법 자금을 추적하며, AML/CFT 의무를 준수할 수 있도록 돕는 제품과 서비스를 구축합니다.

BlockSec은 저명한 학술대회에 다수의 블록체인 보안 논문을 발표했으며, 여러 DeFi 애플리케이션의 제로데이 공격을 신고했고, 다수의 해킹을 차단하여 2,000만 달러 이상을 구제했으며, 수십억 달러 규모의 암호화폐를 보호해왔습니다.

Sign up for the latest updates
~$160만 손실: Moke 토큰, LpdFi 익스플로잇 | BlockSec 위클리
Security Insights

~$160만 손실: Moke 토큰, LpdFi 익스플로잇 | BlockSec 위클리

2026년 8월 3~9일, BNB 체인에서 2건의 보안 사고가 발생해 총 약 160만 달러의 손실이 발생했으며, 모두 가격 조작이 원인이었습니다. LpdFi(약 69.7만 달러)는 PancakeSwap 유동성 풀을 주문 평가와 이자 정산에 동시 사용해 공격자가 원금을 부풀리고 과도한 이자를 탈취했습니다. Moke Token(약 90.6만 달러)은 조작 가능한 현물 가격과 중복 LP 배당 회계를 결합해 MOKE를 부풀려 BNB 배당을 반복 수령했습니다.

COLDCARD 사건: 지갑의 "무작위" 시드가 무작위가 아니었을 때
Security Insights

COLDCARD 사건: 지갑의 "무작위" 시드가 무작위가 아니었을 때

COLDCARD 펌웨어의 빌드 통합 버그로 비트코인 시드 생성이 취약한 소프트웨어 RNG로 라우팅되어 지갑 시드가 오프라인 복구 가능해졌습니다. 시드 자체의 취약점이므로 펌웨어 업데이트로 해결 불가하며, 2026년 8월 7일 기준 확인된 피해는 1,405 BTC(~9,100만 달러), 비공개 추정치는 최대 2,055 BTC입니다.

~$88M 손실: COLDCARD 및 LULA 익스플로잇 | BlockSec 위클리
Security Insights

~$88M 손실: COLDCARD 및 LULA 익스플로잇 | BlockSec 위클리

2026년 7월 27일~8월 2일, 비트코인과 BNB 체인에서 약 8,800만 달러 손실을 유발한 두 건의 보안 사고가 발생했습니다. COLDCARD 사고는 하드웨어 지갑 펌웨어의 엔트로피 오류로, RNG 매크로 활성화 여부 미확인으로 결정론적 폴백이 실행되어 약 1,370 BTC(~8,800만 달러)가 탈취됐습니다. BNB 체인의 LULA 토큰은 비즈니스 로직 취약점으로 `recycle()` 함수가 악용되어 PancakeSwap V2 유동성에서 약 57만 8천 달러가 유출됐습니다.

Best Security Auditor for Web3

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

BlockSec Audit