Back to Blog

약 1,130만 달러 손실: Multicall Router, Nostra | BlockSec Weekly

Code Auditing
2026년 9월 24일
9 min read
Key Insights
  • 이 보고서는 Ethereum과 Starknet에서 발생한 총 약 1,130만 달러 규모의 손실을 기록한 2건의 보안 사고를 다룹니다. 두 수치 모두 사고 발생 시점의 추정치이며, Nostra Finance는 최종 손실액과 회수 금액이 아직 불확실하다고 밝혔습니다.

  • 두 사례 모두에서 인증 또는 가치 평가 검사는 실행되어 성공을 반환했지만, 잘못된 입력값을 평가했습니다. 한 라우터는 원래의 외부 호출자 대신 자체 중첩 호출로 도입된 신원을 수락했으며, 한 머니 마켓은 지나치게 적은 독립적 소스에 기반한 집계 가격을 수락했습니다.

  • 두 사고 모두 잘 알려진 프로토콜 자체의 결함을 필요로 하지 않았습니다. 문제는 기존 구성 요소에 연결된 커스텀 통합 코드에 있었으며, 한 사례에서는 Safe 모듈 스택, 다른 사례에서는 오라클 어댑터 구성이었습니다.

지난 한 주(2026/09/14 - 2026/09/20) 동안 총 2건의 보안 사고가 관측되었으며, 추정 총 피해액은 약 $11.3M입니다.

날짜 사고 유형 추정 피해액
2026/09/15 Unknown Multicall Router 부적절한 접근 제어 ~$7.8M
2026/09/17 Nostra Finance 잘못된 오라클 구성 ~$3.5M

Free Security Scan

A quick security pass with our in-house automated analysis engine.

Scan for free

이번 주 주요 사고: Unknown Multicall Router

이 사고는 중첩된 라우터 호출 과정에서 발생한 미묘한 호출자 신원 변경이 커스텀 모듈을 실행하던 Safe 지갑의 권한 검증을 무력화하여 대규모 자산 인출을 가능하게 했다는 점에서 선정되었습니다.

2026년 9월 15일, Yoink라는 이름으로 운영되는 MEV 봇이 커스텀 전략 모듈을 통해 자산을 관리하던 Safe 지갑에 대한 익스플로잇 시도를 프런트러닝했으며, 그 결과 약 $7.8M의 피해가 발생한 것으로 추정됩니다 [1]. 요청은 multicall 라우터를 통해 해당 모듈에 전달되었는데, 여기서 중첩 호출 권한 검증 오류로 인해 신뢰할 수 없는 명령이 모듈 체인으로 전달되었고, 재사용 가능한 권한이 무단 작업을 추가로 뒷받침했습니다.

배경

Safe 지갑은 Safe 모듈을 활성화할 수 있습니다. 활성화된 모듈은 execTransactionFromModule()을 호출하여 멀티시그 승인 없이 지갑이 작업을 실행하도록 지시할 수 있으므로, 활성화된 모듈은 지갑 자산에 대한 상시 권한이 됩니다. 피해 Safe 지갑은 Gateway 모듈과 LP 모듈이라는 두 개의 전략 구성 요소를 활성화한 상태였습니다.

Gateway 모듈은 재사용 가능한 명령 템플릿을 정의했으며, 각 템플릿은 피해 Safe 지갑이 수행할 수 있는 작업을 설명하고 구체적인 값은 실행 시점에 채워집니다. 이 모듈은 자체 승인 호출자 목록에 있는 호출자의 명령만 받아들였습니다. 또한 각 실행에는 호출되는 명령 템플릿을 인증하는 Merkle 증명이 포함되어야 했으며, 이는 저장된 루트와 대조하여 검증되었습니다. 일부 템플릿은 지갑이 LP 모듈을 호출하도록 지시했고, LP 모듈은 지갑의 자산을 사용하여 Uniswap v4 유동성 작업을 수행했습니다. 따라서 제어권은 한 모듈에서 다음 모듈로 곧바로 넘어가지 않고 지갑 자체를 거쳐 되돌아왔습니다:

Authorized Caller
       |
       v
Gateway module -- verify(command, Merkle proof, root)
       |
       | execTransactionFromModule(...)
       v
Safe wallet context
       |
       v
   LP module --> mintPosition(...)

이번 사고의 운영자들은 Gateway 모듈을 직접 호출하지 않았습니다. 요청은 일괄 호출을 대신 전달하는 multicall 라우터를 통해 도착했습니다. 정상적인 요청을 전달할 때 라우터가 직접 호출자였기 때문에, Gateway 모듈의 승인 호출자 목록에는 라우터 자체가 포함되어 있었습니다.

이 경로를 통해 피해 Safe 지갑은 공급된 rsETH에 대한 Aave 영수증 토큰인 aEthrsETH를 Uniswap v4 풀에 예치하고, 포지션 NFT를 지갑으로 발행받을 수 있었습니다. aEthrsETH를 보유한 누구나 Aave를 통해 이를 소각하고 기초 자산인 rsETH를 인출할 수 있었습니다.

피해 Safe 지갑은 해당 Aave 담보를 기반으로 대출도 받은 상태였습니다. 따라서 Aave는 담보 가치 대비 부채 비율인 헬스 팩터(health factor)를 추적했으며, 헬스 팩터가 1 아래로 떨어지게 되는 담보 이전은 거부합니다.

취약점 분석

0x4f00...8ebC의 라우터는 소스 코드가 검증되지 않았습니다. 따라서 다음 설명은 공식 소스 수준의 명칭이 아니라 배포된 바이트코드, 디컴파일된 로직, 트랜잭션 트레이스, 그리고 공개된 포크 테스트 재현 결과에 의존합니다.

라우터의 디스패치 로직은 허용 목록에 있거나 라우터 자신의 주소인 타깃을 받아들인 다음, 해당 타깃의 승인 호출자 목록을 현재 호출의 msg.sender와 대조하여 확인했습니다. 라우터가 자기 자신에게 수행하는 호출에서는 원래 외부 호출자의 신원을 유지하는 장치가 전혀 없었습니다.

라우터가 자기 자신을 호출하면 내부 호출은 라우터를 msg.sender로 인식했습니다. 권한 검증 헬퍼는 자기 자신을 타깃으로 하는 경우 라우터를 받아들였고, 그 외의 경우에는 현재 msg.sender가 다음 타깃의 승인 호출자 목록에 있는지 확인했습니다. 결과적으로 Gateway 모듈을 타깃으로 하는 내부 호출은 외부 호출자가 아니라 이미 승인된 라우터로부터 온 것으로 평가되었습니다. 이로 인해 신뢰할 수 없는 출처의 명령이 중첩 경로를 통해 Gateway의 호출자 권한 검증을 통과할 수 있었습니다.

두 번째 결함은 증명 검사 자체에 있었습니다. 증명은 명령 템플릿을 인증했지만, 함께 제공되는 런타임 매개변수를 묶어 검증하는 절차는 없었습니다. 따라서 이전의 정상적인 명령에 대해 발급된 유효한 증명은 구체적인 실행 값이 변경된 후에도 계속 사용할 수 있었습니다. 재사용된 증명은 사용 가능한 권한을 제공했지만, 신뢰할 수 없는 호출자가 애초에 Gateway 모듈에 도달할 수 있게 한 것은 중첩 권한 검증 우회였습니다.

공격 분석

동일한 명령 템플릿에 대해 이전에 발급된 Merkle 증명은 다른 런타임 값과 함께 계속 사용할 수 있었습니다. 이 특성이 그 자체로 Gateway의 호출자 권한 검증을 우회한 것은 아니지만, 중첩 라우터 경로가 해당 권한 검증을 충족시킨 뒤에 사용 가능한 권한을 제공했습니다.

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

성공한 트랜잭션 이전에, 원래 공격자는 공격 컨트랙트, 공격자가 통제하는 PAT 토큰, 그리고 이후 PAT 스왑을 수행할 두 번째 컨트랙트를 배포했습니다.

다음 블록에서 공격자는 prepare()를 호출하여 PAT/aEthrsETH Uniswap v4 풀을 생성하고 초기화했습니다.

Yoink MEV 봇은 대기 중인 익스플로잇을 감지하고 준비된 공격 컨트랙트를 호출하여 원래 공격자를 프런트러닝했습니다. 그 호출은 라우터에 진입하여 라우터가 자기 자신을 호출하게 했고, 이어 라우터를 msg.sender로 하여 Gateway 모듈에 도달했습니다. 활성화된 모듈인 Gateway는 이후 피해 Safe 지갑이 멀티시그 승인 없이 전달된 작업을 실행하도록 할 수 있었습니다.

해당 명령으로 인해 피해 Safe 지갑은 약 2,900개의 aEthrsETH를 틱 범위 [10, 20] 내에서 공격자가 통제하는 PAT/aEthrsETH 풀에 유동성으로 공급했습니다. 이 트랜잭션은 관련 Uniswap v4 포지션 NFT도 지갑으로 발행하여, 해당 작업이 예상된 유동성 흐름 안에서 이루어진 것처럼 보이게 했습니다. 이는 지갑의 aEthrsETH 전체 잔액을 가져간 것은 아니었습니다. Aave의 헬스 팩터 검사를 통과할 수 있도록 금액에 상한이 적용되었고, 지갑의 헬스 팩터는 1.001182484056805114로 남았습니다.

이후 공격 컨트랙트는 두 번째 컨트랙트를 통해 공격자가 통제하는 PAT를 예치된 aEthrsETH의 거의 전부와 교환했습니다. 그리고 획득한 영수증 토큰을 Aave를 통해 소각하고 해당하는 양의 rsETH를 인출했습니다. Yoink 봇에 도달한 약 2,900 rsETH 중 약 2,882.37 rsETH는 수익 수령자에게 전달되었고, 약 17.63 rsETHETH로 교환되었으며, 그 결과 얻은 ETH의 거의 전부는 블록 빌더에게 지급되었습니다.

결론

근본 원인은 단일 Safe 지갑에 연결된 커스텀 인프라의 권한 검증 결함이었으며, 모든 실행 매개변수를 묶어 검증하지 않는 권한이 이를 가중시켰습니다. 이를 Safe, Aave, Uniswap v4 또는 Kelp의 핵심 컨트랙트 탓으로 돌려서는 안 됩니다.

다른 주체를 대신해 호출을 전달하는 구성 요소는 호출 체인 중간에 얻게 되는 신원이 아니라 원래의 외부 호출자를 기준으로 권한을 판단해야 하며, 자기 자신을 타깃으로 호출할 수 없어야 합니다. 마찬가지로 권한은 작업이 속한 템플릿뿐 아니라 작업이 실행될 구체적인 값도 함께 묶어 검증해야 합니다.

Get Started with Phalcon Explorer

Dive into Transactions to Act Wisely

Try now for free

이번 주 기타 사고

Nostra Finance

2026년 9월 17일, Nostra의 Starknet 머니마켓이 부풀려진 NSTR 오라클 가격을 통해 익스플로잇되어, 과대평가된 담보를 기반으로 약 $3.5M 상당의 자산이 대출되었습니다. 근본 원인은 오라클 통합 구성이 너무 적은 수의 가격 소스만 허용하도록 되어 있어, 조작된 유동성이 얕은 풀의 시세가 집계 가격에 실질적인 영향을 미칠 수 있었다는 점입니다. Nostra는 마켓을 일시 중지했으며 [2], Pragma는 공격자의 주소가 동결되었고 복구 작업이 진행 중이라고 보고했습니다 [3]. 최종 피해액과 잠재적 회수 가능성은 아직 알려지지 않았습니다.

배경

Nostra는 Starknet에서 사용자가 지원되는 담보를 공급하고, 담보의 오라클 기반 가치에 따라 다른 자산을 대출받을 수 있는 머니마켓을 운영했습니다.

Nostra는 자체 가격 피드 컨트랙트를 통해 NSTR 가격을 얻었으며, 이 컨트랙트는 Starknet에서 집계된 가격을 게시하는 오라클인 Pragma에서 값을 읽는 메인 오라클 컨트랙트에 위임했습니다. 게시자들은 AVNU와 GECKOTERMINAL을 포함한 명명된 소스로 Pragma에 관측값을 제출했으며, 문서화된 NSTR 구성은 이 중 세 개에 대한 중앙값을 사용하는 것으로 기술되어 있었습니다 [4][5]. 각 오라클 응답에는 가격, 소수점 정밀도, 타임스탬프, 기여한 소스 수가 포함되었습니다 [6]. 메인 오라클 컨트랙트는 기여 소스의 최소 개수를 설정할 수 있는 MinAggregatedSources를 저장했습니다.

배포된 집계 구현은 직접 확인하지 않았습니다. 그럼에도 두 가지 독립적인 정황이 같은 방향을 가리킵니다. Pragma의 오픈소스 코드는 항목 수가 짝수일 때마다 가운데 두 항목의 평균을 반환하며 [6], 이번 사고에서 관측된 MEDIAN 응답은 기여한 두 관측값의 산술 평균과 같았습니다.

이러한 소스의 수치는 시장에서 나왔습니다. GECKOTERMINAL 관측값은 온체인 풀에서 도출될 수 있으며, Starknet에서 그러한 거래소 중 하나가 Uniswap v3와 유사하게 집중 유동성을 사용하는 탈중앙화 거래소인 Ekubo입니다. 유동성 공급자는 선택한 틱 범위 내에 자산을 배치하고, 스왑은 활성 범위를 지나며 풀 가격을 이동시키는데, 활성 유동성이 없는 구간은 가격이 크게 다른 곳에 배치된 포지션들을 갈라놓을 수 있습니다.

Nostra는 이 오라클 경로로 얻은 NSTR 가격을 사용하여 예치된 담보의 가치를 평가하고 계정의 대출 한도를 계산했습니다.

취약점 분석

Nostra의 머니마켓은 문서에서 NSTR 가격 피드로 나열한 컨트랙트인 0x6838...5bf0에서 NSTR 가격을 읽었습니다 [7]. 이 컨트랙트는 지정된 메인 오라클 0x7b05...f0ab에 위임했으며, 이 오라클의 MinAggregatedSources1로 설정되어 있었습니다. Pragma는 최소 세 개의 가격 소스를 권장하며, 사고 이후 세 개 소스의 최소 요건이 강제되었다면 이번에 수락된 응답은 거부되었을 것이라고 보고했습니다 [3].

따라서 두 개의 유효한 관측값을 포함한 응답은 설정된 임계값을 초과했습니다. 두 관측값에 대한 MEDIAN 계산이 그 산술 평균으로 귀결되기 때문에, 다른 관측값이 통상적인 시장 가격에 가깝게 유지되더라도 하나의 극단적인 시세가 결과를 크게 왜곡할 수 있었습니다.

이는 소수점 스케일링이나 중앙값 구현의 오류가 아니라 통합 구성상의 약점이었습니다. Pragma는 두 계산 모두에서 결함을 발견하지 못했습니다 [3]. 불충분한 소스 임계값 때문에, 충분히 다양하지 않은 입력 집합에서 올바르게 계산된 출력이 담보 가치와 대출 한도를 결정하게 되었습니다.

공격 분석

이 공격은 새로 생성되어 자금이 얕은 집중 유동성 풀의 조작 가능성에 의존했습니다. 확인 가능한 증거에 따르면 공격자의 풀 시딩과 반복적인 활동이 GECKOTERMINAL 관측값에 사용된 풀에 영향을 미쳤을 가능성이 있으나, 정확한 풀 선택의 인과관계는 확인되지 않았습니다.

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

공격자는 먼저 Ekubo NSTR/SolvBTC 풀을 생성하고, 더 낮은 비활성 가격 범위에 1.5 SolvBTC를 단일 자산 유동성으로 공급했습니다. 이후 공격자는 정상 시장 가격 부근에 약 1,900 NSTR와 0.0001514751 SolvBTC를 추가하고 풀에서 반복적으로 스왑을 수행했습니다.

다음으로 공격자는 정상 가격보다 훨씬 높은 좁은 범위에 190 NSTR를 단일 자산 유동성으로 배치했습니다. 정상 시장 가격 부근의 유동성을 제거한 뒤, 공격자는 이 고가 포지션 앞에 유동성이 없는 공백 구간을 남겼습니다.

단 0.00000001 SolvBTC만 포함한 스왑이 빈 범위를 가로질러 풀을 고가 포지션의 경계인 틱 -6645400으로 이동시켰습니다. 조작된 풀 가치는 이후 GECKOTERMINAL NSTR/USD 관측값인 $99.02439975로 제출되었습니다.

AVNU로 제출된 또 다른 기여 관측값은 NSTR를 $0.00596118로 평가했습니다. 해당 응답에는 구성된 세 번째 소스의 관측값이 나타나지 않아, 이 두 값만이 집계에 도달했습니다 [4].

값이 두 개이므로 MEDIAN 응답은 이들의 산술 평균인 NSTR당 약 $49.51518046이었습니다. Nostra는 그 결과 평가액을 수락하고 공격자의 NSTR 예치금을 상당한 규모의 대출을 위한 충분한 담보로 취급했습니다.

확인된 첫 번째 인출에서 공격자는 NSTR 담보를 보유한 별도의 계정을 사용하여 부풀려진 평가액으로 약 939.386010 ETH를 대출받았습니다 [4]. Nostra는 전체 대출 과정에 STRK, USDC, USDT, WBTC, DAIv1도 포함되었으며 총 대출 가치는 약 $3.5M이라고 보고했습니다 [2].

결론

이번 사고는 Pragma의 소수점 처리나 집계 계산 오류가 아니라 Nostra 통합의 불충분한 오라클 소스 임계값에서 비롯되었습니다. 하나의 관측값이 조작 가능성이 매우 높은 풀에서 나왔음에도 두 개 소스로 구성된 응답이 유효한 것으로 처리되었습니다.

Nostra는 최소 세 개 이상의 기여 가격 소스를 강제해야 하며, 담보 평가나 대출에 가격을 사용하기 전에 소스 수가 해당 임계값 미만인 오라클 응답은 모두 거부해야 합니다. 또한 담보 적격성과 익스포저 한도는 각 자산의 기초 가격 소스를 조작하는 데 필요한 시장 유동성과 깊이를 반영해야 합니다.

Get Started with Phalcon Security

Detect every threat, alert what matters, and block attacks.

Try now for free

참고 자료

[1] https://x.com/Phalcon_xyz/status/2099741447776096270

[2] https://x.com/nostrafinance/status/2100577538053493076

[3] https://www.pragma.build/updates/nostra-nstr-incident

[4] https://x.com/Phalcon_xyz/status/2100818035082952751

[5] https://www.pragma.build/asset/NSTR-USD?network=mainnet

[6] https://github.com/Astraly-Labs/pragma-oracle

[7] https://docs.nostra.finance/lend-and-borrow/deployed-contracts/money-market-mainnet

BlockSec 소개

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

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

Best Security Auditor for Web3

Validate design, code, and business logic before launch

Best Security Auditor for Web3

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

BlockSec Audit