Back to Blog

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

Code Auditing
June 25, 2026
9 min read
Key Insights

지난 한 주간(2026/06/15 - 2026/06/21), 총 약 $18.3M의 손실을 초래한 주목할 만한 보안 사고 3건이 발생했습니다.

날짜 사고 유형 추정 손실
2026/06/18 Aztec 부적절한 공개 입력 바인딩 ~$2.2M
2026/06/20 LABUBU Token 잘못된 설정 ~$1.1M
2026/06/20 jaredFromSubway 부적절한 승인 관리 ~$15M
  • Aztec: 해당 프로토콜이 사흘 만에 두 번째로 익스플로잇되었으며, 이번에는 이스케이프 해치 회로를 통해 공격이 이루어져 ZK 증명 바인딩 문제가 반복적으로 발생하고 있음을 부각시켰기 때문에 선정되었습니다.
  • jaredFromSubway: MEV 봇의 컨트랙트가 소비 여부를 확인하거나 잔여 허용량을 취소하지 않고 신뢰할 수 없는 토큰 컨트랙트에 승인을 부여하여, 공격자가 ~$15M을 누적 및 탈취할 수 있었기 때문에 선정되었습니다.

Web3 최고의 보안 감사자

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

이번 주 하이라이트: jaredFromSubway

기존의 승인 익스플로잇 — 공격자가 신뢰할 수 있는 DeFi 컨트랙트의 취약점을 악용하여 사용자가 해당 컨트랙트에 승인한 자산을 탈취하는 방식 — 과 달리, 이번 공격은 반대 방향을 노렸습니다. MEV 봇이 재정거래 운영의 일환으로 자체 자산에 대한 승인을 신뢰할 수 없는 제3자 컨트랙트에 능동적으로 부여한 것입니다. 공격자는 가짜 스왑 풀이 실제 SwapSync 이벤트를 발생시키면서 가짜 토큰은 부여된 허용량을 소비하지 않는 가짜 거래 환경(사실상 허니팟)을 구성하여 외부로 향하는 승인을 누적한 뒤 한꺼번에 수확했으며, 총 손실은 약 $15M으로 보고되었습니다.

2026년 6월 20일, 이더리움의 MEV 봇 운영자 jaredFromSubway는 약 $15M의 손실을 입었습니다 [1]. 온체인 분석에 따르면, 근본 원인은 봇 컨트랙트의 부적절한 승인 관리였습니다. 신뢰할 수 없는 래퍼 컨트랙트에 승인이 부여되었으나 해당 컨트랙트가 이를 소비하지 않았고, 공격자는 이 미소비 허용량을 누적한 뒤 단일 트랜잭션으로 봇의 실제 잔액을 탈취했습니다.

배경

jaredFromSubway는 이더리움에서 샌드위치 공격과 온체인 차익거래를 전문으로 하는 잘 알려진 MEV 봇 운영자입니다. 피해 컨트랙트(0x1f2f...f387)는 운영 지갑 중 하나로, WETH, USDC, USDT의 대규모 운전자본 잔액을 보유하고 있습니다.

이러한 유형의 MEV 봇은 온체인에 등장하는 임의의 새로운 토큰 및 풀과 동적으로 상호작용해야 합니다. 봇은 멤풀을 모니터링하고, 트랜잭션을 시뮬레이션하며, 차익거래 기회를 포착하기 위해 자동으로 토큰 상호작용을 승인합니다. 이 운영 모델은 토큰이 예상대로 동작한다는 가정, 즉 스왑이 실행될 때 토큰 컨트랙트가 transferFrom을 호출하여 부여된 허용량을 소비한다는 가정에 의존합니다.

취약점 분석

근본 원인은 신뢰할 수 없는 컨트랙트와 상호작용할 때 MEV 봇의 부적절한 승인 관리입니다.

봇은 Uniswap 풀 및 라우터를 통해 다양한 차익거래 경로를 실행합니다. 대부분의 상호작용에서 봇은 transfer를 통해 직접 풀에 토큰을 전송하며, 이 경우 봇 자신이 msg.sender이므로 승인이 필요하지 않습니다. 그러나 래퍼 방식의 토큰 컨트랙트와의 상호작용은 풀(pull) 모델을 따릅니다. 봇이 wrapper.wrapTo()를 호출하면, 해당 호출 내부에서 래퍼 컨트랙트가 realToken.transferFrom(bot, wrapper, amount)를 호출하여 봇의 실제 토큰을 가져갑니다. transferFrommsg.sender는 봇이 아닌 래퍼 컨트랙트이므로, 사전 approve가 필요합니다:

  1. <real_token>.approve(tokenContract, amount) — 래퍼 컨트랙트에 실제 토큰의 허용량 부여
  2. tokenContract.wrapTo() → 풀을 통한 다중 홉 swap()tokenContract.unwrap() — 실제 토큰을 래핑하고, 풀을 통해 라우팅한 후, 실제 토큰으로 언래핑

봇은 정상적인 래퍼 컨트랙트처럼 wrapTo()transferFrom을 통해 허용량을 소비할 것이라고 가정했습니다. 그러나 봇은 작업 후 허용량이 실제로 소비되었는지 확인하지 않았고, 잔여 허용량을 취소하지도 않았습니다. wrapTo()transferFrom을 호출하지 않으면, 전체 허용량이 작업 후에도 남아 지속적인 공격 표면이 됩니다 — 해당 허용량을 보유한 모든 컨트랙트는 나중에 transferFrom을 호출하여 봇의 실제 자산을 이동시킬 수 있습니다.

공격 분석

온체인 재구성에 따르면, 공격자는 위에서 설명한 취약점을 악용하기 위해 세 가지 구성 요소로 이루어진 가짜 거래 환경을 구축했습니다:

  1. 가짜 래퍼 토큰: 각 가짜 토큰은 실제 토큰의 이름을 사용했지만 심볼에 f를 접두사로 붙였습니다(예: USDC의 경우 이름 USD Coin, 심볼 fUSDC). 합법적인 래퍼를 모방하기 위해 wrapTo()unwrap()을 구현했으며, 미소비 허용량을 transferFrom을 통해 탈취하는 공격자 전용 withdraw() 함수도 포함했습니다.

  2. 가짜 스왑 풀: 공격자는 자체 배포한 팩토리를 통해 약 44개의 Uniswap V2 스타일 풀을 배포했습니다. 이 풀들은 가짜 토큰끼리 페어링하여 설득력 있는 스왑 경로를 형성했습니다. swap()이 호출되면, 풀은 합법적인 거래와 구별할 수 없는 실제 SyncSwap 이벤트를 발생시켰습니다.

  3. 공격자가 조작한 수익: unwrap() 중에 가짜 토큰은 transfer를 통해 소량의 실제 토큰을 봇에 돌려보냈습니다. 봇은 실제 수익을 받았지만, 이는 시장 차익거래로 얻은 것이 아니라 공격자가 의도적으로 조작한 것이었습니다.

공격자는 외부 컨트랙트의 블록별 getStatus() 스위치를 통해 이러한 구성 요소를 제어했습니다. getStatus()는 활성화 트랜잭션과 동일한 블록에서 호출될 경우(해당 트랜잭션이 _getStatus = block.number를 설정) 1을 반환하고, 그렇지 않으면 0을 반환했습니다. getStatus() == 0일 때, wrapTo()transferFrom을 정상적으로 호출하여 허용량을 소비했습니다. getStatus() == 1일 때, wrapTo()transferFrom을 건너뛰어 허용량이 소비되지 않았으며, unwrap()은 여전히 공격자가 조작한 토큰을 봇에 반환했습니다. 공격자는 허용량을 누적하고자 할 때 빌더 뇌물을 이용하여 활성화 트랜잭션을 봇의 트랜잭션과 동일한 블록에 배치한 것으로 보입니다.

공격은 세 단계로 진행되었습니다:

1단계: 공격 인프라 배포

  • 단계 1: 공격자는 블록 25354424부터 25354519에 걸쳐 인프라를 구축했습니다. 여기에는 가짜 토큰 팩토리 컨트랙트(0x81f2...0091) 배포, 자체 배포한 팩토리를 통한 ~44개의 가짜 Uniswap V2 풀 생성, swap() 호출이 성공할 수 있도록 풀에 초기 토큰 잔액 충전, 가스 및 빌더 뇌물을 위해 수확 컨트랙트(0xb84d...df52)에 0.01 ETH 전송이 포함되었습니다.

  • 단계 2: 공격자는 CREATE2를 통해 가짜 래퍼 토큰을 대량으로 생성했으며, 각 토큰은 실제 토큰을 모방하고(실제 이름 사용, 심볼에 f 접두사) 공격자 전용 withdraw() 함수를 포함했습니다. CREATE2는 수확 컨트랙트가 반복할 수 있는 결정론적 주소를 제공했습니다.

2단계: 신뢰 구축 및 승인 누적

  • 단계 3 (초기 신뢰 구축): 초기 트랜잭션(예: 블록 25354425의 0x542d...362b)에서 가짜 토큰에는 getStatus() 스위치가 없어 wrapTo()transferFrom을 직접 호출하여 허용량을 소비했습니다. 봇은 정상적으로 승인, 래핑, 스왑, 언래핑, 수익을 경험했습니다. 이를 통해 가짜 토큰이 수익성 있는 거래 기회로 신뢰를 쌓았습니다.

  • 단계 4 (신뢰 지속): 이후 트랜잭션(예: 0x085e...37e51)에서 getStatus() 스위치가 배포되었으나 0을 반환했습니다(활성화 트랜잭션과 다른 블록). wrapTo()는 여전히 transferFrom을 호출하여 허용량을 소비했습니다. 봇은 계속 수익을 내며 상호작용을 유지했습니다.

  • 단계 5 (누적): 블록 25360519의 0x8560...1915부터 공격자는 빌더 뇌물을 통해 활성화 트랜잭션을 봇의 트랜잭션과 동일한 블록에 배치하여 getStatus()가 1을 반환하도록 했습니다. 이 모드에서 wrapTo()transferFrom을 건너뛰어 허용량이 소비되지 않았지만, unwrap()은 여전히 소량의 실제 토큰을 봇에 반환했습니다. 봇은 수익성 있는 작업으로 인식하고 승인을 그대로 유지했습니다. 약 600개 블록(~13개 트랜잭션)에 걸쳐 봇은 WETH, USDC, USDT 전반에 걸쳐 이 패턴을 반복하며 세 가지 실제 자산 모두에 미소비 허용량을 누적했습니다.

3단계: 수확

  • 단계 6: 공격자는 수확 트랜잭션 0x2be870...cf3e65에서 모든 가짜 토큰의 withdraw()를 호출하여, 미소비 허용량을 이용해 transferFrom을 호출하고 봇의 실제 잔액을 공격자에게 이전했습니다. 블록 포함을 보장하기 위해 0.01 ETH의 빌더 뇌물이 포함되었습니다. 이 수확으로 피해 컨트랙트에서만 1,474.58 WETH + 2,870,573 USDC + 2,035,760 USDT (~$7.5M)가 탈취되었습니다.

확인된 공격 트랜잭션으로 인한 손실은 약 $7.5M이며, jaredFromSubway의 주장 [1]에 따른 총 손실은 약 $15M입니다.

결론

이번 사고의 근본 원인은 신뢰할 수 없는 컨트랙트와 상호작용할 때 MEV 봇의 부적절한 승인 관리였습니다. 공격자가 신뢰할 수 있는 DeFi 컨트랙트의 취약점을 악용하여 사용자가 승인한 자산을 탈취하는 기존 승인 익스플로잇과 달리, 이번 공격은 반대 방향으로 작동했습니다. 봇이 차익거래 운영의 일환으로 자체 자산을 신뢰할 수 없는 제3자 컨트랙트에 능동적으로 승인한 것입니다. 공격자는 이러한 외부로 향하는 미소비 승인을 누적한 뒤 단일 트랜잭션으로 수확했습니다.

향후 유사한 위험을 줄이기 위해, 신뢰할 수 없는 토큰 컨트랙트와 상호작용하는 봇 컨트랙트는 각 작업 후 승인이 소비되었는지 확인하고 잔여 허용량을 취소해야 합니다. 성공적으로 보이는 거래 후 미소비 허용량은 악의적인 토큰 동작의 강력한 신호입니다.

Phalcon Explorer 시작하기

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

지금 무료로 체험하기

이번 주 기타 사고

Aztec

2026년 6월 18일, Aztec의 이스케이프 해치 ZK 회로에서 등호 제약 조건이 누락되어 공격자가 이더리움의 레거시 RollupProcessor 컨트랙트에서 약 $2.2M(1,158 ETH, 150K DAI, ~0.47 renBTC)을 인출할 수 있었습니다 [2], [3]. 이는 사흘 만에 발생한 두 번째 Aztec 익스플로잇으로(첫 번째는 이전 보고서에서 다룬 업그레이드된 RollupProcessorV3를 대상으로 했습니다), 관련된 ZK 회로 공개 입력 바인딩 버그를 통해 발생했습니다.

배경

Aztec의 레거시 RollupProcessor에는 escapeHatch 함수가 포함되어 있습니다. 이는 롤업 운영자가 처리를 중단했을 때 누구든지 단일 트랜잭션 증명을 제출할 수 있는 안전 메커니즘입니다. 권한 있는 제공자가 필요한 processRollup과 달리, 이스케이프 해치는 블록 번호에 따라 주기적인 창이 열리며 누구든지 호출할 수 있습니다:

function escapeHatch(
    bytes calldata proofData,
    bytes calldata signatures,
    bytes calldata viewingKeys
) external override whenNotPaused {
    (bool isOpen, ) = getEscapeHatchStatus();
    require(isOpen, 'Rollup Processor: ESCAPE_BLOCK_RANGE_INCORRECT');
    processRollupProof(proofData, signatures, viewingKeys);
}

이스케이프 해치는 전용 ZK 회로(escape_hatch_circuit)를 사용하여 조인-스플릿 트랜잭션을 처리합니다. 즉, 머클 트리에서 입력 노트를 소비하고 출력 노트를 생성합니다. 회로는 입력 노트가 현재 데이터 트리에 존재하는지 확인하고(old_data_root를 머클 멤버십 증명에 사용), 동일한 루트를 공개 입력으로 노출하여 L1 컨트랙트가 온체인 상태와 대조 검증할 수 있어야 합니다.

취약점 분석

취약점은 이스케이프 해치 회로(escape_hatch_circuit.cpp)에 있습니다. old_data_root 값이 두 개의 독립적인 증인으로 변환되지만, 이를 연결하는 등호 제약 조건이 없습니다.

첫 번째 증인(33번째 줄)은 조인-스플릿 회로 구성 요소에 전달되어, 입력 노트가 데이터 트리에 존재하는지 확인하는 머클 멤버십 증명에 사용됩니다:

join_split_inputs inputs = {
    // ...
    witness_ct(&composer, tx.js_tx.old_data_root),        // 33번째 줄: 첫 번째 증인
    // ...
};
auto outputs = join_split_circuit_component(composer, inputs);

두 번째 증인(50번째 줄)은 독립적으로 생성되어 공개 입력으로 노출되며(88번째 줄), Solidity 컨트랙트가 이를 추출하여 온체인 데이터 루트와 비교합니다:

auto old_data_root = field_ct(witness_ct(&composer, tx.js_tx.old_data_root));  // 50번째 줄: 두 번째 증인
// ...
composer.set_public_input(old_data_root.witness_index);    // 88번째 줄: 공개 입력으로 노출

ZK 회로에서 각 witness_ct 호출은 독립적인 변수를 생성합니다. 33번째 줄과 50번째 줄 사이에 명시적인 assert_equal이 없으면, 증명자는 두 증인에 서로 다른 값을 할당할 수 있습니다. Solidity 측에서 validateMerkleRoots는 50번째 줄의 공개 입력만을 사용하여 require(oldDataRoot == dataRoot)를 확인하며, 33번째 줄에서 사용된 값은 볼 수 없습니다.

동일한 언바인딩 패턴이 input_owneroutput_owner에도 존재합니다. 이 값들은 38~39번째 줄(소유권 검증을 위해 join_split_circuit_component에 전달)과 111~112번째 줄(독립적인 공개 증인으로 노출)에서 각각 증인으로 생성됩니다. 그러나 이 간격에 대한 실질적인 익스플로잇 경로는 아직 확인하지 못했습니다.

공격 분석

이스케이프 해치 회로는 aztec-connect 코드베이스에서 제거되었지만 [4], 배포된 검증자 컨트랙트에는 여전히 EscapeHatchVk 검증 키가 포함되어 있어 취약한 회로로 생성된 증명이 온체인 검증을 통과할 수 있습니다. 공격 당시 컨트랙트는 142일간 활동이 없었고 이스케이프 해치 창이 열려 있었습니다. 공격자의 주소는 Union Chain을 통해 익스플로잇 14시간 전에 생성되었습니다 [2]. 공격은 세 가지 핵심 단계로 구성됩니다:

  • 단계 1: 공격자는 임의의 가치를 가진 자기 소유 노트를 포함하는 가짜 머클 트리를 구성했습니다. 이 노트들은 실제 온체인 데이터 트리(모든 유효한 노트를 저장하는 머클 트리)에 존재하지 않았습니다.

  • 단계 2: 공격자는 위에서 설명한 언바운드 증인을 악용하는 이스케이프 해치 증명을 생성했습니다. 33번째 줄의 증인(조인-스플릿 구성 요소의 머클 멤버십에 사용)은 가짜 머클 루트로 설정되었습니다(조작된 노트가 가짜 트리에 존재했으므로 멤버십 확인이 통과되었고, 공격자가 서명 키를 보유했으므로 소유권 확인도 통과). 50번째 줄의 증인(Solidity가 확인하는 공개 입력으로 노출)은 실제 온체인 데이터 루트로 설정되었습니다(이 값이 컨트랙트에 저장된 루트와 일치했으므로 Solidity의 require(oldDataRoot == dataRoot) 확인이 통과).

  • 단계 3: 회로와 Solidity 확인이 모두 통과되면서 증명이 성공적으로 검증되었습니다. 컨트랙트는 이스케이프 해치 트랜잭션을 합법적인 것으로 처리하고 자금을 해제했습니다.

공격자는 이 과정을 세 개의 트랜잭션(0x9e1d6a...6b03ca, 0xab306c...59c2b5, 0x5c196c...4705c3)에 걸쳐 반복하며 서로 다른 자산을 대상으로 1,158 ETH, 150K DAI, ~0.47 renBTC를 각각 탈취하여 총 약 $2.2M을 편취했습니다.

결론

이번 사고의 근본 원인은 이스케이프 해치 회로에서 old_data_root의 두 증인 사이에 등호 제약 조건이 누락된 것이었습니다. 하나의 증인은 조인-스플릿 구성 요소 내부에서 프라이빗 노트 멤버십 검증에 사용되었고, 다른 하나는 Solidity가 확인하는 공개 입력으로 노출되었습니다. 이를 바인딩하는 제약 조건이 없어 공격자는 가짜 머클 트리에 대해 조작된 노트의 소유권을 증명하는 동시에 L1 컨트랙트에는 유효한 온체인 루트를 제시할 수 있었습니다. 특히, 소스에서 취약한 회로를 제거하는 것만으로는 이미 배포된 검증자 컨트랙트를 무력화하지 못합니다 — 레거시 RollupProcessor의 escapeHatch 함수는 블록 번호 창이 열릴 때마다 여전히 호출 가능합니다.

향후 유사한 위험을 줄이기 위해, ZK 회로의 여러 지점에 동일한 논리적 값이 나타날 경우 모든 인스턴스가 명시적으로 동일하도록 제약되어야 합니다 — 동일한 값에 대한 독립적인 witness_ct 호출은 바인딩 간격입니다. 회로 감사는 모든 공개 입력이 해당 값이 나타내는 회로 내부 값에 바인딩되어 있는지 체계적으로 검증해야 합니다.

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 논스 도출 시 비밀 입력이 제거되는 결함으로 공개 트랜잭션 데이터만으로 개인 키 복구가 가능했습니다.

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

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

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

~$598만 달러 손실: Aztec, Raydium 등 | BlockSec 위클리
Security Insights

~$598만 달러 손실: Aztec, Raydium 등 | BlockSec 위클리

이 주간 블록체인 보안 리포트는 2026년 6월 8일~14일을 다루며, 이더리움과 솔라나에서 발생한 4건의 주요 사고를 분석하고 총 손실액은 약 598만 달러입니다. Aztec Connect의 입력 검증 누락으로 롤업 증명 경로와 L1 정산 불일치가 발생했고, Raydium의 레거시 AMM v3 검증 누락으로 LP 토큰 상환 계산이 조작되어 4개 풀이 탈취됐습니다. 두 취약점 모두 수년간 노출된 상태였습니다. 입력 검증 부재, 정수 오버플로우, 거버넌스 탈취 등의 공격 유형을 다룹니다.

Best Security Auditor for Web3

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

BlockSec Audit