배경
2025년 2월 21일 저녁, Bybit 거래소와 관련된 주요 보안 사고가 감지되었습니다. 그날 밤 02:16 UTC에 Bybit 콜드 월렛 (https://etherscan.io/tx/0xb61413c495fdad6114a7aa863a00b2e3c28945979a10885b12b30316ea9f072c )에서 시작된 대규모 전송을 감지했습니다.
401,346 ETH, 8,000 mETH, 90,375 stETH, 15,000 cmETH가 이체되었으며, 그 가치는 약 15억 USD입니다. 여러 차례의 확인 끝에 이는 Bybit에 대한 공격이라는 것이 판명되었습니다.
배경
거래소 지갑 아키텍처
일반적으로 거래소가 인터넷에 직접 접속할 수 있는 지갑을 핫 월렛이라고 합니다. 빈번한 이체가 필요하기 때문에 핫 월렛의 개인 키는 일반적으로 온라인 상태이며, 핫 월렛의 자금은 일반적으로 적고 거래소의 일일 거래량만 충족하면 됩니다. 거래소의 콜드 월렛은 일반적으로 거래소 자금의 대부분을 저장하며, 거래소의 기업 계좌와 동일합니다. 콜드 월렛은 핫 월렛 자금을 보충하는 등 특수한 조건에서만 사용됩니다. 따라서 콜드 월렛은 일반적으로 인터넷에 직접 접속하지 않는 오프라인 지갑이며, 대부분 거래소에서 사용하는 콜드 월렛은 다중 서명 지갑입니다. 이번에 Bybit의 콜드월렛도 예외는 아니며, Safe의 다중서명 지갑을 사용하고 있습니다.
대리점 계약
블록체인에 구축된 스마트 계약은 수정할 수 없지만, 비즈니스 변화로 인해 종종 문제에 부딪히기 때문에, 프록시 계약이라는 설계 메커니즘이 등장했습니다. 프록시 계약은 스마트 계약의 비즈니스 로직과 저장 데이터를 분리할 수 있게 해주는 디자인 패턴입니다. 핵심 메커니즘은 중개 계층으로 '프록시 계약'을 사용해 사용자의 거래 요청을 실행을 위해 논리 계약으로 전달하는 것이지만 최종 상태(데이터와 자산)는 프록시 계약에 저장됩니다. 일반적으로 프록시 계약은 투명 프록시, UUPS, 비콘 등으로 구분됩니다. 가장 흔한 것은 투명 프록시와 UUPS입니다. 모든 프록시 계약은 구현, 즉 논리 계약을 설정해야 합니다.
공격 및 사고 분석
자세한 분석을 한 결과, 공격자의 공격은 세 단계로 나뉘었습니다.
1단계
공격자는 2025-02-18 03:29:11 UTC에 공격 계약 0x96221423681A6d52E184D440a8eFCEbB105C7242를 배포했습니다. 계약을 배포하기 위한 거래는 https://etherscan.io/tx/0x84cd9d6cb84df9df4be638899f4a56053ed98042febd489ef3d51a3ed3652d40입니다. 나중에 이것을 공격 계약 7242라고 부르겠습니다.
이후 공격자는 2025-02-18 06:00:35 UTC에 또 다른 공격 계약 0xbDd077f651EBe7f7b3cE16fe5F2b025BE2969516을 배포했습니다. 계약을 배포하기 위한 거래는 https://etherscan.io/tx/0xc47ac9038127cef763a1c9a33309a645c5a4fa9df1b4858634ae596ccc2aee5e였습니다. 나중에 이것을 공격계약 9516이라고 부르겠습니다.
2단계
공격자는 Bybit의 다중 서명 지갑 3개가 https://etherscan.io/tx/0x46deef0f52e3a983b67abf4714448a41dd7ffd6d32d32da69d62081c68ad7882의 거래 해시를 사용하여 거래에 서명하도록 했습니다. 이 거래를 자세히 분석해 보겠습니다.
거래의 실행 흐름을 통해 이것이 실제로 거래보다 매우 간단하다는 것을 알 수 있습니다. 이는 거래에 대한 다중 서명 지갑의 서명을 받은 다음 안전 지갑을 호출하여 거래를 실행하는 것을 의미합니다. 실행되는 거래도 매우 간단한데, 공격 계약 7242의 전달 함수를 호출하는 것이고, 전달 함수의 _to는 공격 계약 9516이고, _value는 0입니다.
그러면 디컴파일을 통해 계약 7242를 공격하는 논리를 살펴보겠습니다.
그러면 생성된 토큰의 소유자가 런치패드 공식 웹사이트의 스마트 계약자임을 알 수 있습니다.
계약 7242의 전달 함수를 공격하는 것은 매우 간단한데, 즉 계약의 slot0을 전달 함수의 첫 번째 매개변수 수신자로 변경하는 것입니다. 다음으로, 실행 과정을 계속해서 관찰해 보겠습니다. 먼저, 안전 지갑의 프록시 계약은 delegatecall을 통해 안전 지갑의 impl 계약을 호출하고, 그런 다음 impl 계약은 delegatecall을 통해 공격 계약의 전달 함수를 호출합니다. delegatecall의 원리는 호출자의 컨텍스트를 사용하여 호출된 코드를 실행하는 것입니다. 따라서 공격 계약을 실행하는 컨텍스트는 안전 지갑의 프록시 계약이므로 수정된 slot0도 안전 지갑 프록시 계약의 slot0입니다. 안전 지갑의 프록시 계약 코드를 계속해서 살펴보겠습니다.
우리는 안전 지갑의 프록시 계약의 slot0이 안전 지갑의 논리적 계약 주소라는 것을 발견했습니다. 또한, 공격 계약 7242의 전달 함수의 기능은 slot0을 수정하는 것입니다. 그런 다음, 위의 프로세스를 실행한 후, 공격자는 안전 지갑의 논리적 계약 주소를 수정하여 계약 9516을 공격했습니다. 이 시점에서 Bybit의 콜드 월렛은 공격자에게 완전히 장악되었습니다.
3단계
공격자는 Bybit의 콜드 월렛을 인수한 후, 공격 계약 9516의 sweepERC20 및 sweepETH 함수를 호출해 콜드 월렛에 있는 모든 ERC20 토큰과 ETH를 이체했습니다. 이 시점에서 공격은 완료되었습니다. sweepERC20의 구체적인 구현을 살펴보겠습니다.
그 기능은 지정된 콜드 월렛에 있는 지정된 토큰 잔액을 대상 월렛으로 이체하는 것입니다. 공격자는 콜드 월렛에 90 USDT를 이체합니다.
8,000 메스
90,375달러
15,000cmETH
하나하나씩 돌아보세요. 다음으로, sweepETH의 구체적인 구현을 살펴보겠습니다.
이 함수의 주요 기능은 지갑에 있는 모든 ETH를 공격자가 지정한 주소로 전송하는 것입니다. 공격자는 이 기능을 사용하여 콜드 월렛에 있는 모든 ETH를 전송했고, 이로써 공격 단계는 완료되었습니다.
공격기술 발견
분석하는 동안, 우리는 공격자의 방법이 매우 세심하다는 것을 발견했습니다. 우리는 분석하는 동안 우리의 발견 사항을 자세히 설명할 것입니다:
1. 공격자는 먼저 주소 0x5C6120BA4C5B5E18DDcb9589e649e86EE6d540dD를 악용했습니다.
테스트를 위해 안전한 지갑을 만들었습니다.
그러고 나서 사슬을 이용해 공격을 연습했습니다.
이 함수 트랜잭션의 실행 과정을 볼 수 있습니다.
이후, 공격 계약 9516의 sweepERC20과 sweepETH도 하나의 블록에서 코인 출금을 테스트하는 데 사용되었습니다.
2. 공격 계약 7242와 공격 계약 9516은 모두 slot0을 수정하는 기능을 가지고 있습니다.
공격자는 복잡한 공격 계약인 공격 계약 9516을 직접 호출하지 않았지만 투명 프록시와 유사한 간단한 공격 계약 7242를 호출하여 콜드 지갑의 구현을 수정했습니다. 공격자는 호출되는 계약 기능이 너무 복잡하여 알려지지 않은 보호 기능이 작동하거나 관련 인력의 경계가 높아질 수 있다는 점을 걱정할 것으로 추측합니다. 게다가 공격 함수의 이름도 매우 기만적이다. '전송'이다. 공격자는 콜드 월렛의 구현 계약을 수정한 후 많은 양의 돈을 직접 이체하지 않고 먼저 90 USDT를 이체했습니다. 대량의 이체는 나중에 완료됩니다.
보시다시피 공격자는 먼저 테스트 목적으로 아주 소액의 돈을 이체했습니다. 사고를 방지하기 위해, 대량의 전송은 블록체인이 성공적으로 업로드된 후에만 이루어집니다. 모든 대규모 전송이 블록 번호 21895251에서 완료되었음을 알 수 있습니다.
풀리지 않은 미스터리
공격자가 다중 서명 메커니즘을 쉽게 침해하는 이유는 무엇입니까? 우리는 여러 가지 가능성을 나열합니다:
1. 첫째, 안전 지갑의 계약 또는 프런트엔드가 공급망 공격을 받았습니다. Bybit이 ETH에 대해서만 안전을 사용하는 것은 아니라는 것이 알려져 있습니다. 이 경우 안전 지갑을 사용하는 모든 지갑은 공격자에 의해 비워집니다. 이후 Safe는 심층적인 조사 결과 프런트엔드와 계약에 대한 공급망 공격이 없었다고 발표했습니다.
2. 다중 서명 보유자 중 하나가 공격자에 의해 침해되었고, 공격자는 이를 사용하여 이체를 시작했으며, 다른 사람들은 이를 주의 깊게 검토하지 않고 서명했습니다. 이렇게 많은 돈이 보관된 지갑의 개인키 보유자가 수행하는 모든 작업에는 통신이나 내부 프로세스가 필요할 수 있으므로, 상황을 알지 못한 채 누군가가 서명할 가능성은 낮다고 분석했습니다.
3. 모든 다중 서명 보유자는 공격자에 의해 침해를 받았으며, 공격자는 모든 다중 서명 보유자를 사용하여 서명하고 마침내 공격을 완료했습니다.
4. 공격자가 다중 서명 UI를 수정하여 다중 서명 보유자를 오도했습니다.
5. 공격자는 내부 시스템에 숨어서 전체 프로세스를 시작했습니다.
현재로서는 더 많은 정보가 공개되지 않는 한 공격자가 사용한 방법을 확실히 파악하기 어렵습니다. 하지만 확실한 것은 공격자가 신중한 예비 조사, 온체인 테스트 및 실험부터 다중 서명 보유자나 시스템에 대한 복잡한 공격에 이르기까지 온체인 및 오프체인 공격 방법에 매우 능숙하다는 것입니다. 또한 저희는 바이비트가 앞으로 더 많은 정보를 공개하기를 기대하며, 바이비트에 관련 기술 지원을 제공할 의향이 있습니다.
요약하다
이 공격으로 인해 Bybit Exchange는 총 15억 달러 의 손실을 입었으며, 이는 역사상 거래소에 가해진 가장 큰 피해로 기록되었습니다. 실제로 인도 거래소 WarirX에서도 비슷한 공격이 발생했습니다. 거래소는 막대한 자본을 보유하고 있기 때문에 종종 최고의 공격자들의 표적이 되며, 심지어 국가가 지원하는 APT로부터 공격을 받을 수도 있습니다. 따라서 거래소에서는 공격 위험을 줄이기 위해 다방면에서 보안 수준을 개선해야 합니다. 그러나 이에 국한되지는 않습니다. 다중 서명에 사용되는 오프그리드 장치(컴퓨터, 모바일 장치), 실행해야 하는 거래는 기대에 부합하는지 확인하기 위해 먼저 로컬에서 시뮬레이션하고, 전반적인 운영 및 일일 콘텐츠 처리 과정에서 여러 당사자에 의해 여러 번 검증합니다. 마지막으로, Web3 보안에 있어서는 어떤 단일 대책도 완벽한 해결책은 아닙니다. 무적을 유지하려면 공격자와의 싸움에서 끊임없이 능력을 향상시켜야 합니다.