Back to Blog

배열 금융 보안 사고 분석

Code Auditing
2021년 7월 19일
4 min read

7월 18일, 저희 DeFiRanger 시스템이 몇 가지 의심스러운 트랜잭션을 보고했습니다. 수동 분석 후, 이 트랜잭션들이 Array Finance에 대한 공격임을 확인했습니다. 이하에서는 공격 트랜잭션을 사용하여 공격 과정과 취약점의 근본 원인을 설명하겠습니다.

공격 트랜잭션

이 블로그에서 사용된 공격 트랜잭션은 다음과 같습니다: 0xa17bbc7c9ab17aa88fdb5de83b41de982845e9c9c072efff6709dd29febf0daa

공격 흐름

Figure 1
Figure 1

그림 1에서 볼 수 있듯이, 공격자는 AAVE에서 플래시 론을 빌린 후 186.62 WETH의 수익을 얻었습니다. (이 블로그에서는 WETH와 ETH를 명시적으로 구분하지 않습니다.)

Figure 2
Figure 2

자세한 공격 과정은 그림 2에 나와 있습니다.

  • 먼저, 공격자는 Array Finance의 buy 함수를 호출했습니다. 공격자는 45.91 WETH를 사용하여 Array Finance가 발행한 430 ARRAY 토큰을 획득했습니다.
  • 그런 다음 공격자는 클로즈드 소스 컨트랙트(Array Collater - 0xa800cda5)의 joinPool 함수를 다섯 번 호출했습니다. 그는 676,410.58 DAI + 679,080.46 USDC + 901.82 WETH + 20 WBTC + 20 renBTC를 예치하고 Array Collater가 발행한 726.38 aBPT 토큰을 획득했습니다.
  • 공격자는 sell 함수를 호출하여 430 ARRAY 토큰을 소각하고 77.17 aBPT 토큰을 받았습니다.
  • 마지막으로, 공격자는 Array Collater의 exitPool 함수를 호출했습니다. 그는 이전 두 단계에서 획득한 804.55 aBPT 토큰을 소각하고 748,271.55 DAI + 751,225.08 USDC + 997.62 WETH + 22.63 WBTC + 22.74 renBTC를 획득했습니다.

그림 2에서 공격자가 5단계(그림 2: sell 함수 호출)에서 수익을 얻는 것을 확인할 수 있습니다. 이는 획득한 77.17 aBPT 토큰이 3단계(그림 2: buy 함수 호출)에서 예치한 49.9142 WETH보다 더 가치가 있기 때문입니다. 이하에서는 이 공격이 왜 가능한지 이해하기 위해 코드를 분석하겠습니다.

코드 취약점

다음 코드는 Array Finance의 sell 함수를 보여줍니다. 이 함수에서 Array Finance는 공격자가 보유한 ARRAY 토큰의 잔액을 사용하고 내부 _sell 함수를 호출하여 ARRAY 토큰을 판매함으로써 얻을 수 있는 aBPT 토큰의 수를 계산합니다.

다음은 _sell 함수의 구현입니다. 이 함수는 calculateLPtokensGivenArrayTokens를 호출하여 일정 수의 ARRAY 토큰으로 얻을 수 있는 aBPT 토큰의 수를 구합니다. 그런 다음 이 함수는 ARRAY 토큰을 소각하고 aBPT 토큰을 반환합니다.

다음은 calculateLPtokensGivenArrayTokens 함수의 구현을 보여줍니다.

amountLPToken의 계산에 영향을 미칠 수 있는 네 가지 인수가 있습니다. saleTargetAmount를 읽은 후, 공식은 다음과 같이 추론됩니다:

arraySmartPool.totalSupply() * (1 - (1 - amount / ARRAY.totalSupply()) ^ (1000000 / reseveRatio))
 

arraySmartPool은 Array Collater(0xa800cda5f3416a6fb64ef93d84d6298a685d190d)의 스마트 컨트랙트 주소입니다. arraySmartPool.totalSupply()의 값은 공격자가 플래시 론으로 빌린 자금을 Array Collater에 예치할 때 증가합니다(다음 표 참조).

TxnIndex: 64 arraySmartPool.totalSupply():  110162296218708026400
TxnIndex: 107 arraySmartPool.totalSupply():  165243444328062039600
TxnIndex: 150 arraySmartPool.totalSupply():  247865166492093059400
TxnIndex: 193 arraySmartPool.totalSupply():  371797749738139589100
TxnIndex: 236 arraySmartPool.totalSupply():  557696624607209383650
TxnIndex: 280 arraySmartPool.totalSupply():  836544936910814075475

이 로직은 arraySmartPool의 코드를 읽은 후 확인할 수 있습니다. 다음은 arraySmartPool의 joinPool 함수를 보여줍니다.

이 함수는 먼저 SmartPoolManager.joinPool 함수를 호출하여 msg.sender로부터 얻어야 하는 토큰 수(actualAmountsIn)를 계산합니다. 그런 다음 각 토큰에 대해 _pullUnderlying 함수를 호출하여 해당 토큰을 arraySmartPool에 예치합니다. 마지막으로 _mintPoolShare_pushPoolShare를 호출하여 aBPT 토큰을 발행하고 발행된 aBPT 토큰을 msg.sender에게 전송합니다.

arraySmartPool은 PCToken으로부터 상속받는다는 점에 유의하세요. _mintPoolShare 함수는 _mint 함수를 호출하며, 이는 다음과 같이 나타납니다.

_mint 함수는 varTotalSupply 변수를 증가시키며, 이 값은 totalSupply()에 의해 직접 반환됩니다. 따라서 이 값은 joinPool이 호출될 때마다 증가합니다.

수익 추정

요약

요약하자면, 공격자는 Array Finance의 가격 메커니즘이 조작 가능한 aBPT 토큰의 totalSupply에 의존한다는 취약점을 악용했습니다. 이 취약점은 저희 연구 논문 DeFiRanger: DeFi 애플리케이션의 가격 조작 공격 탐지에서 논의되었습니다.

크레딧

Junjie Fei, Yufeng Hu, Ziling Lin, Siwei Wu, Lei Wu, Yajin Zhou @BlockSec

(성의 알파벳 순서)

BlockSec 소개

BlockSec은 2021년 세계적으로 著名한 보안 전문가 그룹에 의해 설립된 선구적인 블록체인 보안 회사입니다. 이 회사는 대중적 채택을 촉진하기 위해 신흥 Web3 세계의 보안성과 사용성을 향상시키는 데 전념하고 있습니다. 이를 위해 BlockSec은 스마트 컨트랙트 및 EVM 체인 보안 감사 서비스, 보안 개발 및 위협을 사전에 차단하기 위한 Phalcon 플랫폼, 자금 추적 및 조사를 위한 MetaSleuth 플랫폼, 그리고 크립토 세계에서 효율적으로 탐색하는 web3 빌더를 위한 MetaDock 확장 프로그램을 제공합니다.

현재까지 이 회사는 MetaMask, Uniswap Foundation, Compound, Forta, PancakeSwap 등 300개 이상의 저명한 고객사에 서비스를 제공했으며, Matrix Partners, Vitalbridge Capital, Fenbushi Capital을 포함한 저명한 투자자들로부터 두 차례의 자금 조달 라운드를 통해 수천만 달러를 유치했습니다.

공식 웹사이트: https://blocksec.com/

공식 트위터 계정: https://twitter.com/BlockSecTeam

Best Security Auditor for Web3

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

BlockSec Audit
배열 금융 보안 사고 분석