Velocore의 사고 분석

이 기사는 기계로 번역되었습니다
원문 표시

2024년 6월 2일, Velocore는 CPMM 풀에 대한 공격을 받아 약 680만 달러의 재정적 손실을 입었습니다. 이 공격의 근본 원인은 ConstantProductPool 에서 거래 수수료를 계산하는 데 잘못된 논리와 정수 언더플로가 결합된 것입니다.

개요

익스플로잇 분석

기술 문서에서 Velocore는 사용자가 Vault 계약 과 직접 상호 작용하여 작업을 수행할 것을 권장합니다. 사용자 관점에서 가장 중요한 기능은 Vault.execute() 입니다. 이 기능을 사용하면 사용자가 내부 풀, 라우터 이더리움 클래식(ETC) 의 주소를 알 필요 없이 스왑, 예치(stake) , 변환 또는 투표할 수 있습니다. 또한 일괄 작업을 지원하여 사용자가 단일 트랜잭션에서 여러 작업을 수행할 수 있습니다.

Verichains를 읽어주셔서 감사합니다! 무료로 구독하여 새로운 게시물을 받고 제 작업을 지원하세요.

토큰 스왑 작업의 일반적인 실행 흐름은 다음과 같습니다.

  1. 사용자는 tokenRef 배열과 작업 목록( ops )을 사용하여 SwapFacet.execute() 호출합니다.

  2. 그러면 SwapFacet 내부 _execute() 함수를 호출하여 사용자의 작업을 처리합니다.

    1. _execute() ops 반복하고 각 작업을 유형에 따라 처리합니다.

    2. 현재 작업이 스왑 요청인 경우 _execute() 해당 풀의 velocore__execute() 호출하여 스왑을 시뮬레이션하고 잔액 델타를 반환합니다. 그런 다음 _verifyAndApplyDelta() 호출하여 결과를 검증하고 적용합니다.

  3. 외부 execute() 함수로 돌아온 후 사용자의 잔액을 확인하고 사용자 지갑으로의 이체나 사용자 지갑에서의 출금을 처리합니다.

Velocore에는 두 가지 유형의 풀이 있습니다. 휘발성 풀(CPMM)과 안정적 풀(Wombat 풀). 공격받은 풀은 휘발성 풀이므로 ConstantProductPool.sol 에서 구현을 검토합니다.

ConstantProductPoolvelocore__execute() 함수는 스왑 결과를 계산하는 역할을 하며 사용자가 Velocore에서 스왑을 시작할 때마다 SwapFacet 계약에 의해 호출됩니다. 그러나 이 함수에는 몇 가지 결함이 있습니다.

  1. 호출자 검증 누락 : velocore__execute() Vault 계약(이 경우 SwapFacet )에서만 호출되어야 하지만 이 검증이 누락되었습니다. 이를 통해 누구나 함수를 호출할 수 있어 잠재적인 공격 벡터가 도입됩니다.

  2. feeMultiplier 에 상한 없음 : feeMultiplier 에 대한 상한 검사가 없습니다. 논리에 따르면 feeMultiplier는 velocore__execute() 호출될 때마다 증가하고 블록 타임스탬프가 변경될 때(세 번째 코드 블록)에만 1e9 로 재설정됩니다. feeMultiplier는 거래 수수료(첫 번째 코드 블록 의 effectiveFee1e9 )를 계산하는 데 사용되므로 feeMultiplier가 3.33e11을 초과하면 effectiveFee1e9는 최소한 3.33e11 * 3e6 / 1e9 = 1e9 되며 이는 수수료가 100%를 초과한다는 것을 의미합니다. 이는 unaccountedFeeAsGrowth1e18 에 상당한 영향을 미쳐 requestedGrowth1e18 이 변경되고 궁극적으로 풀의 잔액에 영향을 미칩니다.

  3. 확인되지 않은 산술 : unaccountedFeeAsGrowth1e18 의 계산은 확인되지 않은 블록 (두 번째 코드 블록) 내부에 배치됩니다. 두 번째 결함과 결합하면 1e18 - ((1e18 - k) * effectiveFee1e9) / 1e9 표현식이 언더플로되어 예상치 못한 동작이 발생할 수 있습니다.

주어진 모든 정보를 바탕으로 이제 우리는 해커의 전략을 이해할 수 있습니다.

  1. feeMultiplier 조작 : 해커는 velocore__execute() 여러 번 직접 호출하여 feeMultiplier를 인위적으로 높여 effectiveFee1e9가 100%를 초과하게 했습니다. 이는 다음 단계에서 정수 오버플로 공격을 실행하는 데 필요합니다. 실제 공격에서 velocore__execute() 동일한 인수로 세 번 호출되었습니다. 테스트를 통해 약간 다른 매개변수로 velocore__execute() 한 번만 호출하여 동일한 효과를 얻었습니다. velocore__execute() 전송을 수행하지 않으므로 이것이 풀 잔액에 즉시 영향을 미치지 않는다는 점에 유의하는 것이 중요합니다. feeMultiplier 만 업데이트합니다.

  2. USDC 유동성 고갈 : 플래시론 기능을 활용하여 해커는 유동성 공급 토큰(LP) 사용하여 풀에서 거의 모든 USDC를 인출하여 USDC의 부족을 만들고 스왑 가격에 상당한 영향을 미치려고 시도했습니다. 실제 공격에서 해커는 풀의 USDC의 98%를 고갈시키기 위해 세 번의 작업을 실행했습니다. 테스트하는 동안 결과에 차이가 없이 단일 작업으로 동일한 결과를 얻을 수 있음을 발견했습니다.

  3. 정수 언더플로우 악용 : 마지막으로 해커는 또 다른 단일 토큰 인출을 수행하여 정수 언더플로우를 트리거하는 정확한 양의 USDC를 선택하여 rpow() 비정상적으로 큰 값을 반환하게 했습니다. 이로 인해 풀이 잘못 계산하여 적절한 인출을 실행하는 대신 해커에게 유동성 공급 토큰(LP) 수여했습니다. 이를 통해 해커는 이전 단계에서 빌린 금액을 상환할 수 있는 충분한 유동성 공급 토큰(LP) 가질 수 있습니다.

결론

Velocore는 여러 감사를 통과했지만 여전히 대규모 공격을 생성하기 위해 결합되어 악용될 수 있는 여러 가지 문제가 있습니다. 이러한 취약성의 근본 원인은 부적절한 시스템 설계에서 비롯된 것으로 보입니다. SwapFacet 계약은 ConstantProductPool 의 논리에 의존하여 풀의 잔액을 업데이트하고 토큰을 전송합니다. 그러나 ConstantProductPool 자체 내부 변수( SwapFacet 과 무관)를 사용하여 델타를 계산하고 결과만 반환합니다. 이러한 설계는 계약 간에 단절을 만들어 오해의 소지가 있고 궁극적으로 악용으로 이어집니다. 향후 위험을 완화하기 위해 Velocore가 코드베이스를 리팩터링하여 내부 구성 요소 간에 명확하고 강력한 논리를 확립하는 것이 좋습니다.

출처
면책조항: 상기 내용은 작자의 개인적인 의견입니다. 따라서 이는 Followin의 입장과 무관하며 Followin과 관련된 어떠한 투자 제안도 구성하지 않습니다.
라이크
즐겨찾기에 추가
코멘트