지난 한 주(2026/07/13 - 2026/07/19) 동안 Ethereum과 Solana에서 총 약 $1.35M의 손실을 발생시킨 주목할 만한 보안 사고 2건을 소개합니다.
| 날짜 | 사고 | 유형 | 추정 손실 |
|---|---|---|---|
| 2026/07/15 | BarnBridge | 부적절한 거버넌스 | ~$776K |
| 2026/07/16 | DeFiTuna | 결함 있는 상태 검사 | ~$570K |
- DeFiTuna: 포지션 상태 검사가 부채가 0이 아닌 상태에서 자산 가치가 0인 경우를 정상으로 허용했습니다. 공격자는 제어된 스왑 라우팅과 별도의 낮은 유동성 풀을 이용하여 이 결함을 트리거하고 불량 부채 포지션을 생성했습니다.
- BarnBridge: 더 이상 사용되지 않는 거버넌스 시스템이 악용되어 중요한 프로토콜 구성을 수정하고 사용자가 승인한 자금을 탈취했습니다.
Web3를 위한 최고의 보안 감사 서비스
출시 전 설계, 코드, 비즈니스 로직을 검증하세요
주간 하이라이트: DeFiTuna
근본 원인은 포지션 상태 검사의 결함 있는 제로값 분기였습니다. 자산 가치가 0이고 약 $570K의 미상환 부채가 있는 포지션이 정상으로 허용되었습니다. 공격자는 별도의 낮은 유동성 풀을 통해 스왑을 라우팅하여 이 결함을 트리거했지만, 결과적으로 발생한 불량 부채를 차단했어야 할 컨트롤은 상태 검사였습니다.
2026년 7월 16일, 레버리지 현물 포지션을 지원하는 Solana의 대출 프로토콜 DeFiTuna가 약 $570K의 USDC를 탈취당하는 익스플로잇 피해를 입었습니다 [1]. 근본 원인은 포지션 상태 검사의 결함 있는 제로값 분기로, 자산 가치가 0이고 부채가 0이 아닌 경우에도 포지션을 정상으로 허용했습니다. 공격자는 담보 없이 레버리지 포지션을 개설하고, 프로토콜 볼트에서 USDC를 빌린 뒤, 공격자가 제어하는 낮은 유동성 풀을 통해 스왑을 라우팅하여 포지션이 목표 토큰을 극히 소량만 수신하게 만들었습니다. 정밀도 절사로 인해 포지션 가치가 0으로 반올림되었고, 상태 검사는 해당 포지션을 정상으로 허용하여 약 $570K의 불량 부채가 발생했습니다.
배경
DeFiTuna는 마진 거래를 지원하는 Solana의 대출 프로토콜입니다. 사용자는 하나의 토큰을 담보로 제공하고, 프로토콜 볼트에서 차입하며, 차입한 자금을 목표 토큰으로 스왑하여 현물 포지션을 개설할 수 있습니다. 이렇게 생성된 포지션은 정상 여부를 판단하기 위해 부채와 비교하여 검사됩니다.
DeFiTuna 현물 마켓에서 두 풀 토큰은 토큰 A와 토큰 B로 불립니다. 공격받은 마켓에서 토큰 A는 TUNA이고 토큰 B는 USDC였습니다.
USDC는 담보 토큰(collateral_token)이었습니다. 사용자는USDC를 증거금으로 예치하고, DeFiTuna의 볼트에서 추가USDC를 차입하며, 차입한USDC는TUNA로 스왑됩니다.TUNA는 포지션 토큰(position_token)으로, 스왑 후 포지션이 보유하는 자산입니다. 순효과는USDC부채로 자금을 조달한TUNA에 대한 레버리지 롱 포지션입니다.- 볼트 계정은 대출자의 유동성을 보유하며 차입 자금의 원천입니다.
- AMM 풀은
TUNA/USDC쌍에 대한 시장 유동성과 가격 컨텍스트를 제공합니다.
DeFiTuna는 Solana 스왑 집계기인 Jupiter를 통해 포지션 스왑을 라우팅합니다. 스왑 경로는 Jupiter 라우트 데이터와 라우트 계정으로 DeFiTuna 명령어에 제공됩니다. 호출자가 이 계정들을 제공하기 때문에, 호출자는 스왑이 사용하는 풀을 제어할 수 있습니다. 스왑 실행 전, DeFiTuna는 일반 시장 풀 가격을 오라클과 비교하여 사전 스왑 가격 검사를 수행합니다.
취약점 분석
버그가 있는 프로그램은 DeFiTuna(tuna4u...nogD)입니다.
근본 원인은 포지션 상태 검사의 결함 있는 제로값 분기였습니다. 스왑 후, DeFiTuna는 보유 중인 TUNA를 USDC 단위로 환산하여 포지션 가치를 평가했습니다. TUNA 잔액이 충분히 작아 0으로 내림 처리되면, total 필드가 0이 됩니다. 상태 검사 로직은 total == 0을 debt == 0 조건 없이 정상 상태로 처리했습니다.


공격 분석
두 가지 설계 특성으로 인해 공격자는 차입 자금이 라우팅되는 경로를 제어할 수 있었습니다. 첫째, DeFiTuna는 오라클 가격과 차입 금액으로부터 자체적으로 최소 허용 TUNA 출력을 도출하지 않고 호출자가 제공한 Jupiter RouteV2 데이터를 그대로 허용했습니다. 둘째, 사전 스왑 오라클 검사는 정상 DeFiTuna 마켓 풀만 검증했으며, Jupiter 라우트가 실제로 사용할 풀은 검증하지 않았습니다.

참고: 프로젝트 팀이 지지한 사고 후 분석 [1]에서는 공격자가 생성한 풀이 정상 오라클 가격 근처에서 초기화되었다고 설명합니다. 온체인 증거에 따르면 풀은 극단적인 가격으로 초기화되었으며, 사전 스왑 검사는 공격자가 제어하는 풀이 아닌 별도의 정상 마켓 풀을 검증했기 때문에 통과되었습니다.
다음 분석은 트랜잭션 4x33Dq...EXj1을 기반으로 합니다. 여러 공격 트랜잭션이 실행되었으며, 이 트랜잭션이 핵심 기법을 잘 보여줍니다.
- 1단계: 공격자는 새로운 Fusion
TUNA/USDC풀을 생성했습니다. 이 풀은 실제TUNA및USDC민트를 사용했지만 정상 DeFiTuna 마켓 풀과는 별개였습니다. 풀은 틱208636근처의 극단적인 가격으로 초기화되어TUNA1개당 약 10억 9천만USDC로TUNA가격이 책정되었습니다. 이 가격에서는 극히 소량의TUNA만으로도 스왑에서 수십만USDC를 흡수할 수 있었습니다.


- 2단계: 공격자는 새 풀에 두 개의 소규모 매도 측 지정가 주문을 배치했습니다. 각 주문은
0.000526 TUNA를 예치하여 총0.001052 TUNA가 되었습니다. 풀 가격이 극도로 높았기 때문에, 이 소량의TUNA공급으로도 스왑 실행 시 차입된 전체USDC금액을 흡수할 수 있었습니다.


- 3단계: 풀 준비가 완료된 후, 공격자는
TUNA를 포지션 토큰으로,USDC를 담보 토큰으로 하여 DeFiTuna 현물 포지션을 개설했습니다. 공격자는 담보로0 USDC를 제공하고 DeFiTuna의USDC볼트에서570,000 USDC를 차입했습니다.

- 4단계: 스왑 전, DeFiTuna는 정상 마켓 풀 가격을 오라클 가격과 비교했습니다. 정상 풀의 현물 가격이 오라클에 근접했기 때문에 검사를 통과했습니다. 이 검사는 정상 DeFiTuna 마켓 풀만 검증했으며, Jupiter 라우트가 사용할 Fusion 풀은 검증하지 않았습니다.

- 5단계: 스왑은 공격자가 제공한 Jupiter 라우트를 따랐으며, 최소 출력을 사실상 0으로 설정한 채 공격자가 제어하는 Fusion 풀을 통해 자금을 유도했습니다. 프로토콜 수수료 공제 후,
569,601 USDC가 공격 풀로 라우팅된 반면, DeFiTuna 포지션은TUNA의 원시 단위로494개(0.000494 TUNA)만 수신했습니다.


- 6단계: 스왑 후, 포지션은 약
570,000 USDC의 부채를 보유했으며 극히 소량의TUNA만 남아 있었습니다. DeFiTuna가 해당TUNA잔액을USDC가치로 환산했을 때, 결과가0으로 내림 처리되었습니다. 상태 검사는total == 0을 정상으로 처리했고, 불량 부채 포지션이 허용되었습니다.


- 7단계: 공격자는 공격자가 제어하는 Fusion 풀에 축적된
USDC를 인출했습니다. 두 번의 인출 금액은 거의 동일했으며, 2단계에서 생성된 두 개의 지정가 주문 포지션과 일치했습니다.
결론
근본 원인은 상태 검사의 total == 0 분기가 미상환 부채와 관계없이 포지션을 정상으로 허용한 것이었습니다. 공격자가 제어하는 라우팅과 유동성이 이 결함을 트리거하는 조건을 만들었지만, 불량 부채를 방지했어야 할 최종 컨트롤은 상태 검사였습니다.
가장 직접적인 수정 방법은 total == 0이고 debt > 0인 포지션을 거부하는 것입니다. 미상환 부채가 있는 제로값 포지션은 결코 정상이 아닙니다. 또한 프로토콜은 호출자가 제공한 라우트 파라미터와 독립적으로 오라클 가격과 차입 금액으로부터 최소 허용 스왑 출력을 도출해야 합니다. 오라클/가격 검사를 실제 스왑 풀에 바인딩하거나, 스왑 출력을 프로토콜이 계산한 하한값과 비교하여 검증하면, 검증되지 않은 풀을 통한 라우팅으로 사전 스왑 검사를 우회하는 것을 방지할 수 있습니다.
참고 자료
- [1] DeFiTuna 사고 후 성명
이번 주 추가 사고
BarnBridge
2026년 7월 15일, Ethereum의 수익 할당 프로토콜인 BarnBridge가 약 $776K의 USDC를 탈취당하는 익스플로잇 피해를 입었습니다 [1]. 근본 원인은 폐기된 거버넌스 컨트랙트가 중요한 프로토콜 구성을 수정할 권한을 계속 보유하고 있었던 것입니다. 공격자는 악의적인 제안을 통과시키기에 충분한 투표권을 획득하여 프로토콜 구성 요소의 컨트롤러를 교체한 다음, 새 컨트롤러를 사용하여 사용자가 승인한 USDC를 이체했습니다.
배경
BarnBridge는 수익 창출을 위해 다양한 대출 시장에 사용자 자금을 배분하는 DAO 거버넌스 프로토콜입니다. 투표권은 스테이킹된 BOND 수량과 잠금 기간에 따라 결정됩니다. 제안을 생성하려면 전체 투표권의 최소 1%에 해당하는 투표권이 필요합니다. 제안이 통과되려면 최소 40%의 쿼럼을 충족하고 참여한 전체 투표의 최소 60%가 찬성해야 합니다. 제출된 제안은 2일간의 준비 기간, 3일간의 투표 기간, 그리고 실행 전 2일간의 대기 기간을 거칩니다.
취약점 분석
근본 원인은 프로토콜이 더 이상 사용되지 않게 된 후에도 폐기된 거버넌스 컨트랙트가 중요한 프로토콜 구성을 수정할 권한을 계속 보유했던 것입니다. 거버넌스 시스템은 사용자가 이전에 USDC 지출을 승인한 컨트랙트인 CompoundProvider의 Controller 할당을 제어했습니다. BarnBridge가 더 이상 사용되지 않게 되면서 총 스테이킹된 BOND와 활발한 참여가 크게 감소하여, 적대적인 제안 통과가 매우 쉬워졌습니다.
공격 분석
다음 분석은 트랜잭션 0xd191fe...895afb를 기반으로 합니다.
공격자는 약 0.335 ETH를 사용하여 약 32,795 BOND를 취득한 뒤, 32,000 BOND를 예치 및 잠금 처리하여 전체 투표권의 약 43%를 확보했습니다.
- 1단계: 공격자는 프록시 컨트랙트를 배포하고 악의적인 제안을 제출했습니다. 2일간의 준비 기간이 지난 후, 공격자는 보유한 모든 투표권을 찬성에 행사하여 쿼럼과 승인 요건을 모두 충족시켰습니다.


- 2단계: 공격자는 제안을 큐에 등록했습니다. 2일간의 대기 기간이 지난 후, 공격자는 제안을 실행하여
CompoundProvider의Controller를 공격자의 프록시 컨트랙트로 설정했습니다.

- 3단계: 공격자는 프록시 컨트랙트의 로직을 업그레이드하고
_takeUnderlying()을 호출했습니다. 이 함수는 약 50명의 사용자가 부여한 미결USDC허용량을 사용하여 그들의USDC를CompoundProvider로 이체했습니다. 공격자는 이후transferFees()를 호출하여 자금을 공격자 주소로 전달하고 약 $776K의USDC수익을 얻었습니다.

결론
DAO 또는 프로토콜이 더 이상 사용되지 않게 될 경우, 거버넌스 컨트랙트는 보안에 중요한 구성 변경 권한, 특히 관리자, 컨트롤러 및 자금 인출 권한을 포기하거나 영구적으로 비활성화해야 합니다. 구체적인 조치로는 다운스트림 컨트랙트에 대한 거버넌스 컨트랙트의 관리자 역할 취소, 소각 주소로 소유권 이전, 또는 업그레이드 함수를 비활성화하고 컨트롤러 참조를 불변의 안전한 값으로 설정하는 최종 제안 실행 등이 있습니다. 더 이상 사용되지 않는 프로토콜에 거버넌스 권한을 유지하면 저비용 공격 표면이 생성됩니다. 참여가 감소함에 따라 쿼럼에 도달하는 데 필요한 자본도 비례하여 감소하기 때문입니다.



