Back to Blog

약 8,800만 달러 손실: COLDCARD 및 LULA 익스플로잇 | BlockSec Weekly

Code Auditing
2026년 8월 5일
9 min read
Key Insights
  • 이번 보고서에는 2건의 주요 보안 사고가 다뤄지며, 이는 비트코인과 BNB Chain 전반에서 약 8,800만 달러의 손실을 합산한 규모입니다. 단일 하드웨어 지갑 엔트로피 결함(COLDCARD)이 전체 손실의 99% 이상을 유발했으며, 이는 지갑 펌웨어 내의 조용한 빌드 구성 오류가 자금 보안이 의존하는 엔트로피를 무너뜨릴 수 있다는 경각심을 일깨워줍니다.

  • 두 사고는 서로 다른 취약점 패턴을 드러냅니다: 지갑 펌웨어의 결함 있는 엔트로피 생성(COLDCARD)에서는 시드 생성이 하드웨어 난수 생성기(RNG) 대신 결정론적 소프트웨어 유사난수 생성기(PRNG)로 조용히 전환되었고, BNB Chain 토큰(LULA)의 비즈니스 로직 결함에서는 공격자가 접근 가능한 경로를 통해 권한이 부여된 recycle() 함수를 트리거할 수 있었으며, 이를 통해 Rental 컨트랙트가 PancakeSwap V2 페어에서 LULA를 유출시키고 조작된 잔액으로 준비금(reserve)을 재동기화할 수 있었습니다.

  • COLDCARD 결함은 2021년에 출시되었으나 대규모로 악용되지 않았으며, 2026년 7월 말에 이르러서야 7월 30일부터 시작된 일련의 온체인 웨이브를 통해 영향을 받은 지갑들이 쓸려나갔습니다. 근본적인 실패 원인은 펌웨어가 시드 생성 API가 실제로 의도된 하드웨어 RNG에 도달했는지를 전혀 증명하지 않았다는 점이었습니다: 빌드 가드는 구성 매크로가 존재하는지만 확인했을 뿐, 그 값을 확인하지 않았습니다. 암호화 엔트로피를 위한 빌드 가드는 매크로 값을 확인하고 실패 시 폐쇄(fail closed)되어야 하며, 오프체인 서명 및 키 생성 구성 요소 또한 동등하게 엄격한 보안 검토가 필요합니다.

지난 한 주(2026/07/27 - 2026/08/02) 동안, 다음 2건의 주목할 만한 보안 사고가 발생했으며, 합산 손실 규모는 약 $88M에 달합니다.

날짜 사고 유형 추정 손실액
2026/07/29 LULA 비즈니스 로직 결함 ~$578K
2026/07/30 COLDCARD 결함 있는 엔트로피 생성 ~1,370 BTC (~$88M)*

* COLDCARD의 손실액은 확인 방식에 따라 달라집니다: 표시된 ~1,370 BTC (~$88M)는 공개적으로 검증 가능한 온체인 최소치이며(coldcardwatch.com 기준), 비공개 채널을 통한 대조 결과(Galaxy Research, 73명의 피해자와의 서신 교환 기반)에 따르면 이보다 높은 약 1,596 BTC로 추정되며, 의심되나 미확인 상태인 인출분까지 포함할 경우 최대 약 2,055 BTC (~$130M)에 이릅니다.

선정 이유

  • LULA: AMM 페어의 잔액을 이동시키고 준비금 재동기화를 강제할 수 있는 권한 있는 토큰 함수가, 가격 조작을 통해 반복 가능한 유동성 탈취 수단으로 변질되었습니다.
  • COLDCARD: 지갑 펌웨어의 빌드 및 통합 오류로 인해 시드 생성이 결정론적 소프트웨어 폴백을 통해 은밀하게 처리되면서 엔트로피 보장이 훼손되었고, 이는 시드 복구를 오프라인 탐색 문제로 만들어 대규모 자금 손실로 확대되었습니다.

Best Security Auditor for Web3

Validate design, code, and business logic before launch

이번 주 하이라이트: COLDCARD

이번 주 하이라이트로 COLDCARD를 선정한 이유는 지갑 엔트로피 버그가 이 기간 중 가장 큰 손실을 발생시켰기 때문입니다. 근본 원인은 구성 매크로가 활성화되었는지가 아니라 존재하는지를 검사한 빌드 가드였는데, 이는 기능 테스트로는 잡아낼 수 없는 종류의 은밀한 통합 오류이며, 이 교훈은 온체인 보안이 오프체인 무작위성에 의존하는 모든 시스템에 적용됩니다.

비트코인 하드웨어 지갑인 COLDCARD는 2021년, 의도된 하드웨어 난수 생성기(RNG) 대신 결정론적 소프트웨어 소스를 사용해 지갑 시드를 생성하는 펌웨어를 배포했습니다 [1][2]. 이 결함은 2026년 7월 말까지 대규모로 악용되지 않았으나, 7월 30일부터 시작된 온체인 파상 공격을 통해 영향을 받은 지갑들이 탈취되었습니다: 공개적으로 확인된 손실은 최소 1,370 BTC(8월 5일 기준 가격 $64,099로 환산 시 ~$88M)에 달하며 [3], 비공개적으로 확인된 보고에 따르면 이 수치는 약 1,596 BTC까지 높아질 수 있습니다 [4]. 근본 원인은 시드 생성을 의도된 하드웨어 RNG 대신 소프트웨어 폴백으로 라우팅한 빌드 및 구성 오류였습니다. 영향을 받은 기기의 경우, 이는 시드 복구를 암호학적으로 불가능한 문제에서 오프라인 탐색 문제로 바꿔버렸습니다.

배경

COLDCARD는 비트코인 하드웨어 지갑입니다. 지갑의 개인 키와 주소는 모두 단일 비밀 값인 시드에서 파생되므로, 모든 자기관리형 지갑의 보안은 그 시드의 두 가지 속성, 즉 비밀이 유지되는 것과 생성 시 예측 불가능한 것에 달려 있습니다. 하드웨어 지갑은 주로 첫 번째 속성을 보호하기 위해 존재하며, 이번 사고는 두 번째 속성의 실패입니다. BIP-39 시드 문구는 사람이 읽을 수 있는 형태이지만, 예측 불가능성 요구사항 아래에 있는 보안 속성은 여전히 그것을 생성하는 데 사용된 무작위 바이트의 엔트로피입니다. 그 바이트가 재현될 수 있다면, 시드도 재현될 수 있습니다. 직관적으로 비유하자면, 조합을 주사위를 굴려서 정하는 금고와 같습니다: 주사위가 조작되어 있다면, 그 편향을 아는 사람에게는 아무리 강력한 잠금장치라도 금고가 열려 있는 것과 같습니다.

지갑에게 "조작된 주사위"란 취약한 난수 생성기를 의미합니다. 하드웨어 지갑은 보안 마이크로컨트롤러의 하드웨어 진정난수 생성기(TRNG)로부터 시드 엔트로피를 얻어야 합니다. 소프트웨어 의사난수 생성기(PRNG)는 결정론적이기 때문입니다: 내부 상태와 호출 이력이 주어지면 그 출력을 정확히 재현할 수 있습니다. 생성기의 출력이 예측 가능하다면, 후보 범위를 열거하여 주소, xpub, 공개 키와 같은 공개된 지갑 데이터와 대조할 수 있으며, 이는 시드 복구를 암호학적으로 불가능한 문제에서 오프라인 탐색 문제로 격하시킵니다.

COLDCARD의 펌웨어는 두 개의 별도 RNG 표면을 노출했습니다. MicroPython은 지갑의 암호화 라이브러리가 기대하는 전역 rng_get() 심볼을 노출하는 STM32 플랫폼 레이어를 제공했으며, COLDCARD 또한 자체 보드 로컬 하드웨어-RNG 래퍼를 유지했습니다. 두 표면 모두 하드웨어 엔트로피를 제공하기 위한 것이며, 지갑의 암호화 라이브러리는 펌웨어 빌드 시 해석되는 단일 전역 RNG 심볼을 통해 이들 중 하나에 접근합니다.

취약점 분석

근본 원인은 MICROPY_HW_ENABLE_RNG 구성 매크로를 둘러싼 빌드 및 통합 오류였습니다. COLDCARD의 프로덕션 보드 구성은 이 매크로를 0으로 설정했는데, 펌웨어가 MicroPython의 하드웨어-RNG 구현이 아니라 자체 보드 로컬 하드웨어-RNG 래퍼를 사용하려고 의도했기 때문입니다. 그러나 지갑 생성 경로는 ngu.random.bytes(32)로 이관되었고, 암호화 라이브러리의 STM32 경로는 궁극적으로 MicroPython이 해석하는 전역 rng_get() 심볼에 의존했습니다.

문제의 흐름은 다음과 같았습니다:

generate_seed()
  -> ngu.random.bytes(32)
  -> libngu CHIP_TRNG_32()
  -> rng_get()
  -> MicroPython STM32 RNG module
  -> Yasmarang software fallback because MICROPY_HW_ENABLE_RNG == 0

보드 구성은 MicroPython의 하드웨어-RNG 분기를 비활성화했습니다:

// We have our own version of this code.
#define MICROPY_HW_ENABLE_RNG (0)

암호화 라이브러리는 여전히 이 매크로를 하드웨어 RNG의 충분한 증거로 취급했는데 [5], rng_get()을 호출하기 전에 매크로가 존재하는지만 확인했기 때문입니다:

extern uint32_t rng_get(void);
#define CHIP_TRNG_32() rng_get()

#ifndef MICROPY_HW_ENABLE_RNG
#error "get a HW TRNG plz"
#endif

이 가드는 위험한 경우를 놓칩니다: 매크로가 0으로 정의되어 있어도 여전히 정의된 상태이므로, #ifndef 검사는 통과하고 빌드는 성공합니다. MicroPython은 매크로의 존재 여부가 아니라 값에 따라 RNG 구현을 선택하기 때문에, MICROPY_HW_ENABLE_RNG == 0rng_get()을 COLDCARD의 보드 로컬 래퍼가 아니라 소프트웨어 폴백 분기로 라우팅했습니다 [6]:

#if MICROPY_HW_ENABLE_RNG
    // STM32 hardware RNG
#else
    // Yasmarang software fallback
#endif

그 결과는 기기 세대에 따라 다릅니다. Mk2/Mk3 펌웨어 v4.0.0-v4.1.9의 경우, Block의 분석 [7]에 따르면 ngu.random에 암호학적 엔트로피가 전혀 추가되지 않았으므로, 폴백 상태와 호출 이력이 알려지면 지갑 생성이 결정론적으로 변할 수 있습니다(Coinkite의 권고문 [2]은 Mk2/Mk3 범위를 v4.0.1-v4.1.9로 다소 좁게 규정합니다). Mk4/Q/Mk5의 경우, 보안 요소 자료가 해시되었지만 ngu.random.reseed()에는 4바이트만 전달되어, 보안 재시드가 단일 32비트 상태 워드로 제한되었으며, 이는 사용자가 기대하는 지갑 엔트로피보다 훨씬 작은 탐색 공간입니다. 최종 32바이트 난수를 해싱하는 것은 결과의 엔트로피를 증가시킬 수 없으며, 이미 제한된 후보 집합을 변형할 뿐입니다.

공격 분석

스마트 컨트랙트 익스플로잇과 달리, 이번 사고에는 추적할 수 있는 단일 온체인 공격 트랜잭션이 없습니다. 이는 오프라인 시드 복구 문제였고, 그 뒤를 온체인 탈취가 이었습니다. 전제 조건은 영향을 받은 사용자들이 취약한 ngu.random.bytes(32) 경로를 통해 지갑 시드를 생성했다는 것으로, 그들의 시드 자료가 완전한 하드웨어 엔트로피가 아니라 재현 가능한 소프트웨어 폴백 상태에 의존했다는 점입니다. 두 번째, 추론된 전제 조건은 영향을 받은 지갑이 시드만으로 파생 가능했다는 것입니다: 강력하고 고유한 BIP-39 패스프레이즈는 RNG 결함이 손대지 못한 독립적이고 사용자가 제공한 엔트로피를 PBKDF2를 통해 혼합하므로, 그런 지갑은 순수한 시드 열거의 범위 밖에 있으며, 탈취 규모로 미루어볼 때 영향을 받은 대부분의 사용자는 그러한 패스프레이즈를 설정하지 않았던 것으로 보입니다. 이로부터, 복구는 아마도 세 단계로 진행되었을 것입니다:

  1. 공격자는 기기 메타데이터, 부팅 타이밍, RTC/SysTick 가정, 그리고 그럴듯한 RNG 호출 이력을 사용해 후보 RNG 상태를 제한하거나 열거했습니다.
  2. 각 후보 상태에 대해, 공격자는 후보 지갑 시드를 도출하고 이를 주소, xpub, 생성된 공개 키와 같은 공개 지갑 데이터와 오프라인으로 대조했습니다.
  3. 후보가 실제 지갑과 일치하면, 공격자는 시드를 복구하고 개인 키를 재구성한 뒤 관련 BTC를 탈취했습니다.

온체인상으로, 이 도난 사건은 7월 30일부터 시작된 일련의 주소 탈취로 나타났습니다. 독립적인 온체인 휴리스틱 추적 [3]은 검증된 4,580개 주소에서 탈취된 최소 1,370 BTC(8월 5일 BTC 가격 $64,099 기준 약 $88M)에 달하는 여러 인출 파동을 확인했으며, 이는 검증된 최소치이지 총액이 아닙니다. 한편, 73명의 피해자와의 서신 교환을 통해 확인된 비공개 채널 [4]은 이 수치를 약 1,596 BTC까지 제시하며, 의심되나 미확인 상태인 인출분을 추가하면 2,055 BTC(~$130M)까지 상승할 수 있다고 밝힙니다.

결론

COLDCARD 사고는 엔트로피 생성 실패였습니다: 보안에 중요한 시드 생성 API가 의도된 하드웨어 RNG 대신 결정론적 소프트웨어 PRNG 폴백으로 은밀하게 해석되었는데, 이는 빌드 가드가 구성 매크로가 활성화되었는지가 아니라 존재하는지만 확인했기 때문입니다. 영향을 받은 기기의 경우, 이는 시드 복구를 암호학적으로 불가능한 문제에서 오프라인 탐색 문제로 바꾸었고, 그 결과 여러 파동에 걸쳐 1,370 BTC 이상이 탈취되었습니다 [3](비공개 채널 집계는 약 1,596에서 2,055 BTC로 제시합니다 [4]).

핵심적인 엔지니어링 실패는 배포된 펌웨어가 가장 보안에 중요한 API가 실제로 의도된 하드웨어 RNG에 도달했음을 결코 증명하지 않았다는 점입니다. 세 가지 관행이 이를 잡아낼 수 있었을 것입니다: 암호학적 엔트로피를 위한 빌드 가드는 매크로의 존재 여부와 값 모두를 확인해야 하며, 엔트로피 폴백은 소프트웨어 PRNG로 은밀하게 대체하는 대신 안전하게 실패해야 하고, 최종 펌웨어 이미지의 검증은 코드가 컴파일된다는 것뿐만 아니라 심볼 출처와 종단 간 엔트로피 흐름까지 다뤄야 합니다. 영향을 받은 시드는 그 자리에서 수정할 수 없습니다; 자금은 수정된 펌웨어로 생성된 지갑으로 옮겨야 하며, 강력하고 고유한 패스프레이즈는 시드를 복구하지는 못하더라도 즉각적인 노출을 줄여줍니다 [2].

이 실패 유형은 강조할 가치가 있습니다: 이런 종류의 무작위성 버그는 생성된 모든 시드가 개별적으로는 유효하기 때문에 기능 테스트로는 보이지 않습니다. 결함은 어떤 단일 출력에 있는 것이 아니라 그것들을 생성한 소스에 있습니다: 그 소스가 예측 가능하고 재현 가능하기 때문에, 시드들은 집합적으로 작고 열거 가능한 범위 안에 들어갑니다. 오프체인 키 생성 구성 요소는 최우선 수준의 보안 검토를 받을 자격이 있습니다.

참고 자료

Get Started with Phalcon Explorer

Dive into Transactions to Act Wisely

Try now for free

이번 주의 추가 사고

LULA

BNB Chain 상의 BEP-20 토큰인 LULA는 2026년 7월 29일, 토큰 컨트랙트의 비즈니스 로직 결함으로 인해 약 $578K의 손실을 입었습니다. 공격자가 접근 가능한 경로를 통해 권한 있는 recycle() 함수를 트리거할 수 있었으며, 이를 통해 Rental 컨트랙트가 PancakeSwap V2 페어에서 직접 LULA를 이체한 뒤 sync()를 호출하여 페어의 준비금을 조작된 잔액으로 업데이트할 수 있었습니다. 공격자는 recycle()을 반복적으로 트리거해 페어의 LULA 준비금을 거의 0에 가깝게 줄인 다음, 소량의 LULA를 스왑하여 거의 모든 USDT를 돌려받았습니다 [1].

배경

LULA는 임대(rental) 기반의 팀 보상 메커니즘을 갖춘 BNB Chain 상의 BEP-20 토큰입니다. 자격을 갖춘 주소들은 Rental 컨트랙트에 대기 중인 팀 보상을 적립하고 claimTeamReward()를 통해 이를 청구합니다. 청구 과정에서, Rental 컨트랙트는 토큰의 recycle() 함수를 호출하여 보상 분배를 위한 LULA를 확보합니다. recycle()은 임의의 사용자가 호출할 수 없으며, Rental 컨트랙트만이 이를 실행할 권한을 갖습니다.

claimTeamReward() 진입점에는 "EOA 전용" 검사가 포함되어 있습니다. 이는 msg.sender == tx.origin인 외부 소유 계정으로부터의 직접 호출을 지원하며, 위임된 코드 접두사를 검사하여 EIP-7702 위임 호출도 지원합니다.

자동화된 마켓 메이커(AMM)에서, 페어는 저장된 준비금을 기준으로 스왑 가격을 책정하며, 이 준비금은 페어의 sync() 함수를 통해 업데이트되어 페어의 현재 토큰 잔액으로 설정됩니다. 준비금은 일반적으로 스왑과 유동성 이벤트에 따라 변동하므로 실제 거래를 반영하지만, 페어의 토큰 잔액은 직접적인 이체를 통해서도 변경될 수 있으며, sync()는 조작 여부와 관계없이 현재 존재하는 잔액을 그대로 저장된 준비금에 복사합니다.

취약점 분석

근본 원인은 LULA.recycle()이 Rental 컨트랙트가 PancakeSwap V2 페어에서 직접 LULA를 이체한 뒤 sync()를 호출하여 페어의 준비금을 조작된 잔액으로 업데이트할 수 있도록 허용했다는 점입니다 [1].

sync()는 준비금을 페어에 남아 있는 LULA 잔액이 무엇이든 그대로 설정하기 때문에, 이 권한 있는 경로는 USDT 쪽은 그대로 둔 채 페어의 LULA 준비금을 임의로 낮출 수 있습니다. LULA 준비금이 거의 0에 가까워지면, 페어는 소량의 LULA를 거의 모든 USDT와 맞먹는 가치로 책정하게 됩니다.

공격 분석

다음 분석은 트랜잭션 0xa219ab9...411d7c를 기반으로 합니다.

  • 1단계: 공격자는 약 1억 9,705만 USDT를 축적하여 조작 자금을 마련했습니다. 이 자금은 Moolah/Lista, Aave V3, Venus, PancakeSwap V3, PancakeSwap Vault, Uniswap V4 PoolManager, Uniswap V3를 포함한 여러 플래시론 및 대출 출처에서 나왔습니다.
  • 2단계: 공격자는 약 1억 9,705만 USDT를 사용해 PancakeSwap V2 라우터를 통해 대규모 USDT -> LULA 스왑을 수행했습니다. 이로 인해 페어의 LULA 준비금이 약 800만 LULA에서 24,022 LULA로 급감했고, USDT 쪽은 약 1억 9,764만 USDT로 증가했습니다.
  • 3단계: 공격자는 여러 EIP-7702 지갑을 통해 보상 경로를 호출했습니다. 각 지갑은 Rental 컨트랙트의 claimTeamReward()를 호출했고, 이는 다시 LULA.recycle()을 트리거하여 페어의 LULA 준비금을 24,022 LULA에서 0.004 LULA로 줄였으며, 이 시점에도 페어는 여전히 매우 큰 USDT 잔액을 보유하고 있었습니다.
  • 4단계: 공격자는 라우터를 통해 마지막 PancakeSwap V2 스왑을 실행하여, 페어에 단 ~4,749 LULA만 넣고 ~1억 9,764만 USDT를 받아냈습니다.
  • 5단계: 공격자는 모든 플래시론을 상환하여 약 $578K의 이익을 얻었습니다.

결론

BNB Chain 상의 LULA 토큰은 토큰 컨트랙트의 비즈니스 로직 결함을 통해 약 $578K의 피해를 입었습니다: 공격자가 접근 가능한 경로를 통해 권한 있는 recycle() 함수를 트리거할 수 있었으며, 이를 통해 Rental 컨트랙트가 PancakeSwap V2 페어에서 직접 LULA를 이체한 뒤 sync()를 호출하여 페어의 준비금을 조작된 잔액으로 재동기화할 수 있었습니다. 공격자는 이를 반복적으로 트리거하여 페어 가격을 왜곡시키고, 소량의 LULA를 스왑하여 거의 모든 USDT를 돌려받았습니다.

토큰 컨트랙트는 AMM 페어의 잔액을 이동시키고 준비금 재동기화를 강제할 수 있는 권한 있는 경로를 절대 노출해서는 안 됩니다. 그렇게 하면 그 경로에 접근할 수 있는 누구에게나 가격 통제권을 넘겨주는 셈이기 때문입니다. AMM 페어와 통합되는 토큰은 페어의 준비금이 실제 시장에서 발생한 잔액 변화에만 묶여 있도록 유지해야 하며, 가격 책정을 위해 풀 준비금을 읽는 모든 로직은 이를 신뢰할 수 있는 값이 아니라 조작 가능한 값으로 취급해야 합니다.

참고 자료

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만 달러 이상을 구제했으며, 수십억 달러 규모의 암호화폐를 보호해왔습니다.

Best Security Auditor for Web3

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

BlockSec Audit