Wormhole 브릿지 해킹: 3억 2,600만 달러 규모 익스플로잇 기술 분석
2022년 2월 2일, Wormhole 토큰 브릿지에서 120,000 wETH, 당시 약 3억 2,600만 달러 상당이 유실되는 사건이 발생했으며, 이는 DeFi 역사상 가장 큰 스마트 컨트랙트 익스플로잇 중 하나로 남아 있습니다. 이번 공격은 키 탈취, 소셜 엔지니어링, 또는 Guardian 검증자 네트워크의 과반수 장악을 필요로 하지 않았습니다. 단 한 가지가 원인이었습니다: 어느 계정을 읽고 있는지 검증하지 못하는 폐기된 Solana 프로그램 API였습니다.
이 익스플로잇을 이해하는 것은 Solana 기반 개발팀, 크로스체인 메시징에 의존하는 모든 프로토콜, 그리고 Solana 프로그램을 감사하는 모든 감사인에게 필수적입니다. 근본 원인은 Wormhole Solana 브릿지 프로그램 내 스마트 컨트랙트 검증 결함이었으며, 키 탈취나 Guardian 네트워크의 실패가 아니었습니다. Guardian 키는 한 번도 손대지 않았습니다. 브릿지 자체 코드가 공격자에게 절대 부여해서는 안 될 권한을 넘겨준 것입니다.
Wormhole 공격의 주요 기술적 취약점은 무엇인가?
취약점은 Wormhole Solana 브릿지 프로그램(bridge.so)의 verify_signatures 명령어에 내재해 있었습니다. 이 함수는 Guardian 노드들의 Ed25519 또는 Secp256k1 서명이 포함된 SignatureSet 계정이 진정한 합의를 표현하는지 검증한 뒤, Verifiable Action Approval(VAA)의 승인을 허가하는 역할을 맡았습니다.
문제는 verify_signatures가 이전에 같은 트랜잭션 내에서 Secp256k1 사전 검증 명령어가 호출되었는지 확인하는 데 사용한 solana_program::sysvar::instructions::load_instruction_at 함수가 폐기됐고, 이 함수가 읽는 계정이 실제 Solana instructions sysvar(Sysvar1nstructions1111111111111111111111111)인지 검증하지 않는다는 점입니다. 이 함수는 지정된 인덱스에 위치한 어떤 계정이든 읽어 들였으며, 공격자가 완전히 통제하는 계정도 포함됩니다.
공격자는 따라서 instructions sysvar 구조를 모방한 조작된 계정을 제출해, 공격자가 조작한 서명 데이터와 자신이 지정한 페이로드를 미리 채워 넣을 수 있습니다. 함수는 이 가짜 데이터를 읽고 Secp256k1 호출이 “존재하는 것”으로 판단한 뒤, VAA를 Guardian 승인된 것으로 표기하여 성공을 반환합니다.
위조된 VAA를 손에 쥔 공격자는 complete_wrapped를 호출하여 Wormhole 브릿지 프로그램의 VAA 승인 신뢰를 통해 Solana 상에서 래핑된 자산을 민팅할 권한을 얻었습니다. 결과는: Ethereum에서 어떤 ETH도 락업하지 않은 상태에서 120,000 wETH가 발행된 것입니다.
해당 취약점을 막는 수정사항, 즉 load_instruction_at를 실제 instructions sysvar 여부를 검사하는 load_instruction_at_checked로 교체하는 패치는 익스플로잇 발생 이전에 Wormhole GitHub 저장소에 커밋되었으나 아직 메인넷에 배포되지 않은 상태였습니다.
| 요소 | 설명 | 영향 |
|---|---|---|
폐기된 sysvar API |
_checked 없는 load_instruction_at 함수 사용; 지정 인덱스 계정에 대한 소유자 검증 부재 |
공격자가 진짜 instructions sysvar 대신 조작된 명령어 계정을 공급 가능 |
verify_signatures 우회 |
계정 출처 검증 없이 공격자가 조작한 SignatureSet을 Guardian 합의 증거로 승인 |
실제 Guardian 서명 없이 발행 권한 부여 |
계정 소유자 검증 누락 |
SignatureSet 계정 소유자가 instructions sysvar 프로그램(Sysvar1nstructions11...)인지 확인하지 않음 |
이 검증 누락이 전체 공격의 근간이 됨 |
래핑 자산 민팅 권한 |
Solana 브릿지 프로그램이 래핑 토큰에 대해 무제한 민팅 권한 보유; 승인된 VAA 하나로 권한 부여 | 120,000 wETH가 Ethereum에 락업된 ETH 없이 Solana에서 민팅됨; 당시 약 3억 2,600만 달러 |
Wormhole 해킹과 Ronin 등 다른 브릿지 공격의 차이점은?
Ronin 브릿지 해킹(2022년 3월, 약 6억 2,500만 달러)은 종종 Wormhole과 함께 브릿지 보안 실패 사례로 거론되지만, 본질적으로 완전히 다른 실패 모드입니다.
Wormhole은 Solana 브릿지 프로그램 내 스마트 컨트랙트 검증 버그였습니다. 19개 노드로 구성된 Guardian 네트워크는 전혀 침해당하지 않았습니다. 공격자는 verify_signatures가 어떤 계정을 읽는지 전혀 체크하지 않는 점을 악용해 Guardian 네트워크 자체를 우회했습니다. Guardian 키도 손대지 않았고 네트워크도 작동 중이었지만 코드가 실제 Guardian 합의를 조회하지 않았기에 의미가 없었습니다.
반면 Ronin은 운영 키 탈취 공격이었습니다. Sky Mavis는 Ronin 검증자 9개 노드 중 5개를 운영했고, 2021년 11월 Axie DAO가 일시적으로 서명 권한을 Sky Mavis에 위임하였으며, 이 위임이 만료 후에도 취소되지 않았습니다. 이후 Lazarus 그룹으로 추정되는 공격자가 Sky Mavis 내부 시스템에 침투해 4개의 검증자 키를 탈취했고, 활성화된 위임 권한을 이용해 다섯 번째 서명을 얻었습니다. 5개 서명으로 Ronin 브릿지에 합법적 인출 메시지를 제출했고, 스마트 컨트랙트 취약점은 없었으며 브릿지는 정상 작동했습니다.
| Wormhole (2022년 2월) | Ronin (2022년 3월) | |
|---|---|---|
| 공격 벡터 | Solana 프로그램 계정 검증 우회 | Sky Mavis 노드에 대한 소셜 엔지니어링과 자격 증명 탈취 |
| 익스플로잇 방식 | 폐기된 sysvar API로 위조된 SignatureSet 계정 제출 |
탈취된 검증자 키로부터 합법적 서명된 인출 명령 |
| Guardian / 검증자 네트워크 | 완전 온전함; 코드가 우회 | 네트워크 침해 — 공격자가 9개 중 5개 키 보유 |
| 피해 방식 | ETH 락업 없이 Solana에서 무단 민팅 | 유효 서명으로 Ronin 브릿지에서 직접 인출 |
| 탈취 금액 | 약 3억 2,600만 달러 (120,000 wETH) | 약 6억 2,500만 달러 (173,600 ETH + 2,550만 USDC) |
| 보안 인사이트 | Solana 프로그램에서 계정 소유자 검증은 필수; 스레시홀드 서명은 실제로 읽을 때만 의미 있음 | 스레시홀드 서명은 과반 키 탈취에는 무방비; 위임 취소는 엄격히 관리돼야 |
Wormhole 익스플로잇 실행 단계별 분석
-
계정 스푸핑. 공격자는 Wormhole 브릿지 프로그램의 명령어 데이터에서
SignatureSet위치에 들어갈 계정 구조를 모방한 Solana 계정을 생성했습니다. 이 계정에는 공격자가 직접 서명한 유효한 Ed25519/Secp256k1 서명이 포함됐으며, 이들은 공격자가 임의로 선택한 VAA 페이로드(자신의 Solana 주소로 120,000 wETH 민팅 승인)를 기준으로 했습니다. -
폐기된 sysvar API 우회. 공격자는
verify_signatures를 호출하는 트랜잭션을 제출했습니다. 브릿지 프로그램은 Secp256k1 명령이 같은 트랜잭션 내에서 이미 호출됐는지 확인하기 위해load_instruction_at(폐기되고 검증 없는 버전)을 사용했습니다. 이 함수는 지정된 인덱스 위치에 있는 계정이 실제 instructions sysvar인지 확인하지 않고 읽었습니다. -
위조 증거 수락.
verify_signatures는 공격자가 통제하는 계정 내 서명을 모두 확인했고, 서명들이 암호학적으로 유효하다고 판단(자신이 직접 서명했기에)하여 VAA를 Guardian 승인된 것으로 표시했습니다. Guardian 네트워크는 한 번도 참조되지 않았습니다. -
민팅 권한 부여. 공격자는 승인된 VAA를 가지고
complete_wrapped를 호출했습니다. 브릿지 프로그램은 VAA 승인 상태를 신뢰하고 공격자 주소로 120,000 wETH를 민팅했습니다. -
크로스체인 현금화. 공격자는 몰래 민팅한 wETH를 Wormhole의 정상적인 크로스체인 프로세스로 Ethereum으로 다리 건너 보냈습니다. wETH는 공격자의 Solana 지갑에 존재하므로 브릿지는 정상 인출로 처리했습니다. 공격자는 Ethereum에서 ETH 및 스테이블코인으로 전환 후 탈출했습니다. Wormhole 모회사인 Jump Crypto가 자체 준비금으로 120,000 ETH를 보충하여 사용자 피해를 복구했습니다.
Solana 프로그램과 크로스체인 브릿지를 위한 가장 중요한 기술적 교훈
1. Solana 프로그램에 전달되는 모든 AccountInfo는 유효성이 확인되기 전까지는 공격자가 통제한다고 가정해야 합니다.
이것이 Solana 프로그램 보안의 근간 규칙입니다. 프로그램은 전달받는 모든 계정에 대해 owner, key는 물론 상황에 따라 executable, is_signer 필드를 반드시 검증해야 합니다. 폐기된 load_instruction_at 함수는 지정된 위치에 어떤 계정이든 받아들였지만, 최신의 load_instruction_at_checked는 해당 계정이 진짜 instructions sysvar인지 반드시 확인합니다. Soken의 Solana 감사 방법론은 컨텍스트에 관계없이 _checked 없는 sysvar API 사용을 치명적(Critical) 결함으로 분류합니다.
2. 서명 검증과 자산 민팅 간 권한 분리
브릿지의 민팅 권한은 반드시 호출자가 공급한 증명이 아닌, 프로그램이 자체 검사한 정규 상태로부터 파생된 증명을 기반으로 하는 검증 모듈 뒤에 배치되어야 합니다. verify_signatures가 공격자 통제 계정을 신뢰한 시점에서 “네트워크가 승인했는가?”와 “민팅이 가능한가?”의 분리가 완전히 무너졌습니다. 민팅 명령은 실제 Guardian 입력을 확인한 후 프로그램이 기록한 상태에서 승인 권한을 가져야 합니다.
3. VAA 재사용 방지 기능은 체인상에서 엄격히 적용되어야 합니다.
진짜 SignatureSet이라고 가정해도 complete_wrapped는 이미 소비된 VAA 해시를 재사용하는 것을 거부해야 합니다. Wormhole은 이후 버전에서 재사용 방지 기능을 도입했으나, 취약하게 사용된 버전에선 위조된 승인 VAA가 반복 사용될 수 있었습니다. 모든 브릿지 작업은 원자적으로 실행 초기에 갱신되는 소비된 VAA 매핑(processed_vaas: mapping[bytes32, bool])을 통해 차단해야 합니다.
4. 폐기된 API 사용은 치명적 감사 항목입니다.
Wormhole 취약점은 이미 알려진 폐기 이슈였습니다. Solana SDK는 load_instruction_at 함수가 폐기됐으며 _checked 대체 버전을 배포 이전에 명확히 안내했습니다. 폐기된 API 미이행은 코드 품질 문제가 아니라 공격자가 릴리즈 노트를 검토하고 미배포 커밋과 배포된 바이트코드 차이를 비교하며 적극적으로 노리는 보안 크리티컬 격차입니다. Solana 프로그램 감사 시 solana_program::sysvar::instructions::* 내 비 _checked 변종을 철저히 탐색해 적발해야 하며, 이는 Ottersec, Halborn, Soken 등 주요 감사기관의 2022년 이후 표준 실무입니다.
5. 미배포 보안 패치는 공격자에게 공개된 공격 지도가 됩니다.
load_instruction_at_checked 수정사항은 익스플로잇 전에 Wormhole 공개 저장소에 커밋됐습니다. 보안 관련 커밋을 모니터링하는 정교한 공격자는 단순히 차이점만 보고도 취약점을 재구성할 수 있습니다. 보안 중요 프로그램 배포 파이프라인은 “메인 브랜치에 병합됨”과 “메인넷에 배포됨” 간 시간 간격을 곧바로 위협 노출 창으로 간주해야 하며, 긴급 배포 절차로 이 창을 수 시간 내에 닫도록 운영해야 합니다.
6. 스레시홀드 멀티시그는 계정 검증 실패를 보완하지 못합니다.
Wormhole Guardian 네트워크는 19개 독립 노드로 구성된 스레시홀드 서명 시스템으로 견고했습니다. 하지만 이번 공격에선 완전히 무의미했습니다. verify_signatures가 어떤 계정을 읽을지 조작 가능했기에 합의 계층 전체를 우회했기 때문입니다. 스레시홀드 서명은 Guardian 키 탈취에 대비하는 것이지, Guardian 확인을 전혀 거치지 않는 버그에는 전혀 의미가 없습니다. 다층 방어 체계는 각 보안 계층이 실제로 호출될 때만 가치가 있습니다. 우회된 통제는 통제란 존재하지 않는 것과 같습니다.
브릿지 감사와 Solana 프로그램 보안에 주는 시사점
Wormhole 익스플로잇은 크로스체인 브릿지 보안이 다층 문제임을 명확히 보여줍니다. Guardian 네트워크가 암호학적으로 완전하고 경제적 인센티브가 올바로 정렬되어 있으며 프로토콜 아키텍처가 견고해도, 온체인 프로그램의 단 한 줄 폐기된 함수 호출이 모든 것을 무용지물로 만들 수 있습니다.
Solana 기반 개발팀에는 계정 검증 교훈을 일반화할 수 있습니다: 프로그램에 전달되는 모든 파라미터를 적대적인 입력으로 간주하고, 소유자(owner), 키(key), discriminator, 데이터 길이를 반드시 검증한 후 계정을 조작하세요. Anchor 프레임워크의 Account<T> 래퍼나 유사한 방식을 사용하여 수동 검증 대신 타입 수준에서 검증을 강제하는 것을 권장합니다.
브릿지 설계자들에게는 권한 분리와 정규 상태 고정이 핵심 교훈입니다. 민팅 권한은 프로그램 자체가 검증한 프로그램 소유 상태에 근거해야 하며, 호출자가 제공하는 검증받지 않은 증거에 의존해선 안 됩니다.
Soken은 모든 Solana 프로그램을 대상으로 폐기된 sysvar API 사용, 누락된 계정 소유자 확인, VAA 재사용 방지 결함 등을 치명적 우선순위 항목으로 감사합니다. Wormhole 패턴 — 검증 함수가 읽는 계정을 조작해 멀티시그 스레시홀드를 우회하는 방식 — 은 현재 Soken Solana 감사 방법론에 공식 명명된 공격 분류입니다. 크로스체인 메시징 또는 래핑 자산 민팅을 사용하는 프로토콜이라면, 배포 전에 soken.dev/services-it.html 로 연락하여 보안 검토를 상담하시길 권장합니다.