develicit
← 글 목록으로

63억 달러가 사라졌다 — 바이낸스 해킹으로 본 서명 위임의 역설

·읽는 시간 41분

TL;DR — 2026년 10월 29일 20:05 UTC, 바이낸스 핫월렛에서 자금이 빠져나가기 시작했다. 약 20분 동안 11개 체인에서 약 63억 달러가 사라졌다. 기록된 가상자산 탈취 중 가장 크다. 바이낸스는 개인키가 유출된 증거는 없다고 했다. 공격자는 키를 훔치지 않았다. 키로 서명하는 시스템에 원하는 트랜잭션을 넣었다. 이더리움에서는 EIP-7702 위임으로 핫월렛을 3시간 49분 동안 '스위퍼'로 바꿔 두었다.

1. 사건 개요 — 공식적으로 확인된 범위

바이낸스 공식 공지로 확인된 사실은 다음과 같다.

  • 출발점은 침해된 DevOps 엔지니어의 노트북이다. 공격자는 이를 통해 내부 서비스 컨테이너에 접근했다.
  • 그 컨테이너에서 승인되지 않은 출금 트랜잭션을 제출했다.
  • 지갑 개인키가 유출된 증거는 없다.
  • 손실은 약 63억 달러, 동결된 금액은 약 30억 달러다.
  • 손실은 SAFU 기금과 회사 자금으로 전액 보상한다.

이후 바이낸스는 노트북 외에 "추가 침투 지점"을 찾았다고 밝혔다. 리처드 텅 공동 CEO는 EIP-7702 위임에 대해 이렇게 말했다. "정상 승인 통제를 거치지 않았다(did not pass through our normal approval controls)."

아직 공개되지 않은 것 — 노트북이 처음 어떻게 감염됐는지는 알려지지 않았다. 추가 침투 지점이 무엇인지, 컨테이너가 서명 시스템에 어떤 권한을 가졌는지도 마찬가지다.

2. 20분의 타임라인

  1. 10-28 07:39
    Tornado Cash로 공격 지갑 충전
    0.1 ETH 풀에서 세 차례 출금(마지막은 10-29 08:23).
  2. 10-29 02:28
    시험·리허설
    시험 컨트랙트 배포 → 시험 지갑 3개에 위임 리허설 → 15:59 최종 스위퍼 배포.
  3. 20:05
    XRP Ledger 유출 시작
    바이낸스 지갑 5개에서 2억 3,346만 XRP. 이어서 Solana·Optimism 등.
  4. 20:20:59
    Binance 14에 EIP-7702 위임
    권한 50개를 담은 트랜잭션 하나로 핫월렛을 스위퍼에 위임. 같은 시각 BTC 18,270개 유출.
  5. 20:24:23
    트랜잭션 한 번으로 이더리움 유출
    ETH 167,464개와 토큰 63종을 한 번에 쓸어 감.
  6. 21:01 · 21:04
    Tether·Circle 동결
    수령 주소를 블랙리스트에 등록. 그 사이 USDT 약 6억 4,400만 개가 빠져나감.
  7. 22:15
    바이낸스 출금 중단
    출금은 멈췄지만 입금 모음 경로는 계속 장악된 지갑으로 자금을 보냄.
  8. 23:56:47
    마지막 스윕
    출금 중단 1시간 40분 뒤 들어온 입금 2,962 ETH까지 쓸어 감.
  9. 10-30 00:10:35
    바이낸스가 자기 키로 위임 해제
    위임 대상을 0x0으로 되돌림. 위임은 3시간 49분 동안 유지됐다.
  • 준비
  • 유출
  • 동결
  • 출금 중단
  • 위임 해제
Fig 1. 사건 전체 타임라인(UTC) — 36시간의 준비, 20분의 유출, 37분 뒤의 동결, 그리고 위임이 풀리기까지 3시간 49분.

3. 키는 안전했다 — 거래소 규모의 '서명 위임의 역설'

휴대폰의 Secure Enclave는 지갑 키를 절대 밖으로 내보내지 않는다. 그런데 멀웨어가 원하는 트랜잭션에 서명을 요청하면 어떻게 될까. 보안 영역은 그 요청에 그대로 서명해 준다. 키는 안전한데 자산은 털리는, 서명 위임의 역설이다.

바이낸스 사건은 이 역설이 거래소 규모에서 일어난 사례다. 구조를 나란히 놓으면 이렇다.

계층모바일 지갑바이낸스 핫월렛
키 보관Secure Enclave / StrongBoxHSM 또는 MPC 서명 시스템(구성 미공개)
서명 요청자지갑 앱내부 서비스 컨테이너
공격자가 장악한 곳멀웨어가 앱이나 사용자를 속임엔지니어 노트북 → 컨테이너
결과키는 그대로, 자산은 탈취키는 그대로, 11개 체인 자산 탈취
운영 영역
DevOps 엔지니어 노트북
최초 침투 지점
↓
내부 서비스 컨테이너
서명 요청 권한 보유
정상 경로
↓
리스크·정책 엔진
화이트리스트 · 한도 · 이상 탐지
↓
공격 경로
↓
정책 엔진 우회
"정상 승인 통제를 거치지 않았다"
↓
신뢰 경계
서명 영역
핫월렛 서명 시스템
개인키는 이 안에만 존재 — 유출 증거 없음

휴대폰의 Secure Enclave와 같은 구조다. 키는 경계를 넘지 않지만, 경계 안으로 들어온 요청에는 서명한다.

Fig 2. 서명 인프라의 신뢰 경계 — 키는 서명 시스템 안을 벗어나지 않았다. 공격자는 노트북에서 컨테이너로 들어간 뒤, 정책 엔진을 거치지 않는 경로로 서명 시스템에 요청을 넣었다.

Blockaid CEO는 이를 "키 탈취가 아닌 키 오용(key misuse)"이라고 불렀다. 다른 10개 체인의 지갑들은 키 종류도 서명 방식도 제각각이다. 그런데도 약 30분 안에 모두 정상 서명 거래로 송금했다. 이더리움의 두 번째 핫월렛도 위임 없이 일반 거래 9건으로 1억 7,400만 달러를 보냈다. 피싱으로는 이더리움만 설명할 수 있다. 그래서 TRM과 Elliptic은 공격자가 핫월렛 서명 인프라에 직접 명령할 수 있었다고 본다.

핵심 통찰 — "개인키는 유출되지 않았다"는 말이 안전을 뜻하지는 않는다. 보안 경계는 키가 있는 곳에서 끝나지 않는다. 서명을 요청할 수 있는 모든 경로까지 그어야 한다.

4. EIP-7702 기본 모델 — 위임 지정자와 nonce 규칙

EIP-7702는 EOA가 자기 코드를 스마트컨트랙트에 맡길 수 있게 한다. 이때 쓰는 것이 EOA가 서명한 권한(authorization)이다.

  • 권한은 (chain_id, address, nonce, y_parity, r, s) 튜플이다. type-4 트랜잭션의 authorization_list에 담겨 제출된다.
  • 권한이 적용되면 EOA의 코드 자리에 위임 지정자 0xef0100 || address가 기록된다.
  • 이후 이 EOA를 호출하면 address의 코드가 실행된다. 잔액과 저장소는 EOA의 것을 쓴다.
  • 위임은 새 권한으로 바꾸거나 address = 0x0으로 지울 때까지 유지된다.
  • 제출자와 서명자가 달라도 된다. 즉 서명만 있으면 누구든 제출할 수 있다.

이번 사건을 이해하려면 권한 처리 규칙 중 nonce 검사를 알아야 한다.

# EIP-7702 권한 처리 (명세를 단순화한 개념 코드)
for auth in tx.authorization_list:
    authority = ecrecover(auth)
    if auth.nonce != get_nonce(authority):
        continue                      # 실패한 권한은 조용히 건너뛴다 (트랜잭션은 계속)
    set_code(authority, b"\xef\x01\x00" + auth.address)
    increment_nonce(authority)        # 적용될 때마다 nonce +1

두 가지 성질이 중요하다.

  1. 실패한 권한은 트랜잭션을 되돌리지 않는다. 그래서 nonce가 다른 권한을 여러 개 넣어 둘 수 있다. 실행 시점에 하나만 맞으면 된다.
  2. 적용될 때마다 nonce가 1씩 오른다. 그래서 권한을 넣는 순서가 결과를 바꾼다(5.2절).

5. 공격 해부 — 온체인으로 직접 확인한 것

공개 보고서가 다루지 않은 부분은 온체인 기록에 남아 있다. 공격자 지갑과 Binance 14를 블록 단위로 따라가면 공격의 전 과정이 보인다.

5.1 36시간의 준비

공격자 EOA는 nonce 0부터 22까지 모두 23건의 트랜잭션을 보냈다.

시각(UTC)nonce내용
10-29 02:28:590시험용 컨트랙트 v1 배포
13:51:351시험 지갑 A에 위임
13:51:592시험 지갑 B에 위임
14:19:593시험 지갑 A 스윕 시험
14:24:114시험 지갑 B 스윕 시험
15:59:115최종 스위퍼 배포
16:20:476시험 지갑 C에 위임
16:25:597시험 지갑 C에 다시 위임
16:30:118시험 지갑 C 스윕 리허설
16:47:239시험 지갑 C에서 withdrawETH 시험
20:20:5910Binance 14 위임
20:24~23:5611~22스윕과 인출 12건(5.3절)

자금은 Tornado Cash 0.1 ETH 풀에서 첫 번째, 두 번째, 세 번째 출금으로 받았다. 공격 2시간 전에는 별도 가스 지갑이 1.08 ETH를 보냈다. 이 지갑의 첫 입금도 Tornado 0.1 ETH 풀이었다. 스위퍼 바이트코드에는 authorizedCaller()가 공격자 EOA로 고정돼 있다.

패턴 — 소액 Tornado 충전 → 시험 → 리허설 → 사전 서명 일괄 실행. TRM은 Bybit, KelpDAO 사건도 같은 순서였다고 본다.

5.2 권한 50개, 그리고 내림차순

처리 시점 nonce: 809·nonce는 앞자리 189147를 생략해 표시
오름차순이었다면
  1. 775 … 808건너뜀 · 34개
  2. 809 … 824적용 · 16개
↓
nonce 809 → 825 (+16)
이미 서명해 둔 출금(nonce 810~824)이 모두 무효 → 운영 알림
실제 — 내림차순
  1. 824 … 810건너뜀 · 15개
  2. 809적용 · 1개
  3. 808 … 775건너뜀 · 34개
↓
nonce 809 → 810 (+1)
다른 트랜잭션처럼 보임 → 흔적 최소화
Fig 3. 권한 50개를 어떤 순서로 넣느냐가 흔적의 크기를 바꾼다 — 오름차순이었다면 16개가 줄줄이 적용돼 nonce가 크게 뛰었겠지만, 실제 내림차순에서는 하나만 적용되고 나머지 49개는 조용히 실패했다.

위임 트랜잭션에는 권한 50개가 들어 있다. 대상은 모두 스위퍼다. nonce는 18914775부터 18914824까지 연속이다.

바이낸스 핫월렛은 쉬지 않고 출금을 처리한다. 그래서 nonce도 계속 오른다. 공격자는 연속된 nonce 50개의 권한을 받아 두고, 그중 하나만 맞기를 노렸다. 그런데 권한의 순서를 보면 더 흥미로운 점이 있다.

  • 권한은 nonce 내림차순(824 → 775)으로 들어 있었다.
  • 같은 블록 index 133에서 바이낸스가 자기 트랜잭션을 보냈다. 이 트랜잭션의 nonce는 18914808이다.
  • 공격 트랜잭션은 index 138이다. 그래서 실제로 적용된 권한은 18914809 하나다. 블록이 끝난 뒤 nonce는 18914810이었다.

왜 굳이 거꾸로 넣었을까. 오름차순이었다면 809가 적용된 뒤 nonce가 810이 된다. 그러면 다음 권한 810도 맞아서 또 적용된다. 이렇게 824까지 줄줄이 적용돼 nonce가 16이나 뛰었을 것이다. 바이낸스가 미리 서명해 둔 출금(nonce 810~824)은 모두 무효가 된다. 운영 알림이 바로 울렸을 가능성이 크다. 내림차순이면 하나가 적용된 뒤 나머지는 nonce가 작아서 조용히 실패한다. 흔적을 최소화하는 배열인 셈이다.

가스 사용량 1,258,562도 이 구조와 맞는다. 기본 21,000에 권한 50개 × 25,000을 더한다. 여기서 이미 존재하는 계정에 적용된 1건의 환급 12,500을 빼면 거의 같은 값이 나온다. 실패한 49개도 가스는 냈다.

그렇다면 이 권한들은 언제 서명됐을까. Binance 14의 nonce는 20:17:47에 18914775를 넘었다. 서명 범위의 시작값이 바로 그때의 nonce다. 이 지갑은 분당 약 10건을 처리한다. nonce 50개면 4~5분의 여유가 생긴다. 즉 공격자는 제출 약 3분 전에 실시간으로 권한을 받았을 가능성이 높다. TRM의 추정과도 맞는다. "접근 시간이 제한됐거나, 시스템을 거쳐 서명을 요청해야 하는 구조였을 것"이라는 추정이다.

5.3 3시간 49분 — 공격자 호출 12건

시각(UTC)함수결과
20:24:23sweepETH 167,464 + 토큰 63종(USDT 16억 1,541만 개 포함)
20:41:23callExecute바이낸스 스마트 계정에서 USDC 7억 8,000만 개 인출
20:59:47callExecute같은 계정에서 USDC 4,300만 개 인출
21:04:23sweepETH 1,700 + 토큰 23종
21:44:11sweepETH 370 + 토큰 14종
22:39:35sweepETH 128 + 토큰 122종
23:36:47, 23:37:23, 23:37:47, 23:38:23, 23:54:59sweep ×5잔액이 1 ETH 미만이라 옮긴 것 없음(자동 폴링)
23:56:47sweepETH 2,962
  • 스윕으로 빠져나간 ETH는 모두 약 172,624 ETH다. 매번 정확히 1 ETH를 남겼다.
  • callExecute는 Binance 14의 다른 권한을 이용했다. Binance 14는 별도 스마트 계정의 실행자였다. 위임과 함께 이 권한까지 공격자에게 넘어갔다. 노출 범위는 지갑 잔액에서 끝나지 않는다.
  • 23:56에 쓸어 간 2,962 ETH는 출금 중단(22:15) 1시간 40분 뒤에 들어온 입금이다. 바이낸스의 입금 모음 경로가 장악된 지갑으로 계속 자금을 보내고 있었다.

5.4 위임 해제 — 바이낸스는 서명 능력을 잃지 않았다

위임은 10월 30일 00:10:35에 이 트랜잭션으로 해제됐다. Binance 14가 직접 보낸 트랜잭션이고, 권한의 대상은 0x0이다.

  • 보낸 사람과 권한 서명자가 같은 자기 부담(self-sponsored) 권한이다.
  • 트랜잭션 nonce는 18914903, 권한 nonce는 18914904다. 보낸 사람의 nonce가 권한 처리보다 먼저 오르기 때문이다. 그래서 권한에는 nonce+1을 써야 한다.
  • 위임 중에도 바이낸스는 이 지갑에서 트랜잭션 93건을 보냈다. 마지막은 00:07:11이다.
  • 바이낸스가 자기 키로 위임을 풀었다. 서명 능력을 잃지 않았다는 뜻이다. "개인키는 유출되지 않았다"는 공식 설명과 맞는다.

6. 침투 메커니즘 — 증거에서 거꾸로 추론하기

바이낸스는 노트북에서 서명까지 이어진 경로를 공개하지 않았다. 하지만 드러난 증거만으로도 가능성을 꽤 좁힐 수 있다. 거래소 핫월렛의 일반 구조에서 출발해 보자. 그리고 증거가 어떤 경로를 허용하고 배제하는지 따라가 보자.

6.1 거래소 출금 파이프라인의 일반 구조

  1. 출금 서비스
    요청 생성
    ↓
  2. H3
    리스크·정책 엔진
    화이트리스트 · 한도
    ↓
  3. H1
    서명 오케스트레이터
    체인별 형식 변환
    ↓
  4. H2
    체인별 서명기
    HSM / MPC
    키 보관
    ↓
  5. 브로드캐스터
    체인에 전파
H4
운영 경로 — CI/CD · 클러스터 관리
위 모든 층의 코드와 설정을 바꿀 수 있다
  • H1서비스 자격증명으로 서명 API 직접 호출
  • H2원시 다이제스트 서명 경로 악용
  • H3정책 엔진 설정 조작
  • H4배포 경로(CI/CD) 오염
Fig 4. 거래소 출금 파이프라인의 일반 구조와 네 가지 가설이 닿는 지점 — 서명기는 키를 지키지만 들어온 요청에는 서명한다. 그래서 공격의 목표는 서명기 앞단의 어느 층이 된다.

대형 거래소의 핫월렛은 대체로 다음과 같은 층으로 나뉜다.

층역할이 층을 장악하면
출금 서비스사용자 출금과 내부 이체 요청을 만든다요청은 만들 수 있다. 하지만 정책 엔진을 통과해야 한다
정책 엔진주소 화이트리스트, 금액 한도, 속도 제한, 이상 징후를 검사한다무엇에 서명할지를 사실상 결정한다
서명 오케스트레이터요청을 체인별 형식으로 바꿔 서명기에 넘긴다모든 체인에 한 번에 닿는다
체인별 서명기HSM 또는 MPC 노드가 실제 키로 서명한다키는 지킨다. 하지만 들어온 요청에는 서명한다
운영 경로CI/CD로 서비스를 배포하고 클러스터를 운영한다위의 어느 층이든 코드나 설정을 바꿀 수 있다

휴대폰 지갑의 Secure Enclave가 그렇듯, 서명기는 키를 내보내지 않는다. 대신 들어온 요청에 서명한다. 그래서 공격자의 목표는 키가 아니다. 서명기 앞단의 어느 층이다.

6.2 증거가 남긴 제약 조건

관측된 사실근거메커니즘에 주는 제약
• 키 유출 증거 없음
• 위임 중에도 바이낸스가 93건 서명
• 위임 해제도 바이낸스가 직접 함
바이낸스, 온체인공격자가 얻은 것은 키가 아니라 서명 요청 권한이다
• 곡선이 서로 다른(secp256k1, ed25519) 11개 체인 지갑이 약 30분 안에 모두 유출TRM, Elliptic체인별 서명기를 하나씩 뚫은 게 아니다. 체인 공통의 상위 층에 닿았다
• 다른 체인은 정상 서명된 일반 출금으로 유출TRM, Elliptic서명 시스템이 받아들이는 정상 요청 형식을 썼다
• EIP-7702 위임은 "정상 승인 통제를 거치지 않았다"리처드 텅정책 엔진을 우회했다. 또는 정책 엔진이 해석하지 못하는 형식이었다
• 권한 50개를 제출 약 3분 전에 받음
• chainId는 1(메인넷 한정)
온체인미리 훔친 서명이 아니다. 실시간 서명 API 접근이다. 접근 시간이 제한됐을 수 있다
• 36시간 동안 시험과 리허설
• 정확한 권한 형식 사용
온체인공격자는 내부 서명 API의 사양을 미리 알고 있었다. 정찰 기간이 있었다는 뜻이다
• "추가 침투 지점"
• 공격자 도구의 "자기 파괴 장치"
바이낸스한 번의 클릭이 아닌 다단계 침투다. 흔적 제거로 포렌식도 늦어진다

6.3 가설 비교

가설내용맞는 증거맞지 않거나 불확실한 점
H1. 서비스 자격증명으로 서명 API 직접 호출침해된 컨테이너의 서비스 계정 토큰이나 mTLS 인증서로 서명 오케스트레이터를 직접 호출. 정책 엔진이 서명 경로 앞이 아니라 옆에 있다면 가능• 11개 체인 동시 유출
• 공식 설명("컨테이너에서 출금 제출")
• 실시간 접근
• 서명기가 정책을 다시 검사했다면 막혔어야 함
H2. 원시 다이제스트 서명 경로 악용서명 API에 32바이트 해시를 그대로 받아 서명하는 경로가 있었음. 여기에 7702 권한 다이제스트를 넣음(6.5절)• "7702는 승인 통제를 거치지 않았다"
• 다른 체인은 일반 출금 형식이었다는 차이
• 그런 API가 있었는지 미공개
H3. 정책 엔진 설정 조작화이트리스트와 한도를 바꿔 공격자 주소로의 출금을 통과시킴• 일반 출금이 "정상 서명"됨• 공식 표현은 통과가 아니라 우회
• 설정 변경 흔적에 대한 언급 없음
H4. 배포 경로(CI/CD) 오염DevOps 권한으로 서명 관련 서비스의 이미지나 설정에 악성 코드를 심음. Bybit에서 Safe 프런트엔드를 바꾼 방식과 같은 계열• 침투 지점이 "DevOps" 단말
• 자기 파괴 장치
• 추가 침투 지점
• 이미지가 바뀌었다면 배포 기록에 남음
• 그에 대한 언급 없음

이 제약을 한꺼번에 만족하는 가장 단순한 그림은 H1 + H2다. 흐름은 이렇다.

  1. DevOps 단말에서 클라우드와 클러스터 자격증명을 얻는다.
  2. 출금 관련 서비스 컨테이너에 들어간다.
  3. 그 컨테이너가 원래 가진 서명 요청 권한을 쓴다.
  4. 다른 체인에서는 일반 출금 형식으로 요청한다(H1).
  5. 이더리움에서는 정책 엔진이 해석하지 못하는 권한 다이제스트를 서명받는다(H2).

H4는 "DevOps"라는 침투 지점과 잘 맞아 배제할 수 없다. H3은 공식 표현과 가장 덜 맞는다.

6.4 최초 침투 — TraderTraitor의 알려진 수법

노트북이 어떻게 감염됐는지는 공개되지 않았다. 다만 배후로 지목된 TraderTraitor의 수법은 공식 기록으로 남아 있다.

사건최초 침투내부 이동
CISA 경고(2022)• 시스템 관리자와 DevOps 직원 대상 채용 사칭 스피어피싱
• 트로이목마를 심은 가상자산 앱
—
DMM Bitcoin(2024)• LinkedIn 채용 담당자를 사칭
• Ginco 직원에게 GitHub "채용 전 테스트"로 악성 Python 스크립트를 실행하게 함
• 탈취한 세션 쿠키로 직원 사칭
• 내부 시스템 접근
• 거래 조작
Bybit(2025)• Safe 개발자의 macOS가 Docker 프로젝트로 감염(소셜 엔지니어링 추정)• 활성 AWS 세션 토큰을 가로채 MFA 우회
• Safe 프런트엔드 코드 변조
• Bash 기록 삭제
• 악성코드 제거

세 사건은 같은 흐름을 따른다. 개발자와 운영자의 단말 → 세션 자격증명 탈취 → 정상 사용자로 위장한 내부 이동이다. 세션 토큰은 이미 MFA를 통과한 상태다. 그래서 탈취하면 MFA가 무력해진다. Bybit 공격자가 흔적을 지운 방식은 바이낸스가 언급한 "자기 파괴 장치"와도 비슷하다. 바이낸스의 노트북도 같은 길을 밟았을까. 이는 사후 분석 보고서가 답할 질문이다.

6.5 왜 권한 서명 하나가 출금 수천 건보다 위험한가

EIP-7702 권한 서명은 트랜잭션 서명과 다른 메시지에 서명하는 일이다.

EIP-1559 트랜잭션 서명:  keccak256(0x02 || rlp([chain_id, nonce, ..., to, value, data, ...]))
EIP-7702 권한 서명:     keccak256(0x05 || rlp([chain_id, address, nonce]))

서명기 입장에서는 둘 다 32바이트 해시일 뿐이다. 정책 엔진은 보통 디코딩한 트랜잭션을 검사한다. 받는 주소, 금액, calldata 같은 것이다. 그런데 권한 다이제스트에는 받는 주소도 금액도 없다. 서명 API에 원시 해시를 받는 경로가 있다면, 권한 서명은 정책 엔진에 아무것도 아닌 것처럼 보인다. H2가 공식 표현("승인 통제를 거치지 않았다")과 잘 맞는 이유다.

그리고 두 서명이 넘겨주는 권한의 크기는 전혀 다르다.

출금 트랜잭션 서명EIP-7702 권한 서명
범위자산 하나, 금액 하나, 한 번지갑의 모든 자산과 앞으로 들어올 입금까지
기간실행되면 끝해제할 때까지 유지
부수 권한없음이 지갑의 다른 컨트랙트 역할까지(5.3절 callExecute)
정책 엔진의 가시성받는 주소와 금액을 검사할 수 있음검사할 받는 주소도 금액도 없음

핵심 통찰 — 출금 서명은 금액에 대한 서명이다. 위임 서명은 계정 자체에 대한 서명이다. 서명 정책이 금액만 본다면, 가장 위험한 서명이 가장 덜 검사받는다.

7. 동결 경쟁 — 37분과 2억 USDT

수령 주소USDT 블랙리스트USDC 블랙리스트현재 잔액(동결)
0x5227…2f8c21:01:3521:04:59USDT 11억 7,546만, USDC 8억 2,300만
0xa97b…8d10—10-30 04:11:35USDC 약 12만
  • 첫 스윕(20:24)부터 Tether 동결(21:01)까지 37분이 걸렸다. 그 사이 약 6억 4,400만 USDT가 빠져나갔다.
  • 21:44 스윕은 이미 동결된 주소로 USDT 2억 40만 개를 보냈다. USDT 컨트랙트는 보내는 쪽만 블랙리스트를 검사한다. 받는 쪽은 막지 않는다. 그래서 이 돈은 도착하자마자 묶였다.
  • 공격자는 동결 1시간 38분 뒤인 22:39에야 수령 주소를 바꿨다.

양쪽 모두의 자동화 실패 — 바이낸스는 장악된 지갑으로 입금을 계속 보냈다. 공격자는 동결된 주소로 송금을 계속했다. 둘 다 상대의 상태를 확인하지 않는 자동화였다.

BTC, XRP, SOL, NEAR 같은 네이티브 자산은 동결할 수 없다. 실제로 동결된 적도 없다. Elliptic 집계로 공격자에게는 아직 약 33억 3,000만 달러가 남아 있다. 동결은 처분을 막는 조치일 뿐, 회수가 아니다.

8. 시장의 2차 효과 — 38% 프리미엄과 MEV

2,4002,8003,20020:3021:0021:3022:00해킹 전 ≈ 2,320위임Tether 동결정점 3,328.6 · 21:09:11WETH 가격 (USDT)

슬롯0(sqrtPriceX96)을 블록별로 조회한 값. 5분 간격 샘플에 블록 단위로 찾은 정점 두 곳(20:49:23, 21:09:11)을 더했다.

Fig 5. Uniswap v3 WETH/USDT 0.05% 풀 가격(UTC) — 공격자가 동결 전에 USDT를 서둘러 ETH로 바꾸면서 풀 가격이 해킹 전보다 최대 43% 높아졌다. 21:09:11 정점(3,328.6)은 HOW TO ONCHAIN이 보고한 '21:09, 시장가 대비 38% 할증'과 시각이 일치한다.

공격자는 동결 전에 USDT를 서둘러 ETH로 바꿨다. 그러면서 DEX와 CEX 사이에 큰 가격 차이가 생겼다. Elliptic은 공격자가 시세보다 12~26% 손해를 감수하고 속도를 택했다고 분석했다.

Uniswap v3 WETH/USDT 0.05% 풀 가격을 블록별로 보면 흐름이 선명하다. 해킹 전 가격은 약 2,320 USDT였다. 20:36부터 오르기 시작해 20:49에 2,917을 찍었다. 정점은 21:09:11의 3,328.6이다. 21:36에는 원래 수준으로 돌아왔다. HOW TO ONCHAIN이 보고한 "21:09, 시장가 대비 38% 할증"과 시각이 정확히 맞는다.

같은 분석에 따르면 이 차익은 대부분 MEV 봇에게 돌아갔다. WETH 차익거래 PnL 4,490만 달러 중 대부분을 봇 78개가 가져갔다. 그날 밤 ETH 우선순위 팁은 10,251 ETH였다. 전날 같은 시간대(4.6 ETH)의 약 2,200배다. 공격자가 서두른 만큼의 손해가 블록 자리를 산 봇의 이익이 된 셈이다.

9. 배후 — 확인된 것과 아닌 것

TRM Labs는 "높은 확신"으로 북한 TraderTraitor를 지목했다. Chainalysis와 Elliptic도 각자의 분석으로 같은 결론을 냈다. 반면 FBI는 "사건을 인지하고 파트너와 협력 중"이라고만 했다. 배후를 공식 지목하지는 않았다.

근거반론
Tron에서 THORChain과 Hyperlane을 거친 자금의 도착 주소가 2026년 9월 Bitget 해킹 자금 주소와 같음겹치는 금액은 약 3만 9,000달러. 같은 세탁망을 썼다는 증거일 뿐, 같은 해커라는 증거는 아닐 수 있음
소액 Tornado 충전 → 리허설 → 사전 서명 일괄 실행 패턴이 Bybit와 같음스테이블코인 26억 달러를 들고 있다가 동결당함. 빠르게 처분하던 북한 조직의 평소 방식과 다름
가짜 채용 등으로 거래소 엔지니어를 노려 온 이력(DMM, Bybit)노트북 최초 감염 경로가 아직 공개되지 않음

10. Bybit(2025)와의 비교

항목Bybit (2025.02)Binance (2026.10)
피해액약 15억 달러약 63억~64억 달러
침투 지점Safe{Wallet} 개발자 PCDevOps 엔지니어 노트북 + 추가 침투 지점
조작 대상멀티시그 서명자가 승인한 트랜잭션 내용핫월렛 서명 인프라(11개 체인)
공통점암호 기술이 아니라 지갑을 둘러싼 인프라와 사람이 뚫림같음

두 사건 모두 "누가 서명하는가"는 문제가 아니었다. 뚫린 것은 "서명할 대상을 누가 결정하는가"였다.

11. 방어 설계 — 서명 인프라를 보안 경계로

공격자DevOps 단말 침해 → 서명 요청 경로
↓
1운영자 단말 분리
§1 최초 침투
2컨테이너 최소 권한
§6.3 H1
3정책 엔진 직렬 배치
§5.2 위임
4서명기 자체 디코딩
§6.5 H2
5체인·등급별 서명 분리
§3 11개 체인
6위임 상태 실시간 감시
§5.3 3시간 49분
서명 시스템과 핫월렛 자산
Fig 6. 서명 인프라를 위한 계층 방어 — 바깥 단말부터 위임 감시까지 여섯 겹. 각 층 오른쪽은 이번 사건에서 그 층이 막았을 단계다.
완화 전략이번 사건에서 막았을 단계트레이드오프
• 서명기가 원시 해시를 받지 않고, 구조화된 요청을 스스로 디코딩한 뒤 서명6.5 권한 다이제스트 우회(H2)체인과 메시지 형식마다 파서 필요
• 서명기 단에서 정책을 한 번 더 검사(정책 엔진을 서명 경로 앞에 직렬 배치)6.3 서비스 자격증명 직접 호출(H1)지연 시간, 정책 이중 관리
• 서명 요청 권한을 서비스와 체인 단위로 쪼개고, 수명이 짧은 자격증명 사용6.3 컨테이너 하나로 11개 체인 접근자격증명 발급 인프라
• 서명 정책에서 EIP-7702 권한을 기본 거부5.2 위임 자체AA 전환 같은 정당한 위임에 별도 승인 절차 필요
• 여러 nonce의 권한을 한꺼번에 요청하면 침해 징후로 처리5.2 권한 50개 일괄 발급정상 운영에선 거의 없는 패턴이라 비용 낮음
• 트레저리 주소의 위임 상태 실시간 감시
• 미리 시험한 해제 절차
5.3 위임 3시간 49분 → 수 분감시 인프라 운영
• 위임 감지 시 입금 모음 경로 자동 차단5.3 23:56 스윕오탐 시 입금 처리 지연
• 서명 인프라를 체인과 지갑 등급별로 분리3절 11개 체인 동시 유출운영 복잡도
• 운영자 단말과 일상 업무 환경 분리
• 권한 상승에 별도 승인
1절 최초 침투개발 생산성

위임 감시는 생각보다 단순하다. 코드가 없어야 할 EOA에 위임 지정자가 생기는지만 보면 된다.

// 트레저리 EOA의 EIP-7702 위임 감시 (개념 코드)
const DELEGATION_PREFIX = "0xef0100"; // EIP-7702 위임 지정자 접두사
const POLL_INTERVAL_MS = 12_000;      // 이더리움 블록 시간(약 12초)마다 확인
 
async function watchDelegation(eoa: `0x${string}`, alert: (target: string) => void) {
  for (;;) {
    const code = await client.getCode({ address: eoa });
    if (code?.startsWith(DELEGATION_PREFIX)) {
      alert(`0x${code.slice(DELEGATION_PREFIX.length)}`); // 위임 대상 주소
    }
    await new Promise((r) => setTimeout(r, POLL_INTERVAL_MS));
  }
}

실제 운영에서는 폴링보다 빠른 방법이 있다. 새 블록의 type-4 트랜잭션에서 authorizationList 서명자를 복원해 대조하는 것이다. 그러면 권한이 블록에 포함되는 순간 알 수 있다.

실무 권고 — "키를 어디에 두느냐"보다 "누가 서명을 요청할 수 있느냐"가 더 중요하다. 서명 정책 엔진은 키 보관 장치만큼 중요한 보안 경계다. EIP-7702처럼 계정의 성격을 바꾸는 서명은 일반 출금과 다른 등급으로 다뤄야 한다.

12. 확인된 것과 남은 질문

확인된 것은 분명하다. 공격자는 DevOps 엔지니어의 노트북을 거쳐 내부 서비스 컨테이너에 들어갔다. 거기서 승인되지 않은 출금을 제출했다. 바이낸스는 개인키를 잃지 않았다. 이더리움에서는 nonce 50개에 걸친 EIP-7702 권한으로 Binance 14가 스위퍼에 위임됐다. 바이낸스는 3시간 49분 뒤 자기 키로 위임을 풀었다.

남은 질문도 분명하다. 노트북은 어떻게 감염됐는가. 추가 침투 지점은 무엇인가. 서명 요청은 어떤 경로로 정책 엔진을 우회했는가. 서명 시스템은 HSM이었는가, MPC였는가. 배후는 정말 TraderTraitor인가. 바이낸스의 사후 분석 보고서는 이 질문들에 답해야 한다. 특히 6절의 가설 중 어느 쪽이 맞았는지가 중요하다.

13. 결론

바이낸스는 키를 잃지 않았다. 잃은 것은 무엇에 서명할지 결정하는 권한이었다.

  • 키는 유출되지 않았지만 자산은 털렸다. 서명 위임의 역설이 거래소 규모에서 일어났다.
  • 보안 경계는 키가 아니라 서명 요청 경로까지 그어야 한다. 노트북 → 컨테이너 → 서명 시스템으로 이어지는 경로 전체가 위협 모델에 들어가야 한다.
  • 출금 서명은 금액에 대한 서명이고, 위임 서명은 계정에 대한 서명이다. 서명 정책이 금액만 본다면 가장 위험한 서명이 가장 덜 검사받는다.
  • 사고 대응의 속도가 피해 규모를 정한다. Tether 동결까지 37분, 위임 해제까지 3시간 49분이 걸렸다. 출금 중단 뒤에도 입금은 계속 들어왔다.

그렇다면 EIP-7702는 이번 사건의 원인이었을까. 다른 10개 체인은 7702 없이도 털렸다. 다만 이더리움에서는 위임 서명 하나가 지갑 전체를 넘겼다. 앞으로 들어올 입금까지였다. 같은 침투가 3시간 49분짜리 계정 탈취로 커진 이유다.

결국 물어야 할 것은 "EIP-7702가 위험한가"가 아니다. "우리 서명 시스템은 서명의 무게를 구분하는가"다. 금액을 옮기는 서명과 계정을 넘기는 서명은 같은 32바이트 해시로 보인다. 하지만 같은 등급일 수 없다. 무엇에 서명하는지 아는 것까지가 보안이다.

부록 — 직접 실험으로 확인하기

이 글의 온체인 주장은 공개 RPC만으로 재현할 수 있다. 필요한 것은 아카이브 조회가 되는 이더리움 노드 하나다.

  • 위임 시점과 해제 시점 — Binance 14에 블록 번호를 바꿔 가며 eth_getCode를 호출한다. 이분 탐색하면 두 블록이 나온다. 코드가 0xef010063e8…로 바뀐 블록 26300753과 0x로 돌아온 블록 26301896이다.
  • 권한 50개와 순서 — 위임 트랜잭션의 authorizationList에서 nonce를 읽는다. 18914824부터 18914775까지 내림차순이다.
  • 공격자 트랜잭션 전체 — 공격자 EOA의 eth_getTransactionCount가 바뀌는 블록만 재귀적으로 찾는다. 인덱서 없이도 nonce 0~22를 모두 복원할 수 있다.
  • 동결 시점 — USDT getBlackListStatus(address)와 USDC isBlacklisted(address)를 블록별로 eth_call 한다. 블랙리스트에 오른 블록이 나온다.
  • Uniswap 정점 — 풀의 slot0()에서 sqrtPriceX96을 읽어 가격으로 바꾼다. 21:09:11의 3,328.6을 확인할 수 있다.

출처

괄호 안은 해당 자료를 참고한 절이다.

공식 발표

온체인 분석 보고서

보도

TraderTraitor 과거 수법

표준

온체인 증거 (필자 직접 조회)

관련 글


댓글