Back to Blog

솔라나 네트워크의 치명적인 버그가 어떻게 발견되고 적시에 패치되었는가

Code Auditing
2022년 6월 7일
5 min read

4월, 저희의 취약점 탐지 시스템은 Solana의 rBPF(즉, 모든 Solana dApp이 실행되는 가상 머신: https://github.com/solana-labs/rbpf)에서 문제를 발견했습니다. 면밀한 조사 끝에, 이것이 컨트랙트의 잘못된 실행 경로로 이어질 수 있는 보안 취약점임을 확인했습니다. 저희는 해당 버그를 Solana 보안팀에 보고했으며, 팀은 즉시 취약점을 확인하고 수정했습니다. 또한, 팀은 저희 팀에게 $800,000 USD 상당의 SoL 토큰을 지급했습니다.

이 취약점은 최신 버전의 rBPF(0.2.26~0.2.27)에 존재합니다. 저희가 문제를 보고했을 당시, 메인넷에서 사용되는 검증자들은 영향을 받는 버전으로 업그레이드되지 않은 상태였습니다. 저희 시스템은 영향을 받는 버전이 병합되기 전에 문제를 감지하여, 메인넷의 검증자가 이 취약점에 영향을 받지 않도록 했습니다.

이 취약점의 세부 사항에 대해 아래에서 자세히 설명합니다.

1. eBPF와 rBPF

eBPF(Extended Berkeley Packet Filter)는 원래 커널에서 패킷을 필터링하기 위해 개발되었습니다. eBPF의 보안성, 효율성, 확장성으로 인해 현재 네트워킹, 추적, 프로파일링 등 다양한 분야에서 활용되고 있습니다. eBPF의 풍부한 기능을 고려하여, Solana는 이를 스마트 컨트랙트의 실행 엔진으로 사용합니다. Solana에서 dApp을 개발하기 위해, 개발자들은 Rust로 스마트 컨트랙트를 작성하고 이를 eBPF 바이트코드로 컴파일합니다.

Solana는 Rust로 작성된 가상 머신인 rBPF를 사용하여 컴파일된 BPF 바이트코드를 실행합니다. 그러나 제안된 가상 머신(즉, rBPF)이 견고하고, 안전하며, 정확한지는 알 수 없습니다. rBPF 내부에 보안 문제가 존재할 경우, rBPF를 포함하는 모든 검증자에 영향을 미쳐 전체 Solana 네트워크에 막대한 손실(예: 자금 손실)을 초래할 수 있습니다.

2. 근본 원인

저희는 rBPF의 구현 버그를 자동으로 찾아내고 rBPF의 코드를 주기적으로 스캔할 수 있는 도구를 개발했습니다. 스캔 과정에서 rBPF(버전 0.2.26)에서 컨트랙트의 잘못된 실행 경로로 이어질 수 있는 심각한 문제가 발견되었습니다.

구체적으로, sdiv 명령어는 부호 있는 나눗셈 명령어로 사용되며, rbpf 0.2.26에서 기본 활성화된 기능으로 도입되었습니다. sdiv는 32비트(즉, sdiv32)와 64비트(sdiv64) 피연산자 모두에 대한 나눗셈을 지원합니다. sdiv32 명령어의 경우, 계산 결과는 64비트인 bpf 레지스터에 저장됩니다. 그러나 sdiv32 이후의 명령어가 계산 결과를 64비트로 읽으면 결과가 달라질 수 있습니다. 이는 rBPF가 JIT 컴파일 과정에서 sdiv32의 계산 결과를 올바른 64비트 값으로 부호 확장하지 않기 때문입니다.

예를 들어, 양수(즉, 12)를 음수(즉, -4)로 sdiv32를 사용하여 나눌 경우, 올바른 결과는 32비트와 64비트 모두에서 -3이어야 합니다. 아래 코드가 그 예시입니다.

JIT 모드와 인터프리티드 모드 모두에서 실행하고 추적한 후, 두 모드 간의 차이를 확인할 수 있었습니다:

2.1 인터프리티드 모드

0 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    29: lddw r5, 0x10000000c
 1 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 000000010000000C, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    31: sdiv32 r5, -4
 2 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, FFFFFFFFFFFFFFFD, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    32: jslt r5, 0, lbb_7
 3 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, FFFFFFFFFFFFFFFD, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    36: exit

2.2 JIT 모드

0 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    29: lddw r5, 0x10000000c
 1 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 000000010000000C, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    31: sdiv32 r5, -4
 2 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 00000000FFFFFFFD, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    32: jslt r5, 0, lbb_7
 3 [0000000000000000, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 00000000FFFFFFFD, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    33: lddw r0, 0x1
 4 [0000000000000001, 0000000400000000, 0000000000000000, 0000000000000000, 0000000000000000, 00000000FFFFFFFD, 0000000000000000, 0000000000000000, 0000000000000000, 0000000000000000, 0000000200014000]    35: exit

인터프리티드 모드에서는 레지스터 r5가 0xFFFFFFFFFFFFFFFD(32비트 및 64비트 모드 모두에서 -3)로 설정되는 반면, JIT 모드에서는 r5가 0x00000000FFFFFFFD로 설정됩니다. 이 경우, 64비트 값을 수신하는 jslt 명령어에서 r5는 양수(즉, 0x00000000FFFFFFFD)로 인식되어, 이후 실행 경로가 완전히 잘못됩니다.

3. 영향

이 잘못된 구현은 컨트랙트의 잘못된 실행 경로로 이어질 수 있으며 심각한 문제를 야기할 수 있습니다.

예를 들어, 스마트 컨트랙트의 필수 연산이 sdiv32 명령어의 결과에 의존할 경우, 잘못된 실행 결과로 이어질 수 있으며 공격자에 의해 악용될 수 있습니다.

이 문제는 https://github.com/solana-labs/rbpf/pull/283에서 도입되었으며, 이는 rBPF가 버전 0.2.26부터 취약하다는 것을 의미합니다. 저희는 2022년 4월 28일에 문제를 식별하고 Solana 보안팀에 보고했습니다. 팀은 저희의 보고에 신속히 대응하여 sdiv32 명령어에 부호 확장 연산을 추가함으로써 몇 시간 내에 문제를 수정했습니다. 수정 사항은 https://github.com/solana-labs/rbpf/pull/310에 있습니다. 저희 팀의 적시 탐지 및 보고 덕분에 메인넷의 검증자들은 이 취약점에 영향을 받지 않았습니다.

이 문제는 프로토콜 활성 버그로 분류되어 Solana로부터 $800,000의 버그 바운티가 지급되었습니다.

타임라인

  • 2022/04/28: 저희가 Solana 보안팀에 문제를 보고했습니다
  • 2022/04/29: 취약점이 수정되었습니다
  • 2022/05/09: CVE-2022-23066이 할당되었습니다
  • 2022/06/01: 버그 바운티가 지급되었습니다

BlockSec 소개

BlockSec 팀은 블록체인 생태계의 보안에 집중하며, 선도적인 DeFi 프로젝트와 협력하여 제품을 보호합니다. 팀은 학계와 산업계 모두에서 최고 수준의 보안 연구자와 경험 풍부한 전문가들로 구성되어 있습니다. 이들은 저명한 학회에서 다수의 블록체인 보안 논문을 발표하고, DeFi 애플리케이션의 여러 제로데이 공격을 보고했으며, 큰 영향을 미친 보안 사고에 대한 상세한 분석 보고서를 공개했습니다.

Twitter: [BlockSecTeam]

Medium: https://blocksecteam.medium.com

Website: https://www.blocksec.com

Sign up for the latest updates
약 557만 USD 손실: X100 Freezer·NEM 공격 | BlockSec 주간 보고서
Security Insights

약 557만 USD 손실: X100 Freezer·NEM 공격 | BlockSec 주간 보고서

이 주간 보고서는 2026년 10월 19일–2026년 10월 25일에 Ethereum과 BNB Chain에서 발생한 보안 사고 두 건을 다룹니다. 플래시론으로 자금을 조달해 X100 Freezer의 거버넌스를 장악한 사건과 BNB Chain의 NEM 토큰 유동성 풀에 영향을 미친 세금 정산 결함을 살펴봅니다. 보고서 범위에 포함된 추정 손실액은 X100의 대표 거래에서 발생한 약 475만 USD와 NEM 풀 사고에서 발생한 약 82.0만 USD를 합쳐 총 약 557만 USD입니다. 이 총액에는 별도로 보고된 후속 X100 자금 유출액은 포함되지 않습니다.

Autheo Network·UNCX 해킹으로 약 387만 USD 손실 | BlockSec 주간 소식
Security Insights

Autheo Network·UNCX 해킹으로 약 387만 USD 손실 | BlockSec 주간 소식

이 주간 보고서는 2026년 10월 12일–2026년 10월 18일 기간에 발생한 보안 사고 3건을 다루며, 총 추정 손실액은 약 387만 USD입니다. Autheo Network에서는 개인 키 침해로 약 176만 USD의 손실이 발생했고, Qubic Wallet에서는 취약한 시드 생성으로 약 130만 USD의 손실이 발생했습니다. UNCX Network의 Smart Token Vesting V2 계약에서는 Ethereum, BNB Chain, Base, Robinhood Chain에 걸쳐 약 80.7만 USD의 손실을 초래한 회계 오류가 발생했습니다. 중점적으로 다룬 UNCX 분석에서는 잘못된 지분 합산 계산이 서로 다른 토큰 대 지분 비율로 생성된 베스팅 트랜치를 혼합해 공유 풀에서 초과 인출을 가능하게 한 과정을 설명합니다.

약 54만 2천 달러 손실: MakerDaoBot 공격 | BlockSec 주간 소식
Security Insights

약 54만 2천 달러 손실: MakerDaoBot 공격 | BlockSec 주간 소식

2026/10/05~10/11 이더리움 보안 사고 1건의 추정 손실은 약 54.2만 달러입니다. 공격 컨트랙트가 악성 어댑터를 접근 제어가 없는 MakerDaoBot 함수에 전달하자 봇이 내부 MakerDAO 잔액 권한을 부여했습니다. 어댑터는 기존 ETH-A 경매 4건을 정산하고 담보 200 ETH-A를 WETH로 전환했습니다. 공격 컨트랙트는 이를 언래핑해 공격자에게 200 ETH를 보냈습니다.

Best Security Auditor for Web3

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

BlockSec Audit
솔라나 네트워크의 치명적인 버그가 어떻게 발견되고 적시에 패치되었는가