Back to Blog

주간 Web3 보안 사고 요약 | 2026년 3월 30일 – 4월 5일

Code Auditing
April 8, 2026
27 min read
Key Insights

지난 한 주(2026/03/30 - 2026/04/05) 동안, BlockSec은 9건의 공격 사고를 탐지 및 분석하였으며, 총 예상 손실액은 약 $287M입니다. 아래 표는 각 사고를 요약한 것이며, 각 사례에 대한 상세 분석은 이후 소절에서 제공됩니다.

날짜 사고 유형 예상 손실
2026/03/30 알 수 없는 프로토콜 사고 잘못된 비즈니스 로직 ~$10K
2026/03/30 WDGG 토큰 사고 접근 제어 ~$40K
2026/03/31 i6Token 사고 잘못된 비즈니스 로직 ~$273.8K
2026/04/01 Drift Protocol 사고 피싱 공격 ~$285.3M
2026/04/01 LML 스테이킹 프로토콜 사고 잘못된 비즈니스 로직 ~$950K
2026/04/01 Tactile 사고 가격 조작 ~$12K
2026/04/02 SAS 토큰 사고 잘못된 비즈니스 로직 ~$12K
2026/04/03 Unknown-EIP-7702 사고 접근 제어 ~$17.2K
2026/04/03 Silo Finance 사고 잘못된 설정 ~$359K

Web3 최고의 보안 감사 기관

출시 전 설계, 코드, 비즈니스 로직을 검증하세요

1. 알 수 없는 프로토콜 사고

간략한 요약

2026년 3월 30일, BNB Chain의 알 수 없는 프로토콜이 잘못된 비즈니스 로직으로 인해 약 $10K의 손실을 입었습니다. 해당 프로토콜은 사용자 예치금의 일부를 플랫폼 토큰 PSTART를 구매하고 유동성을 추가하는 데 사용하여, 사용자들이 시장 가격 변동에 노출된 LP 포지션을 실질적으로 보유하게 되는 구조였습니다. 그러나 출금 시, 프로토콜은 당시 LP의 실제 환매 가능 가치를 기준으로 정산하지 않았습니다. 대신 과거 예치금과 사전에 정의된 규칙에 따라 고정된 스테이블코인 금액을 지급하겠다는 약속을 유지했습니다. 그 결과, 공격자는 강제 투자를 통해 자본을 투입한 뒤, 사전에 합의된 고정 가치로 자금을 출금할 수 있었으며, LP 포지션이 부담해야 할 손실을 프로토콜로 전가하여 결국 무비용 이익을 실현했습니다.

배경

프로토콜의 동작 방식은 다음과 같습니다: 사용자가 BUSD를 예치하면, 프로토콜은 자동으로 자금의 일부를 사용하여 PSTART를 구매하고, 나머지 BUSD와 함께 풀에 유동성을 추가합니다. 생성된 LP 지분은 Vault가 보관하며, 프로토콜은 내부 장부에 고정 일일 수익을 약속하는 사용자 주문을 기록합니다.

이후 사용자는 고정 이율로 보상을 청구할 수 있으며, 출금 시 Vault는 기존 LP 포지션의 현재 실제 순자산 가치를 기준으로 엄격하게 환매하는 대신, 사전 정의된 규칙에 따라 원금과 수익을 정산합니다.

취약점 분석

이 취약점은 기저 자산의 실제 가치와 분리된 정산 로직을 가진 불합리한 프로토콜(0x587984...73a43c) 설계에서 비롯됩니다.

사용자가 BUSD를 예치하면, 프로토콜은 일부를 사용해 PSTART를 구매하고 유동성을 추가합니다. 즉, 사용자의 실제 기저 포지션은 시장 가격에 따라 가치가 변동하는 LP 노출입니다. 그러나 사용자가 출금할 때, 프로토콜은 당시 LP의 실제 환매 가능 가치를 기준으로 정산하지 않습니다. 대신, 과거 예치금액과 사전에 정의된 정산 규칙에 따라 고정된 스테이블코인 금액을 지급하겠다고 약속합니다.

공격자는 이 결함을 이용해 플래시 론으로 대량의 자본을 확보한 뒤 deposit()을 반복적으로 실행했습니다. 이를 통해 프로토콜이 지속적으로 PSTART를 구매하고 풀의 자산 구성을 변경하도록 강제하여 PSTART 가격을 인위적으로 끌어올리고 차익 거래 기회를 만들었습니다.

그 후 공격자는 withdraw()를 실행하여 사전에 약속된 고정 가치로 자금을 환매함으로써, 기저 LP 포지션이 부담해야 했던 손실을 프로토콜 자체로 전가하여 결국 무비용 이익을 달성했습니다.

공격 분석

다음 분석은 트랜잭션 0xf3b8...55e7을 기반으로 합니다.

  • 1단계: 공격자는 플래시 론을 통해 약 2,000,000e18 BUSD를 확보하고, 풀에서 19,013,120e18 PSTART로 교환했습니다.

  • 2단계: 공격자는 계약의 deposit() 함수를 반복적으로 호출하여 자금을 스테이킹했습니다. 매번 예치 시, 프로토콜은 유동성 추가에 사용되는 최종 토큰 대 BUSD 비율이 풀의 현재 비율과 더 잘 맞도록 토큰 구매에 사용할 BUSD 금액을 계산했습니다. 반복 예치를 통해 공격자는 풀에 지속적으로 BUSD를 주입했으며, PSTART 수량은 거의 변하지 않았습니다. 그 결과 PSTART 가치는 계속 상승했습니다. 이 단계에서 공격자의 예치를 통해 획득한 LP는 실제로 손실을 감수하며 취득된 것이었습니다.

  • 3단계: 공격자는 1단계에서 구매한 PSTART를 풀에 다시 매도했습니다. 2단계에서 풀의 BUSD 준비금이 증가했기 때문에, 이 스왑으로 약 2,010,655e18 BUSD가 반환되어 단일 공격 사이클에서 약 10,655 BUSD의 이익이 발생했습니다.

  • 4단계: 마지막으로, 공격자는 2단계에서 시작한 모든 스테이킹 포지션에 대해 withdraw()를 실행했습니다. 이 시점에서 해당 포지션에 해당하는 자산의 시장 가치는 이미 초기 예치 가치를 훨씬 밑돌았습니다. 정상적인 경제 논리 하에서는 전액 환매가 불가능했어야 합니다. 그러나 프로토콜은 과거 예치 금액을 기준으로 환매 가능한 BUSD 금액을 계산하여, 공격자가 이전에 강제 투자한 모든 비용을 손실 없이 전액 회수할 수 있었습니다.

결론

이 사고의 근본 원인은 프로토콜이 사용자 자금을 시장 가격 변동에 노출된 LP 포지션에 투자하면서도, 과거 예치 가치와 사전 정의된 규칙에 따라 고정된 BUSD 금액으로 정산할 것을 약속했다는 점입니다. 이로 인해 프로토콜의 부채와 기저 자산의 실제 가치 사이에 괴리가 발생했습니다.

공격자는 이 결함을 이용해 deposit()을 반복적으로 사용하여 풀의 자산 구조를 변경하고 PSTART 가격을 끌어올린 뒤, 외부 포지션을 통해 차익 거래를 완료하고, 마지막으로 withdraw()를 사용하여 이전에 손실이 발생한 포지션을 장부 가치로 환매했습니다. 이 방식으로 포지션 자체가 부담해야 할 손실을 프로토콜로 전가하여 결국 무위험 이익을 실현했습니다.


Phalcon Explorer 시작하기

트랜잭션을 심층 분석하여 현명하게 행동하세요

지금 무료로 체험하기

2. WDGG 토큰 사고

간략한 요약

2026년 3월 30일, BNB Chain의 WDGG 토큰이 익스플로잇되어 약 $40K의 손실이 발생했습니다. 근본 원인은 burnFrom() 함수의 접근 제어 누락이었습니다. 구체적으로, burnFrom() 함수는 임의의 사용자가 어떤 주소에서든 WDGG 토큰을 소각할 수 있도록 허용했습니다. 공격자는 이를 이용해 PancakeSwap 풀에서 WDGG 토큰을 소각한 뒤, sync() 함수를 호출하여 풀의 WDGG 준비금을 줄이고, 이후 역방향 스왑을 수행하여 이익을 추출했습니다.

배경

이 사고는 단일 토큰 WDGG와 관련되어 있으며, 이는 각 전송 시 수수료를 부과하는 배당 분배 토큰입니다.

취약점 분석

WDGG 토큰 계약(0x512de7...6b90c5)은 호출자 권한 없이 burnFrom()을 노출했습니다. 그 결과, 어떤 주소든 PancakeSwap 풀 자체를 포함한 모든 보유자로부터 WDGG 토큰을 소각할 수 있었습니다. 기록된 준비금을 실제 잔액에 맞게 재조정하는 PancakeSwap의 공개적으로 호출 가능한 sync()와 결합하여, 이 결함은 정당한 거래 없이도 풀의 WDGG 준비금을 임의로 줄이고 상수 곱 불변량을 깨뜨려 풀을 가격 불균형 차익 거래에 노출시켰습니다.

setWdgAddress()의 부차적인 결함으로 인해 어떤 호출자든 임의의 주소를 수수료 면제로 표시할 수 있어, 이 공격 표면을 통해 추출 가능한 이익을 더욱 극대화했습니다.

공격 분석

다음 분석은 트랜잭션 0x2da5...0bd1을 기반으로 합니다.

  • 1단계: 공격자는 먼저 setWdgAddress()를 호출하여 자신의 주소를 수수료 면제로 설정하여, 이후 전송 시 토큰의 전송 수수료를 우회할 수 있도록 했습니다.
  • 2단계: 공격자는 PancakeSwap 풀을 통해 소량의 BNBWDGG 토큰으로 교환했습니다.

  • 3단계: WDGG를 획득한 후, 공격자는 burnFrom()을 호출하여 PancakeSwap 페어 주소에서 직접 WDGG 토큰을 소각했습니다.

  • 4단계: 공격자는 이후 sync()를 호출하여 페어가 조작된 토큰 잔액에 맞게 준비금을 업데이트하도록 강제했습니다. 그 결과 풀의 WDGG 준비금이 단 1 wei로 줄어들었습니다.

  • 5단계: 풀 준비금이 심각하게 왜곡된 상태에서, 공격자는 역방향 스왑을 실행하여 가격 불균형에서 이익을 추출했습니다.

결론

이 사고는 궁극적으로 WDGG 토큰 계약의 burnFrom() 함수에서 접근 제어가 누락되어 발생했습니다. 그 결과, 공격자는 PancakeSwap 풀에서 직접 토큰을 소각하고, sync()를 통해 풀의 준비금을 조작하여 발생한 가격 불균형으로 이익을 취할 수 있었습니다.


3. i6Token 사고

간략한 요약

2026년 3월 31일, BNB Chain의 i6 토큰은 invest()가 풀의 현물 가격을 변동시키는 반면 withdraw()는 지연된 TWAP을 통해 잔액을 정산하며, 두 함수가 동일한 트랜잭션 내에서 조합될 수 있어 약 $273.8K의 손실을 입었습니다. 공격자는 invest()를 통해 현물 가격을 부풀리고, withdraw()를 통해 오래된 TWAP 가격으로 초과 i6를 환매한 뒤, i6를 부풀려진 풀에 다시 팔아 이익을 얻었습니다.

배경

프로토콜의 동작 방식은 다음과 같습니다. 사용자가 invest()를 호출하면, USDT가 예치되고 일부가 PancakeSwap에서 i6 구매에 사용됩니다. 취득한 i6는 나머지 USDT와 함께 USDT/i6 풀에 유동성으로 추가되며, 생성된 LP 토큰은 소각됩니다. 프로토콜은 사용자 및 추천인 잔액을 USDT 단위로 기록합니다.

withdraw()가 호출되면, 프로토콜은 USDT 기준으로 사용자의 누적 가치를 계산하고, 프로토콜이 관리하는 TWAP 가격(twapPrice)을 사용하여 이를 i6 수량으로 변환합니다.

취약점 분석

프로토콜 계약(0x1cb36b...2a18a)의 근본 원인은 invest()i6 구매 및 유동성 추가의 부작용으로 USDT/i6 풀의 현물 가격을 변경하는 반면, withdraw()는 시간 창이 경과한 후에만 업데이트되는 프로토콜 관리 TWAP(twapPrice)를 사용하여 누적된 USDT 단위 잔액을 i6로 정산한다는 것입니다. 계약 내 어떤 것도 이 두 함수가 동일한 트랜잭션에서 실행되는 것을 막지 않습니다.

invest() 호출이 동일한 트랜잭션 내에서 현물 가격을 부풀릴 수 있고, 이후 withdraw()가 아직 업데이트되지 않은 TWAP을 읽기 때문에, 두 함수는 동일한 풀 상태에 대해 사실상 두 개의 다른 가격을 보게 됩니다. withdraw()를 통해 환매된 USDT 단위 잔액은 오래되고 훨씬 낮은 가격으로 i6로 지급되지만, 각 i6는 현재 풀에서 훨씬 더 많은 USDT로 실현 가능합니다. 이 차이로 인해 프로토콜 내 누적된 모든 USDT 잔액이 내부 정산과 실시간 풀 사이의 스프레드로 이용될 수 있게 됩니다.

공격 분석

다음 분석은 트랜잭션 0xc1b9...2f16을 기반으로 합니다.

  • 1단계: 공격자는 먼저 플래시 론을 통해 270,000 WBNB를 획득하고, Venus에 담보로 공급한 뒤 대량의 USDT를 차입했습니다. 또한 공격자는 0xda49에 공격 계약 A를, 0x096a에 보조 계약 B를 배포했습니다.

  • 2단계: 공격 계약이 첫 번째 invest()를 실행했습니다. 이 과정에서 프로토콜은 먼저 531,489e18 USDT를 사용하여 234,188e18 i6를 구매하고, 이후 354,326e18 USDT72,607e18 i6를 풀에 추가했습니다. 그 결과 풀 현물 가격이 약 1.05159 USDT/i6에서 약 4.89287 USDT/i6로 빠르게 상승한 반면, 프로토콜에 기록된 TWAP은 여전히 1.05159에 머물렀습니다.

  • 3단계: 공격자는 124,014,184e18 USDT를 보조 계약 B로 이전했으며, 이 계약은 referrer = Ainvest()를 호출했습니다. 이 단계에서 프로토콜은 다시 한번 대규모 USDT -> i6 구매와 addLiquidity()를 수행하도록 강제되어, 풀 준비금을 현물 가격 약 15,528 USDT/i6에 해당하는 새로운 상태로 밀어 올렸습니다. 그러나 새로운 시간 창이 경과하지 않았기 때문에, 프로토콜은 그에 따라 TWAP을 업데이트하지 않았습니다.

  • 4단계: 두 번째 invest()가 완료된 후, 추천인으로서의 공격 계약 A는 즉시 USDT 단위의 추천 보상을 받을 자격이 생겼습니다. 공격자는 이후 withdraw()를 호출했습니다. 프로토콜은 오래된 TWAP을 사용하여 지급할 i6 수량을 계산하고 자체 잔액에서 토큰을 전송하여, 총 5,896,508e18 i6를 지급했습니다.

  • 5단계: i6를 받은 후, 공격자는 즉시 swapExactTokensForTokensSupportingFeeOnTransferTokens()를 호출하여 5,896,508e18 i6 전체를 풀에 다시 팔아 125,177,224e18 USDT를 획득했습니다. 이 i6 토큰들은 약 1.05159 USDT/i6의 오래된 TWAP으로 정산되었지만, 공격자가 약 15,528 USDT/i6로 끌어올린 풀 현물 가격으로 매도되었기 때문에, 공격자는 두 가격 사이의 막대한 스프레드를 직접 실현할 수 있었습니다.

  • 6단계: 플래시 론을 상환한 후, 공격자는 273,802e18 USDT를 보유하게 되었으며, 이것이 공격의 실제 이익이었습니다.

결론

근본 원인은 현물 가격에 영향을 미치는 함수(invest())와 TWAP으로 정산하는 함수(withdraw())가 단일 트랜잭션 내에서 조합될 수 있어, 두 함수가 동일한 풀 상태에 대해 서로 다른 가격을 보게 된다는 것입니다.

이러한 유형의 결함을 방지하기 위해, AMM 상호작용과 지연 가격 책정을 결합하는 프로토콜은 동반 함수가 기저 풀의 현물 가격을 이동시키는 동일한 트랜잭션에서 TWAP을 사용하여 잔액을 정산하는 것을 피해야 하며, 대신 지급액을 오래되거나 파생된 가격이 아닌 풀의 실시간 실현 가능 가치에 고정시켜야 합니다.


4. Drift Protocol 사고

간략한 요약

2026년 4월 1일(UTC), Solana의 Drift Protocol이 약 $285.3M의 피해를 입었습니다. 근본 원인은 스마트 계약 버그가 아니라 멀티시그 승인 프로세스의 취약점이었으며, 이는 타임락이 없는 2-of-5 보안 위원회와 서명된 멀티시그 승인을 공격자가 실행을 선택하는 순간까지 무한정 유효하게 유지시키는 Solana의 내구성 논스 메커니즘이 결합되어 악화되었습니다. 수 주에 걸친 준비 작업 끝에, 공격자는 5명의 서명자 중 2명을 유도하여 내구성 논스 계정에 바인딩된 악의적인 거버넌스 트랜잭션에 사전 서명하도록 한 뒤, 이를 제출하여 관리자 권한을 탈취하고, 조작된 담보 자산(CVT)을 도입하여 오라클 가격을 부풀리고, 출금 한도를 완화한 뒤, Drift Vault(JCNCMF...XJfrw)를 통해 실제 자산을 탈취했습니다.

배경

Drift Protocol은 Solana의 DeFi 프로토콜로 마진 거래, 대출, 현물 시장 및 파생상품을 지원합니다. 관리자 변경, 시장 생성, 오라클 구성, 리스크 파라미터 업데이트, 출금 한도 조정 등 높은 권한이 필요한 작업은 단일 개인 키가 아닌 Squads 멀티시그 프레임워크에 의해 관리됩니다. 공격 당시 Drift의 보안 위원회는 타임락이 없는 2-of-5 임계값 구성으로 운영되었으며, 이는 5명의 서명자 중 2명이 즉각적인 효력으로 관리 조치를 승인할 수 있다는 것을 의미합니다. 이 시스템의 보안은 서명자 키 보관뿐만 아니라, 어떤 트랜잭션이 생성되었는지, 서명자들이 무엇을 승인한다고 믿었는지, 최종 실행된 지시가 해당 검토 맥락과 일치하는지 등 전체 승인 파이프라인의 무결성에 달려 있습니다.

별도로, Solana의 내구성 논스 계정은 단기 블록해시를 전용 계정에 저장된 영구 논스로 대체하여, 서명된 트랜잭션이 논스가 전진될 때까지 무한정 유효하게 유지될 수 있도록 합니다. 이 메커니즘은 오프라인 서명 및 지연 제출과 같은 합법적인 사용 사례를 위해 설계되었지만, 트랜잭션이 서명된 시점과 온체인에서 실행된 시점을 분리함으로써 중요한 공격 원소를 도입합니다. 서명자가 내구성 논스 트랜잭션을 승인하면, 논스 권한자가 수동으로 논스 계정을 전진시키지 않는 한 승인을 취소할 수 없습니다.

취약점 분석

근본 원인은 스마트 계약 버그나 키 탈취가 아니라, Drift의 거버넌스 구성에 있는 세 가지 구조적 취약점이 결합되어 사회공학적 기회를 $285.3M 탈취로 전환시킨 것입니다. 첫째, 내구성 논스는 암묵적인 서명 만료 안전망을 제거했습니다. 일반적인 블록해시 기반 트랜잭션에서는 속은 서명자의 승인이 즉시 실행되거나 좁은 창 안에 무해하게 만료되어 조율된 악용의 범위를 제한합니다. 내구성 논스는 이 제약을 해소합니다: 두 보안 위원회 서명자가 오해의 소지가 있는 서명 요청을 통해 악의적인 거버넌스 트랜잭션을 승인하도록 유도되면, 그들의 서명은 무한정 이용 가능한 상태로 유지되어 공격자에게 실행 타이밍에 대한 완전한 제어권을 부여합니다.

둘째, 관리 조치에 대한 타임락 부재는 사전 서명된 트랜잭션이 제출되는 순간 관리자 이전이 즉시 효력을 발생시켜, 탐지 또는 개입 여지를 남기지 않았습니다. 셋째, 관리자 역할의 범위는 단일 권한 경로에서 새로운 담보 시장을 생성하고, 오라클 소스를 전환하고, 출금 한도를 완화할 수 있을 만큼 광범위하여, 단 한 번의 성공적인 거버넌스 탈취만으로도 추가 승인 장벽 없이 임의의 자산을 실제 자금 추출로 전환하기에 충분했습니다.

공격 분석

공격은 세 가지 뚜렷한 단계로 전개되었습니다: 공격 전 준비 단계에서 공격자는 수 주에 걸쳐 가짜 담보 자산을 제조하고 오해의 소지가 있는 서명 요청을 통해 거버넌스 접근권을 획득하는 작전을 진행했습니다; 거버넌스 탈취 단계에서 두 개의 사전 서명된 내구성 논스 트랜잭션이 빠르게 연속 제출되어 관리 권한을 장악했습니다; 자금 추출 단계에서 공격자는 프로토콜 파라미터를 조작하고 프로토콜의 대출 경로를 통해 실제 자산을 탈취했습니다. 아래 다이어그램은 이 세 단계에 걸친 실행 흐름을 보여줍니다.

  • 1단계 (공격 전 준비): 3월 11일부터 공격자는 Tornado Cash에서 10 ETH를 인출하고 CarbonVote Token(CVT)을 배포하여 7억 5천만 개를 발행한 뒤, Raydium에 유동성을 공급하고 워시 트레이딩을 이용해 $1 근처의 인위적인 가격 이력을 만들었습니다. 병행하여, 3월 23일까지 네 개의 내구성 논스 계정이 생성되었으며, 두 개는 Drift 보안 위원회 멤버와 연결되고 두 개는 공격자가 제어하여, 5명의 서명자 중 최소 2명이 이미 내구성 논스 계정에 연결된 트랜잭션에 서명했음을 나타냈습니다. 3월 27일, Drift는 멤버 변경으로 인한 계획된 보안 위원회 마이그레이션을 실행하여 이전에 수집된 서명을 무효화했습니다; 그러나 3월 30일까지 공격자는 새로운 구성 하에서 필요한 임계값을 다시 획득하여, 온체인 거버넌스 변경에 대한 능동적인 모니터링과 실시간 적응을 보여주었습니다.

  • 2단계 (거버넌스 탈취): 4월 1일 약 16:05 UTC, Drift가 보험 기금에서 합법적인 테스트 출금을 수행한 지 약 1분 후, 공격자는 4개 슬롯 간격으로 두 개의 사전 서명된 내구성 논스 트랜잭션을 제출했습니다. 첫 번째 트랜잭션(2HvMSg...2C4H)은 악의적인 관리자 이전 제안을 생성하고 승인했습니다. 두 번째 트랜잭션(4BKBmA...RsN1)은 이를 승인하고 실행했으며, 저장된 논스를 활성화하는 AdvanceNonceAccount로 시작하여 proposalApprovevaultTransactionExecute를 거쳐 궁극적으로 UpdateAdmin을 호출하여 관리 권한을 공격자가 제어하는 주소로 이전했습니다.

  • 3단계 (자금 추출): 완전한 관리자 권한을 확보한 공격자는 CVT를 위한 담보 시장을 생성하고, 공격자가 제어하는 오라클로 전환하여 장부 가격을 부풀리고, 주요 자산 시장의 출금 한도를 상향 조정하거나 제거했습니다. 그 후 공격자는 대량의 과대평가된 CVT를 프로토콜에 예치하고 약 12분에 걸쳐 31번의 신속한 출금을 실행하여 USDC, JLP, SOL, cbBTC, USDT, wETH, dSOL, WBTC, JTO, FARTCOIN을 탈취하였으며, 총 손실액은 공격자의 출금 계정(HkGz4K...pZES)을 기준으로 약 $285.3M으로 계산되었습니다.

결론

이 사고의 근본 원인은 스마트 계약 취약점이나 키 탈취가 아니라, 내구성 논스 기반 지연 실행과 타임락 없는 관리 경로가 결합된 멀티시그 승인 프로세스의 취약점입니다. 일반적으로 몇 분 안에 만료되었을 사전 수집된 승인이 무한정 이용 가능한 상태로 유지되었으며, 제출된 이후에는 관리자 탈취와 이후 자금 추출 사이에 개입 여지가 없었습니다.

이러한 유형의 위험을 완화하려면 서명자 키 보관만이 아닌 전체 승인 파이프라인을 보호하고, 높은 권한이 필요한 작업에 타임락을 적용하며, 내구성 논스와 같은 지연 실행 메커니즘을 더 높은 서명 임계값, 시간 제한 또는 취소 가능한 승인, 무한정 유효한 서명된 트랜잭션에 대한 제한을 요구하는 별도의 위협 표면으로 취급해야 합니다.


5. LML 스테이킹 프로토콜 사고

간략한 요약

2026년 4월 1일, BNB Chain의 LML 스테이킹 프로토콜이 약 $950K의 피해를 입었습니다. 근본 원인은 보상 계산 로직의 불일치였습니다: 보상 변환이 3600초 업데이트 쿨다운에 잠긴 저장된 LML/USDT 가격을 읽는 반면, 지급된 LML은 실시간 AMM 가격으로 환매 가능하며, 두 값 사이에 편차 확인이 없었습니다. 공격자는 플래시 론으로 풀 현물 가격을 부풀리고 EIP-7702 코드 위임을 통해 단일 트랜잭션에서 11개의 사전 스테이킹된 EOA의 보상을 일괄 청구하여, 오래된 저장 가격으로 과도한 양의 LML을 받고 현재 심각하게 왜곡된 풀을 통해 다시 매도하여 이익을 얻었습니다.

배경

LML은 BNB Chain의 스테이킹 프로토콜로, 사용자들은 APower 계약을 통해 BNB를 스테이킹하여 LML 토큰을 보상으로 받습니다. 보상은 USDT 단위로 계산된 후, 분배 전 프로토콜에 저장된 LML/USDT 가격을 기준으로 LML 수량으로 변환됩니다. 저장된 가격은 AMM 현물 가격을 읽지만 업데이트 사이에 3600초 쿨다운을 적용하는 updatePrice()에 의해 갱신됩니다. 보상 청구는 msg.sender에 기반한 APowerreceive()를 통해 트리거되므로, 원래 스테이킹 주소만 자신의 보상을 청구할 수 있습니다.

취약점 분석

스테이킹 계약(0xbe9713...adce19)의 핵심 결함은 보상 발생과 보상 환매가 두 가지 다른 가격에 고정되어 있으며, 두 값 사이에 일관성 확인이 없다는 것입니다. 보상 공식 reward += (10^18 * base_reward) / stored_price는 3600초 쿨다운 후 updatePrice()에 의해서만 갱신되는 프로토콜 저장 LML/USDT 가격인 _prices[]에서 LML 지급액을 계산하지만, 지급된 LML은 즉시 실시간 AMM 현물 가격으로 환매 가능합니다. 이 쿨다운 창 내에서 현물 가격을 이동시키는 외부 활동은 고정된 발생 가격과 실시간 매도 가격 사이의 격차를 만들며, 계약 내 어떤 것도 그 격차가 불합리해질 때 청구를 거부하지 않습니다.

두 번째 구조적 결함은 보상 소스가 보충되는 방식에 있습니다. PROOF 계약의 LML 잔액이 청구를 지급하기에 부족할 때, swapBack()super._transfer(swapPair, PROOF, deficit)를 호출하고 그 뒤 sync()를 호출하여, 일반적인 스왑을 통하지 않고 LP 페어의 준비금에서 직접 LML을 이동하고 페어의 저장 상태를 재조정함으로써 이를 보충합니다. 이 경로는 페어의 가격 발견을 우회하기 때문에, 이를 트리거하는 모든 청구는 어떤 상쇄 토큰 유입도 없이 페어의 LML 준비금을 줄이고 현물 가격을 추가로 이동시켜, 반복적인 청구가 기계적으로 고정된 저장 가격과 실시간 매도 가격 사이의 격차를 확대합니다.

공격 분석

다음 분석은 트랜잭션 0x805d...5b47, 0x70f7...3572을 기반으로 합니다.

  • 1단계: 공격자는 Moolah로부터의 플래시 론, Venus와 Moolah Pool에서의 차입(WBNB를 담보로 사용), PancakeSwap V4, 다수의 V3 풀, V2 풀로부터의 플래시 론을 통해 대량의 USDTWBNB를 집결시켰습니다. 이 자본은 LML/USDT 페어 가격을 조작하는 데 필요했습니다.

  • 2단계: 공격자는 LML 토큰 계약에서 swapAndTrans()를 호출하여, 계약에 누적된 LML 수수료를 USDT로 교환했습니다. 이로 인해 LML 계약 자체의 LML 잔액이 소진되어 로컬 토큰 소스로 더 이상 기능할 수 없게 되었으며, 이후의 모든 보상 분배는 swapBack()을 통해 LP 페어에서 LML을 가져와야 했습니다.

  • 3단계: 공격자는 PancakeRouter swapExactTokensForTokensSupportingFeeOnTransferTokens를 통해 USDTLML로 교환했으며, 수신자를 dead 주소로 설정했습니다. 구매된 LML 토큰은 공격자가 받지 않고 소각되었습니다. 유일한 목적은 페어에서 LML을 소진하고 AMM에서 LML 가격을 부풀리는 것이었으며, 공격자는 토큰 자체가 아닌 가격 왜곡만 필요했습니다.
  • 4단계: 공격자는 이전에 11개의 EOA 주소를 사용하여 스테이킹 프로토콜에 예치했습니다. APower의 receive()msg.sender를 기반으로 _claimReward(msg.sender)를 트리거하기 때문에, 보상은 예치 주소 자체만 청구할 수 있습니다. 단일 트랜잭션 내에서 11개 EOA 모두의 보상을 청구하기 위해, 공격자는 EIP-7702를 사용하여 이 EOA들에 코드를 설정하여 공격자의 메인 계약에 의해 계약으로 호출될 수 있게 했습니다. 각 EOA는 소량의 BNB를 APower로 전송하는 transfer(rst, fte) 함수를 실행하여 receive(), _claimReward(EOA)를 트리거했습니다. 각 청구 내부에서: updatePrice()는 건너뛰어졌고(3600초 쿨다운이 충족되지 않아 stored_price는 역사적으로 낮은 값으로 유지됨), updateUser()는 오래된 낮은 가격을 사용하여 보상을 계산했으며, sendMining()은 PROOF에서 APower로 LML을 전송하고 swapBack()을 트리거하여 LP 페어에서 LML을 가져오고 sync()를 호출함으로써 PROOF를 보충하여 페어의 준비금을 더욱 줄였습니다. 마지막으로 claimReward()가 EOA에 LML을 분배하고, 각 EOA는 받은 LML을 공격자 계약으로 다시 전송했습니다.
  • 5단계: 공격자는 누적된 LML을 현재 심각하게 고갈된 풀을 통해 극도로 부풀려진 가격으로 USDT로 다시 교환했습니다.

  • 6단계: 모든 플래시 론, 차입금 및 수수료를 상환했습니다. 나머지 이익을 이전했습니다.

결론

근본 원인은 스테이킹 계약에서 보상 발생과 환매 사이의 불일치입니다: 지급액은 3600초 쿨다운에 잠긴 저장된 LML/USDT 가격으로 산정되지만, 실제 가치가 실시간 AMM 가격을 추적하는 LML로 정산되며, 두 값을 연결하는 편차 확인이 없습니다. swapBack() 보충 경로는 각 청구마다 LP 페어에서 직접 LML을 소진시켜 처리되는 청구가 많을수록 기계적으로 고정된 저장 가격과 실시간 매도 가격 사이의 격차를 확대함으로써 이 결함을 증폭시킵니다.

AMM 파생 가격으로 보상을 산정하는 스테이킹 프로토콜은 청구 시점에 저장된 가격과 현재 현물 가격 사이의 편차 확인을 적용하고 격차가 안전 임계값을 초과할 때 되돌려야 하며, LP 준비금을 일반적인 스왑 경로 외부에서 변경하는 보충 메커니즘을 피해야 합니다. 그러한 메커니즘은 오래된 가격 책정으로 인한 피해를 제한할 가격 발견을 우회하기 때문입니다.


6. Tactile 사고

간략한 요약

2026년 4월 1일, Polygon의 단계별 예치 프로토콜인 Tactile이 약 $12K의 손실을 입었습니다. 근본 원인은 예치와 출금 정산 로직의 불일치였습니다: 진입과 퇴출 모두 CES의 현재 현물 가격으로 변환되었으며, 내부 지분은 원래 발행된 자산 가치에 대한 기록을 담고 있지 않았습니다. 공격자는 예치 전 현물 가격을 부풀려 과도한 지분을 획득하고, 출금 전 가격을 낮춰 지분당 더 많은 CES를 환매하는 방식을 보조 계약을 통해 반복하여 이익을 추출했습니다.

배경

Tactile은 Polygon의 단계별 예치 프로토콜로, 사용자들은 선택한 등급에 따라 결제 계약에 CES를 예치합니다. 필요한 예치 금액은 CES의 현재 현물 가격과 등급 구성에서 계산되며, 사용자는 자신의 포지션을 나타내는 내부 회계 지분을 받습니다. 출금 시, 기록된 지분은 원래 예치된 금액에 대해 정산하는 대신 퇴출 시점의 현물 가격을 사용하여 CES로 역변환되므로, 사용자 잔액은 고정된 자산 금액이 아닌 가격 의존적 회계 단위로 추적됩니다.

취약점 분석

결제 계약(0x9153e1...09b654)의 핵심 결함은 예치와 출금이 두 다른 시점에 동일한 현물 가격 오라클에 대해 정산되며, 두 시점을 연결하는 불변 앵커가 없다는 것입니다. 예치 시, 계약은 getActualPrice()를 읽고 현재 가격에 기반하여 예치된 CES를 내부 지분으로 변환합니다; 출금 시, 동일한 지분이 환매 시점의 현물 가격을 사용하여 CES로 역변환됩니다.

지분 자체가 발행된 가격이나 자산 금액에 대한 기록을 담고 있지 않기 때문에, 이 두 시점 사이의 현물 가격의 모든 변동은 직접적으로 지급된 CES와 받은 CES 사이의 불일치로 전환되어, 프로토콜의 회계가 기저 자산 가치가 아닌 가격 경로에 완전히 노출됩니다.

공격 분석

다음 분석은 트랜잭션 0xc321...da74를 기반으로 합니다.

  • 1단계: 공격자는 먼저 Uniswap V3 플래시 풀에서 55,365e18 CES를 차입하고 5개의 보조 계약에 자금을 분배했습니다. 각 보조 계약은 먼저 6,426e18 CES를 받은 뒤 deposit(12)를 호출했습니다. 이 과정에서 각 보조 계약은 먼저 getPriceForLevel(12)를 쿼리하고, 현재 가격에 기반하여 이 예치에 필요한 CES 금액을 준비했습니다.
  • 2단계: 5개의 보조 계약이 모두 첫 번째 deposit 라운드를 완료한 후, 공격자는 DEX에서 300,000 CES를 덤핑하여 bank가 사용하는 가격을 1.067585에서 0.688542로 낮췄습니다. 그 후 5개의 보조 계약은 하나씩 withdraw를 실행하여 높은 가격에서 생성된 지분을 현재 낮은 가격의 CES로 환매했습니다. 각 보조 계약은 9,427e18 CES를 받았습니다.
  • 3단계: 첫 번째 withdraw 라운드를 완료한 후, 공격자는 획득한 상대방 자산을 CES로 다시 교환하여 가격을 다시 끌어올렸습니다. 공격자는 이후 2-3단계를 반복했습니다.

  • 4단계: 마지막으로, 여러 공격 사이클 후, 플래시 론과 166.097975017841805126 CES의 플래시 수수료를 상환한 후, 공격자는 이익으로 567,736e18 CES를 보유하게 되었습니다.

결론

이 사고의 근본 원인은 Tactile이 예치 시점의 자산 금액이나 가격에 회계 지분을 고정하지 않고, 조작 가능한 현물 가격에 대해 예치와 출금을 모두 정산하여, 내부 회계가 진입과 퇴출 사이의 모든 가격 변동에 완전히 노출되었다는 것입니다.

변동성 자산에 대해 지분형 포지션을 발행하는 프로토콜은 각 지분을 발행 시점의 구체적인 자산 금액이나 가격에 고정하여, 환매가 실시간 오라클에 대해 재가격을 책정하는 것이 아닌 원래의 경제적 가치를 재현하도록 해야 합니다. 정산 함수가 현재 가격을 참조해야 하는 경우, 시간 가중 또는 그 외의 조작 저항적인 소스를 사용하고, 정산 호출과 동일한 트랜잭션에서 실행된 거래에 의해 이동될 수 있는 동일한 현물 가격을 읽는 것을 피해야 합니다.


7. SAS 토큰 사고

간략한 요약

2026년 4월 2일, BNB Chain의 SAS 토큰이 약 $12K의 피해를 입었습니다. 근본 원인은 토큰의 커스텀 전송 로직의 결함이었습니다: LP 풀로 SAS를 전송하면 전역 sellBurn 카운터만 증가시켰으며, 이후의 일반적인 전송은 AMM의 스왑 로직을 거치지 않고 풀에서 직접 SAS를 소각하고 sync()를 호출하여 준비금을 재작성할 수 있었습니다. 공격자는 이를 이용해 매도를 통해 sellBurn을 누적시키고, 관련 없는 일반 전송을 트리거하여 풀에서 SAS를 소각하고 준비금을 1 wei로 낮춘 뒤, 남은 SAS를 역방향 스왑하여 이익을 얻었습니다.

배경

SAS는 BNB Chain의 디플레이션 토큰으로, PancakeSwap V2 풀 위에 구축된 커스텀 전송 로직을 가지고 있습니다. transfer() 함수는 두 가지 경로를 구분합니다: LP 풀이 전송 목적지일 때 트리거되는 매도 경로로, 전역 sellBurn 누산기를 전송된 금액만큼 증가시키는 것과; sellBurn이 0이 아닐 때 LP 풀에서 직접 SAS를 소각하고 sync()를 호출하여 새로운 온체인 잔액에 맞게 준비금을 업데이트하는 일반 전송 경로. 두 경로는 누적된 매도 압력에 반응하여 풀의 SAS 준비금을 줄이는 디플레이션 메커니즘으로 함께 작동하도록 설계되었습니다.

취약점 분석

SAS 토큰 계약(0xbfa266...3d91c6)의 핵심 결함은 디플레이션 메커니즘이 transfer()에 연결된 방식에 있습니다. SAS가 LP 풀로 전송될 때, 계약은 전역 sellBurn 누산기를 전송된 금액만큼 증가시킵니다. 그 후, 이후의 모든 일반 전송에서 sellBurn이 0이 아니면, 계약은 _burnFromPair()를 호출하여 LP 풀에서 직접 SAS를 소각하고 sync()를 따라 호출하여 풀의 준비금을 온체인 잔액에 맞게 재작성합니다.

문제는 이 소각-및-동기화 경로가 AMM의 스왑 로직을 거치지 않고 풀의 준비금을 재작성한다는 것입니다. sellBurn이 풀로의 전송에 의해 끌어올려지면, 관련 없는 일반 전송만으로도 소각 및 동기화를 트리거하여 풀의 SAS 준비금을 0 방향으로 강제하고 일반 스왑을 통해 수확될 수 있는 큰 가격 왜곡을 만들 수 있습니다.

공격 분석

다음 분석은 트랜잭션 0x878e...adc5를 기반으로 합니다.

  • 1단계: 공격자는 플래시 론을 통해 WBNB를 차입했습니다.

  • 2단계: 공격자는 WBNBSAS로 교환했습니다.

  • 3단계: 공격자는 계약을 배포하고 constructor()에서 공격 로직을 실행했습니다. 이는 프로토콜의 is_contract() 확인을 우회하기 위한 것으로, 토큰 계약은 transfer()from이 화이트리스트 주소이거나 EOA여야 함을 요구했습니다.

  • 4단계: 공격자는 SAS를 풀로 전송하여 매도 경로를 트리거하고 sellBurn을 누적시켰습니다.
  • 5단계: 공격자는 두 번째 계약을 배포하고, 다시 constructor() 내부에서 일반 전송을 시작했습니다. 4단계에서 이미 sellBurn이 0이 아니었기 때문에, 이 전송은 _burnFromPair() 함수를 트리거하여 LP 풀에서 직접 SAS를 소각하고 sync() 함수를 호출하여 SAS 준비금을 1 wei로 줄였습니다.
  • 6단계: 공격자는 역방향 스왑을 수행하여 남은 SAS를 이익으로 팔았습니다.

결론

이 사고의 근본 원인은 SAS 토큰의 커스텀 전송 로직의 결함입니다: 일반 전송이 LP 풀에서 직접 SAS를 소각하고 준비금을 줄어든 잔액으로 동기화할 수 있어, 누적된 매도 활동이 풀의 SAS 준비금의 임의적인 감소로 전환되고, 이후 일반 스왑을 통해 수확될 수 있는 큰 가격 왜곡으로 이어질 수 있었습니다.

토큰은 외부 AMM 풀에 접근하여 일반 스왑 경로 외부에서 준비금을 변경해서는 안 됩니다. 디플레이션 설계가 정말로 풀에서의 소각을 요구하는 경우, 소각과 함께하는 sync()는 임의의 사용자 전송에 편승하는 것이 아닌, 신뢰할 수 있는 키퍼나 속도 제한된 스케줄과 같은 엄격하게 제어된 내부 트리거에 바인딩되어야 합니다.


8. Unknown-EIP-7702 사고

간략한 요약

2026년 4월 3일, EIP-7702를 통해 위임된 코드를 활성화한 BNB Chain의 사용자 계정이 약 $17.2K를 탈취당했습니다. 위임된 코드는 적절한 접근 제어 없이 pancakeV3SwapCallback() 함수를 노출했습니다. 공격자는 조작된 calldata로 이 콜백을 직접 호출하여 피해자 계정이 공격자가 제어하는 주소로 토큰을 전송하도록 강제했습니다.

배경

피해자 EOA는 EIP-7702 Type-4 트랜잭션을 사용하여 계정이 스왑 관련 로직을 실행할 수 있도록 위임된 코드를 설정했습니다. 그러나 위임된 구현에는 합법적인 PancakeSwap V3 풀 콜백 중에만 호출되도록 의도된 공개 pancakeV3SwapCallback() 함수가 포함되어 있었습니다.

취약점 분석

근본 원인은 위임된 계약(0x02C809...aEDbAE)의 pancakeV3SwapCallback() 함수에서 접근 제어가 누락된 것입니다.

올바른 UniswapV3/PancakeV3 콜백 설계에서는, 콜백이 msg.sender가 예상되는 정식 풀(팩토리 + 토큰 페어 + 수수료에서 파생되거나 신뢰할 수 있는 풀 목록에 대해 검증됨)인지 확인해야 합니다. 이 경우 해당 검증이 누락되어, 어떤 외부 호출자든 콜백을 직접 호출할 수 있었습니다.

콜백이 이를 호스팅하는 계정에서 토큰 전송을 실행하기 때문에, msg.sender 확인 누락은 양수 amount0Delta/amount1Delta를 전달하는 모든 외부 호출이 콜백 내부의 결제 경로에 진입하여 실제 스왑 없이 피해자 계정에서 토큰을 이동시킬 수 있음을 의미합니다.

공격 분석

다음 분석은 트랜잭션 0x5b2c...4261을 기반으로 합니다.

  • 1단계: 공격자는 조작된 파라미터로 pancakeV3SwapCallback()을 직접 호출하여, 콜백 전송 로직이 피해자의 토큰을 공격자가 제어하는 주소로 이동시키도록 트리거했습니다.

결론

이 사고는 엄격한 콜백 인증 없이 EIP-7702 계정에 스왑 콜백 로직을 배포하여 발생했습니다. pancakeV3SwapCallback()에 접근 제어가 없어, 어떤 외부 호출자든 콜백을 호출하여 합법적인 스왑 없이 피해자 계정에서 토큰을 이동시키는 데 사용할 수 있었습니다.

V3 스타일 콜백을 구현하는 모든 계약 또는 위임된 EIP-7702 코드에 대해, 개발자는 콜백이 전송 로직에 진입하기 전에 msg.sender가 신뢰할 수 있는 팩토리, 토큰 페어, 수수료 등급에서 파생된 정식 PancakeV3 풀인지 검증해야 합니다.


9. Silo Finance 사고

간략한 요약

2026년 4월 3일, Arbitrum의 Silo Finance soUSDC 볼트가 약 $359K의 피해를 입었습니다. 근본 원인은 세 가지 결함의 수렴이었습니다: 시장 가격이 약 0.12로 폭락한 후에도 wstUSR을 약 1.133으로 가격 책정하는 불변 오라클, soUSDC의 자체 예치만 제한하고 외부 예치는 제한하지 않는 공급 한도 메커니즘, 그리고 해당 soUSDC 지분을 발행하지 않고 외부에서 입금된 bUSDC 지분을 계산하는 totalAssets() 회계 결함. 공격자는 receiver=soUSDC로 0 한도 wstUSR 시장에 직접 USDC를 예치하여 볼트의 지분 가격을 부풀리고, 과대평가된 wstUSR 담보로 동일한 USDC를 다시 차입하고, 부풀려진 가치로 이전에 획득한 soUSDC 지분을 환매하였으며, 부족분은 출금 대기열의 다른 건전한 시장에서 가져왔습니다.

배경

Silo Finance는 Arbitrum의 위험 격리 대출 프로토콜입니다. 각 Silo 시장은 양방향 대출 페어(예: wstUSR/USDC)입니다: 차입자는 담보(wstUSR)를 예치하고 대출 자산(USDC)을 차입하며, 대출자는 USDC를 예치하고 이자를 받습니다. 대출자가 특정 시장에 USDC를 예치하면, 해당 시장의 예치 지분 토큰을 받습니다. 차입자가 담보를 예치하면, 담보 지분 토큰(예: bwstUSR-149)을 받습니다.

soUSDC는 여러 Silo 시장 위에 있는 SiloVault로 USDC 대출을 집계합니다. 사용자들은 USDCsoUSDC에 예치하고 soUSDC 지분을 받습니다. 볼트는 그 후 예치된 USDC를 할당자가 설정한 공급 한도에 따라 승인된 Silo 시장으로 라우팅하며, 볼트 자체는 예치한 각 시장의 bUSDC 지분을 보유합니다. 사용자가 soUSDC 지분을 환매할 때, 볼트는 totalAssets()를 사용하여 지분의 USDC 가치를 계산하는데, 이 함수는 출금 대기열의 모든 시장을 반복하여 각 시장에서 볼트의 bUSDC 지분 잔액을 합산합니다. 그 후 볼트는 환매자에게 지급하기 위해 기저 시장에서 USDC를 인출합니다.

wstUSR(Wrapped Staked USR)은 Resolv가 발행한 USR 스테이블코인의 스테이킹 파생상품입니다. Resolv가 익스플로잇된 후, USR이 디페그되고, stUSR도 페그를 잃어 wstUSR의 2차 시장 가격이 약 0.12로 폭락했습니다. 그러나 wstUSR에 대한 Chainlink 피드는 wstUSR/stUSR 환율(약 1.133)만 추적했으며, 프로토콜은 1 stUSR = 1 USD를 암묵적으로 가정했기 때문에, 오라클은 시장 현실과 약 10배 차이가 나는 약 1.133으로 wstUSR을 계속 가격 책정했습니다.

취약점 분석

wstUSR/USDC 시장의 오라클 주소는 SiloConfig에 불변으로 하드코딩되어 있어 교체할 수 없습니다. 오라클 계약(0x836a1a...04425e) 자체는 기저 Chainlink 피드(설명: "wstUSR / stUSR Exchange Rate")가 wstUSRstUSR 랩핑 비율(약 1.133)만 추적하고 2차 시장 가격은 추적하지 않는 ChainlinkV3Oracle입니다. 프로토콜은 암묵적으로 1 stUSR = 1 USD를 가정하여 wstUSR을 약 1.133으로 가격 책정합니다. USR이 디페그된 후, stUSR도 페그를 잃고 wstUSR은 공개 시장에서 약 0.12로 폭락했지만, 오라클은 계속 약 1.133을 보고하여 약 10배의 과대평가가 이루어졌습니다.

프로토콜은 위험을 부분적으로 인식하고 있었습니다: soUSDCwstUSR 시장 공급 한도가 0으로 설정되어, 볼트가 자발적으로 USDC를 해당 시장으로 라우팅하지 않을 것임을 의미했습니다. 그러나 이 한도는 볼트 자체의 아웃바운드 deposit() 호출만 관리합니다. wstUSR_Market.deposit()이 임의의 receiver 파라미터를 받기 때문에, 누구든 USDCwstUSR 시장에 직접 예치하고 결과적인 bUSDC 지분을 soUSDC의 주소로 입금하여 공급 한도를 완전히 우회할 수 있습니다.

이것이 핵심 익스플로잇 경로를 만듭니다. 이러한 외부 예치를 통해 bUSDC 지분이 soUSDC의 잔액에 들어오면, totalAssets()가 이를 계산합니다: 출금 대기열의 모든 시장을 반복하고 볼트의 실제 지분 잔액을 읽으며, 포지션이 자발적으로 진입되었는지 확인하지 않습니다. 한편, 볼트 자체의 발행 로직이 호출된 적이 없기 때문에 이러한 외부 입금된 포지션에 대해 새로운 soUSDC 지분이 발행되지 않습니다. 결과적으로 totalAssets는 증가하지만 totalShares는 동일하게 유지되어 soUSDC 지분 가격이 부풀려집니다.

공격 분석

다음 분석은 트랜잭션 0xf77a...f3e1을 기반으로 합니다.

공격자는 먼저 2차 시장에서 토큰당 약 0.12로 wstUSR을 구매했습니다.

  • 1단계: Morpho에서 플래시 론으로 약 4,236,352 USDC를 차입했습니다. 오라클 가격 오류만으로는 충분하지 않습니다 - wstUSR 시장에는 USDC 유동성이 없었으며(한도=0, soUSDC가 해당 시장에 예치하지 않음), 따라서 과대평가된 담보에 대해 차입할 것이 없었습니다. 플래시 론은 이후 예치 및 기부 단계에 필요한 자본을 제공합니다.

  • 2단계: wstUSR 시장에 wstUSR을 담보로 예치하고 bwstUSR-149를 받았습니다. 이는 5단계 차입을 위한 준비입니다 - 오라클은 13,797 wstUSR을 약 15,633(개당 1.133)으로 평가하지만, 공격자는 약 1,656만 지불했습니다.

  • 3단계: soUSDC 볼트에 약 4,222,007 USDC를 예치하고 soUSDC 지분(총 공급량의 약 91.5%)을 받았습니다. 볼트는 이 USDC를 기존의 건전한 시장으로 라우팅합니다(wstUSR 시장이 아닌, 한도=0이므로). 이 soUSDC 지분들은 6단계에서 이익을 추출하기 위한 수단입니다 - 공격자가 더 많은 지분을 보유할수록 지분 가격이 부풀려질 때 더 많은 이익을 얻습니다.
  • 4단계: wstUSR_Market.deposit(receiver=soUSDC)를 통해 wstUSR 시장에 약 14,344 USDC를 직접 예치하고 soUSDCbUSDC-149를 발행했습니다. 결과적인 bUSDC 지분은 공격자의 주소가 아닌 soUSDC의 주소로 입금됩니다. 이것이 핵심 조작입니다: soUSDCtotalAssets()는 이제 이 bUSDC 지분을 액면 가치(약 14,344 USDC)로 포함하지만, 볼트 자체의 예치 로직이 호출된 적이 없기 때문에 새로운 soUSDC 지분이 발행되지 않습니다 - totalAssets는 증가하고, totalShares는 동일하게 유지되며, soUSDC 지분 가격이 부풀려집니다. 동시에, 이는 이전에 비어 있던 wstUSR 시장에 USDC 유동성을 만들어 다음 단계에 필요합니다.
  • 5단계: 2단계에서 예치한 담보를 사용하여 wstUSR 시장에서 약 14,344 USDC를 차입했습니다. 오라클은 담보를 약 15,633으로 평가하므로, 92% maxLTV에서 공격자는 약 14,344를 차입할 수 있습니다. 이는 4단계에서 기부한 USDC를 회수합니다 - 차입과 기부는 현금 중립적입니다. 그러나 wstUSR 시장은 이제 완전히 고갈되었습니다: 모든 USDC가 차입되어 거의 가치 없는 wstUSR 담보로 뒷받침되는 미결제 대출만 남습니다. soUSDC는 여전히 totalAssets()에서 액면 가치로 bUSDC 지분을 보유합니다.
  • 6단계: 3단계에서 획득한 모든 soUSDC 지분을 환매했습니다. 지분 가격은 4단계의 기부로 부풀려져 있어, 공격자는 약 4,235,143 USDC를 받았으며, 이는 3단계에서 예치한 4,222,007보다 약 13,136 더 많습니다. 볼트는 wstUSR 시장에서 인출을 시도하지만 유동성이 없어(5단계에서 차입됨), 출금 대기열의 다른 건전한 시장에서 부족분을 가져옵니다. 이것이 손실이 실현되는 곳입니다: 다른 soUSDC 예치자들의 시장에서 실제 USDC가 부풀려진 환매를 충당하기 위해 이전됩니다.
  • 7단계: 플래시 론을 상환했습니다.

32번의 루프 후, soUSDCwstUSR 시장에 액면 가치 약 359K이지만 그 일부에 불과한 wstUSR 담보로 뒷받침되는 bUSDC 포지션을 보유하게 되었습니다 - 100% 활용률로, 사실상 남아있는 soUSDC 예치자들이 부담하는 회수 불가능한 부실 채무입니다.

결론

이 사고는 디페그된 자산의 시장 가격이 아닌 스테이킹 환율을 추적하는 오라클, 해당 지분을 발행하지 않고 외부에서 입금된 포지션을 totalAssets()에 계산하는 볼트 회계 시스템, 그리고 볼트 자체의 예치만 제한하고 외부 예치는 제한하지 않는 공급 한도 메커니즘이 수렴하여 발생했습니다. SiloConfig에서 오라클 주소가 불변으로 되어 있어 문제가 명확해진 후 긴급 수정이 불가능했습니다.

여러 대출 시장을 집계하는 볼트 프로토콜은 totalAssets()가 볼트가 자체 예치 작업을 통해 진입한 포지션만 계산하고, 외부에서 입금된 지분 잔액은 계산하지 않도록 보장해야 합니다. 오라클 주소는 영구적으로 불변이어서는 안 됩니다; 기저 자산이 디페그될 때 가격 피드 업데이트를 위한 긴급 거버넌스 메커니즘이 존재해야 합니다.


Phalcon Security 시작하기

모든 위협을 탐지하고, 중요한 것에 대해 알림을 받고, 공격을 차단하세요.

지금 무료로 체험하기

BlockSec 소개

BlockSec은 풀스택 블록체인 보안 및 암호화폐 컴플라이언스 제공업체입니다. 저희는 고객이 코드 감사(스마트 계약, 블록체인 및 지갑 포함), 실시간 공격 차단, 사고 분석, 불법 자금 추적, 프로토콜 및 플랫폼의 전체 생명주기에 걸쳐 AML/CFT 의무 이행을 수행할 수 있도록 돕는 제품과 서비스를 구축합니다.

BlockSec은 권위 있는 학술 컨퍼런스에서 다수의 블록체인 보안 논문을 발표하고, DeFi 애플리케이션의 여러 제로데이 공격을 보고하였으며, 다수의 해킹을 차단하여 2,000만 달러 이상을 구하고, 수십억 달러의 암호화폐를 보호했습니다.

Sign up for the latest updates
~$410만 손실: Taiko, SecondFi 익스플로잇 | BlockSec 위클리
Security Insights

~$410만 손실: Taiko, SecondFi 익스플로잇 | BlockSec 위클리

이 주간 블록체인 보안 리포트는 2026년 6월 22~28일 발생한 주요 사건 2건을 다루며, 이더리움과 카르다노에서 약 410만 달러의 피해가 확인됐습니다. Taiko 브릿지 공격은 노출된 SGX 서명 키와 디버그 엔클레이브를 거부하지 못한 증명 정책 결함을 이용해 악성 증명자를 등록하고 L2 상태 증명을 위조했습니다. SecondFi 지갑은 Ed25519 논스 도출 시 비밀 입력이 제거되는 결함으로 공개 트랜잭션 데이터만으로 개인 키 복구가 가능했습니다.

~$18M 손실: jaredFromSubway, Aztec 등 | BlockSec 위클리
Security Insights

~$18M 손실: jaredFromSubway, Aztec 등 | BlockSec 위클리

이 주간 블록체인 보안 보고서는 2026년 6월 15일~21일을 다루며, 이더리움과 BNB 체인에서 3건의 주요 사고가 발생해 약 $18.3M의 손실이 발생했습니다. jaredFromSubway 사건은 MEV 봇이 차익거래를 위해 신뢰할 수 없는 제3자 컨트랙트에 자산을 승인한 역방향 승인 공격으로, 가짜 래퍼 토큰과 스왑 풀을 이용해 약 $15M 손실이 발생했습니다. Aztec은 이스케이프 해치 ZK 회로의 제약 누락으로 공격자가 가짜 머클 트리로 온체인 검증을 통과했습니다.

Web3 컴패니언: 오픈소스 보안 에이전틱 지갑

Web3 컴패니언: 오픈소스 보안 에이전틱 지갑

BlockSec가 Web3 Companion을 오픈소스로 공개했습니다. 이 보안 중심의 에이전트 지갑은 자체 AI 에이전트를 신뢰하지 않는 방식으로 설계되었으며, 키 격리, 강력한 정책, Passkey를 활용해 온체인 자산을 보호합니다.

Best Security Auditor for Web3

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

BlockSec Audit