2024년 5월 15일, 손네 파이낸스는 옵티미즘 체인에 대한 공격을 받아 최대 2천만 달러의 손실을 입었습니다.
공격이 발생한 후, X의 @tonyke_bot 사용자는 트위터를 통해 Sonne Finance의 토큰 담보 풀(시장이라고도 하며 컴파운드의 cToken과 유사)에 남아 있는 약 650만 달러를 약 100달러로 보호했다고 밝혔습니다.
(https://twitter.com/tonyke_bot/status/1790547461611860182)
이 공격을 발견한 후 Sonne Finance의 프로젝트 측은 모든 낙관론을 신속하게 중지하고 마켓을 모두 중단하고 베이스의 마켓은 안전하다고 발표했습니다.
(https://twitter.com/SonneFinance/status/1790535383005966554)
p style="text-align:가운데;">
한마디로 공격
Sonne Finance는 Optimism의 포크업 버전입니다. 개인, 기관, 프로토콜이 금융 서비스를 이용할 수 있도록 Compound V2를 포크한 옵티미즘의 탈중앙화 대출 프로토콜로, 사용자 토큰 자산을 모아 대출 유동성 풀을 형성하여 사용자에게 은행과 같은 대출 비즈니스를 제공하는 Sonne Finance 프로토콜입니다. 컴파운드와 마찬가지로, 프로토콜 참여자는 자신의 토큰 보유를 손네 파이낸스의 대출 유동성 풀에 담보로 제공하고 소토큰(c토큰과 같은)을 받을 수 있습니다. 소토큰은 블록이 진행됨에 따라 일정량의 수익을 창출하는 이자부 자산 토큰이며, SONNE 토큰으로 인센티브를 받기도 합니다. 또한 참여자는 자신의 soToken으로 손네 대출 풀에서 다른 토큰을 빌려줄 수도 있습니다. 예를 들어, 참여자는 일정량의 USDC를 담보로 soUSDC 토큰을 얻은 다음 추가 유통에 사용할 WETH를 빌려줄 수 있습니다. 손네 금융 프로토콜에서 대출과 차용은 다대다 자산 관계가 될 수 있으며 참여자 주소의 건전성이 자동으로 계산됩니다. 프로토콜은 참여자 주소의 건강 지수를 자동으로 계산하고, 건강 지수가 1 이하로 떨어지면 해당 주소의 담보가 청산 지원되며 청산자는 일정 금액의 청산 보상을 받습니다.
사용자가 예치한 기초 토큰 수와 발행된 토큰 수 사이의 관계는 주로 교환률이라는 변수와 관련이 있으며, 교환률은 대략적으로 각 토큰의 가치를 나타내는 데 사용할 수 있습니다. 교환률은 다음 공식을 사용하여 계산됩니다:
위 공식에서 totalCash는 soToken이 보유한 기초 토큰의 수, totalBorrows는 특정 시장에서 대출된 기초 토큰의 수, totalReserve는 총 준비금(대출자가 지불한 이자 포함)의 수입니다. 차입자가 지불한 이자 포함), 총공급량은 발행된 토큰의 수입니다.
상환할 때 사용자는 상환하려는 기본 토큰의 수, redeemAmount를 지정하여 소각해야 하는 soToken의 수, redeemTokens를 계산할 수 있으며, 이는 대략 "redeemTokens = redeemAmount / exchangeRat"입니다. exchangeRat", 여기서는 정밀도 손실이 없다는 점에 유의하세요.
이 공격의 핵심은 시장(soToken)이 생성될 때 공격자가 첫 번째 담보 캐스팅 작업을 수행하여 소량의 기초 토큰으로 소수의 soToken을 캐스팅하여 soToken의 "총공급" 값이 너무 작아진다는 것입니다. 그런 다음 공격자는 담보 + 캐스팅을 통해 기초 토큰을 예치하는 대신 기초 토큰을 직접 soToken 콘트랙트로 전송함으로써(soToken을 캐스팅하지 않고, 즉 totalSupply는 변하지 않고 totalCash는 커짐) 솔리디티 콘트랙트의 정밀도가 떨어지는 점을 악용합니다. 이렇게 하면 컨트랙트의 "totalCash" 변수는 더 커지지만 "totalSupply"는 동일하게 유지되므로 교환 비율이 더 커집니다. 결국 공격자가 기초 토큰을 상환할 때 소멸해야 하는 토큰은 담보화 과정에서 캐스팅된 토큰보다 적으며, 공격자는 획득한 토큰을 사용하여 다른 토큰(예: soWETH, soUSDC)에서 기초 토큰인 WETH, USDC를 빌려 궁극적으로 최대 2천만 달러의 이익을 얻게 됩니다. 2,000만 달러.
공격에 연루된 주요 주소
공격 준비 거래:
https://optimistic.etherscan.io/tx/ 0x45c0ccfd3ca1b4a937feebcb0f5a166c409c9e403070808835d41da40732db96
수익 탈취 거래 공격:
https:// optimistic.etherscan.io/tx/0x9312ae377d7ebdf3c7c3a86f80514878deb5df51aad38b6191d55db53e42b7f0
EOA 공격 관련:
0x5d0d99e9886581ff8fcb01f35804317f5ed80bbb
0xae4a7cde7c99fb98b0d5fa414aa40f0300531f43
공격자(계약)와 연관된 주소:
0xa78aefd483ce3919c0ad55c8a2e5c97cbac1caf8
0x02fa2625825917e9b1f8346a465de1bbc150c5b9
기초 토큰(VELO 토큰 V2):
0x9560e827af36c94d2ac33a39bce1fe78631088db
블록쿼트>취약 컨트랙트(soVELO, 컴파운드의 c토큰과 유사):
0xe3b81318b1b6776f0877c3770afddff97b9f5fe5
/>/ blockquote>X on @tonyke_bot 사용자 구조 거래:
https://optimistic.etherscan.io/tx/ 0x816f9e289d8b9dee9a94086c200c0470c6456603c967f82ab559a5931fd181c2
Attack Flow Analysis
< strong>이전
소네 파이낸스 프로젝트 측은 최근 소네 파이낸스에 VELO 마켓을 추가하는 제안을 채택했습니다(https://twitter.com/SonneFinance/status/ 1786871066075206044), 다중 서명 지갑을 통해 이틀 후 5건의 거래가 실행되도록 준비했습니다(https://optimistic.etherscan.io/tx/ 0x18ebeb958b50579ce76528ed812025949dfcff8c2673eb0c8bc78b12ba6377b7)를 통해 VELO 시장(soVELO 계약)을 생성하고 이자율 모델 설정 등 해당 시장에 대한 몇 가지 주요 구성을 설정하는 데 사용되었습니다. VELO 마켓이 생성된 후 사용자는 VELO 토큰을 예치하여 soVELO 토큰을 발행할 수 있으며, 이를 통해 다른 soToken을 빌릴 수 있습니다.
공격 준비
공격 준비 단계는 다음 사항에 중점을 둡니다. 공격자는 제안서의 2일간의 락업 기간이 지나면 손네 파이낸스의 제안서 정보를 기반으로 VELO 마켓(soVELO 계약)을 생성하고 키 구성을 설정한 후, VELO 토큰을 soVELO 계약에 약정하여 soVELO 토큰을 채굴함과 동시에 공격자가 보유하고 있는 VELO 토큰을 직접 soVELO 계약에 전송합니다. 후속 공격에 대비하여 교환 비율을 높이기 위해 계약을 체결합니다.
구체적인 단계는 다음과 같습니다:
2일간의 락아웃이 끝나면 공격자는 먼저 제안서에 예정된 처음 4개의 거래를 단일 거래(거래 0x45c0cc)로 패키징하여 VELO 시장(soVELO 계약)을 생성하고 키 구성을 설정합니다. VELO 시장은 "200,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000,000"으로 설정된 교환환율로 초기화됩니다.
공격자는 soVELO 컨트랙트의 "mint" 함수를 호출하여 VELO 토큰을 입금하고 soVELO 토큰을 발행하며, "mintAmount"를 "400,000,001"(VELO 토큰 수)로 지정합니다. "exchangeRateStoredInternal" 함수를 보면, 현재 soVELO 토큰의 "_totalSuppl"이 0이므로 교환 비율은 1단계에서 설정한 값임을 알 수 있습니다. "mintTokens = actualMintAmount / exchangeRate" 공식에 따라 이 시점에서 발행해야 하는 soVELO 토큰의 수는 2로 계산됩니다. 즉, 이 단계에서 공격자는 "400,000,001"의 값을 가진 VELO 토큰을 soVELO 계약에 입금하고 공격자는 2 개의 soVELO 토큰을 얻게 됩니다. soVELO 토큰.
soVELO.mint:
공격자는 '2,552,964,259,704,265,837,526' 값으로 직접 VELO 컨트랙트의 형태로 VELO 토큰을 전송했습니다. soVELO 컨트랙트는 더 많은 VELO 토큰을 보유하고 있지만, 새로 발행된 토큰이 없으므로 총공급량은 변하지 않으므로 교환비율 공식에 따라 계산된 교환비율은 더 커지게 됩니다.
공격자는 보유한 soVELO 토큰을 여러 번 전송하여 결국 다른 공격 EOA 0xae4a로 전송합니다.
공격 수익성
공격 수익성 단계는 공격자가 제안의 다섯 번째 거래를 실행하고 공격자에게 VELO를 빌려주면서 지배적으로 이루어집니다. 공격자는 교환 비율을 더 높이기 위해 soVELO 계약에 VELO 토큰을 빌려주고, 공격자가 보유한 가치가 2인 soVELO 토큰을 사용하여 WETH, USDC 및 기타 기초 토큰을 다른 soToken(예: soWETH, soUSDC 등) 계약에 빌려주고, 이 부분이 공격자의 기초 토큰이 됩니다. 이러한 부분은 공격자에게 수익이 됩니다. 이후 공격자는 자신의 기초 토큰을 상환하기 위해 soVELO 컨트랙트로 이동하는데, 교환 비율이 커지고 상환을 위해 소멸해야 하는 soVELO 토큰 계산의 정확성이 떨어지면서 공격자는 결국 자신이 예치한 거의 모든 VELO 토큰을 상환하고 1의 가치를 가진 soVELO 토큰만 사용하게 되는데, 이는 공격자가 초과된 soToken을 사용하여 자신이 예치한 모든 VELO 토큰을 상환한 것으로 해석할 수 있습니다. 공격자는 가치가 1인 여분의 소토큰을 다른 소토큰에서 차용하여 WETH, USDC 등의 기초 토큰을 획득하는 데 사용한 것으로 이해할 수 있으며, 공격자는 동일한 수법으로 공격을 여러 번 반복하여 결국 막대한 수익을 올렸습니다.
단계는 다음과 같습니다:
공격자는 제안서에 명시된 대출 비율을 설정하여 제목 케이스의 다섯 번째 트랜잭션을 실행합니다.
공격자는 "35,469,150,965,253,049,864,450,449" 값으로 VolatileV2 AMM - USDC/VELO 풀에서 VELO 토큰을 플래시 대출하며, 이는 공격자의 후크 함수를 트리거합니다. 후크 함수에서 공격자는 공격을 계속 수행합니다.
공격자는 교환 비율을 더 높이기 위해 자신의 VELO 토큰을 soVELO 컨트랙트에 전송합니다. 현재 soVELO는 "35,471,703,929,512,754,530,287,976"(공격자가 세 번 전송한 VELO 토큰의 합)의 값을 가진 VELO 토큰을 컨트랙트에 보유하고 있습니다. VELO 토큰(공격자가 세 번 전송한 VELO 토큰의 총합).
공격자는 새로운 컨트랙트 0xa16388a6210545b27f669d5189648c1722300b8b를 생성하고 생성자에서 보유한 2개의 soVELO 토큰을 새로 만든 컨트랙트 0xa163으로 전송합니다(이하 공격자 0xa163)로 전송합니다.
공격자 0xa163은 보유하고 있는 soVELO 토큰으로 soWETH에서 "265,842,857,910,985,546,929" 값의 WETH를 차용합니다.
공격자 0xa163은 soVELO의 " redeemUnderlying" 함수를 호출하여 상환된 VELO 토큰의 가치를 "35,471,603,929,512,754,530,287,976"(공격자가 이전에 soVELO 계약에 양도하거나 담보한 VELO 토큰의 양)으로 지정하며, 이는 "redeemTokens = redeemAmountIn / exchangeRate" 공식에 따라 상환을 위해 소멸해야 하는 soVELO 토큰의 수를 계산합니다.
"exchangeRateStoredInternal" 함수에서 _totalSupply가 0이 아니라 2이므로 "exchangeRate = (totalCash + totalBorrows - totalReserves) / totalSupply" 공식을 사용하여 exchangeRate의 값을 계산해야 한다는 것을 알 수 있습니다. 총예치금) / 총공급"을 사용하면 현재 교환률은 "17,735,851,964,756,377,265,143,988,000,000,000,000"으로 초기 교환률인 "200,000,000,000,000"보다 훨씬 큰 값입니다. exchangeRate "200,000,000,000,000,000,000,000,000,00".
새 교환율을 기준으로 계산된 "redeemTokens"의 값은 "1.99"이며, 솔리디티의 하향 반올림 특성으로 인해 "redeemTokens"의 값은 1이 되므로 공격자 0xa163이 이전에 입금했던 거의 모든 soVELO 토큰을 1의 값을 가진 soVELO 토큰을 사용하여 상환했음을 의미합니다. 즉, 공격자 0xa163은 자신이 예치한 거의 모든 VELO 토큰을 1의 값으로 상환했습니다. 동시에 공격자 0xa163은 "265,842,857,910,985,546,929" 값으로 soWETH에서 빌린 WETH도 획득했습니다.
soVELO.redeemUnderlying:
&™
soVELO. exchangeRateStoredInternal:
공격자 0xa163은 빌린 WETH와 상환된 VELO 토큰을 모두 상위 계층의 공격자에게 전송한 후 자폭했습니다.
공격자는 새로 생성된 0xa163 컨트랙트에서 차용한 자산의 일부를 청산하기 위해 soWETH의 "liquidateBorrow" 함수를 호출하여 잠겨 있는 값이 1인 soVELO 토큰을 회수합니다. 현재 공격자는 단 1개의 soVELO 토큰만 보유하고 있습니다.
공격자는 soVELO의 "mint" 기능을 호출하여 2 개의 soVELO 토큰을 얻는 것을 목표로 다시 soVELO 토큰을 채굴한 다음 위의 3-8 단계를 수행하여 나머지 미지급 토큰을 얻습니다.
공격자는 9 단계의 단계를 수행하여 soVELO 토큰을 반환합니다. 9단계의 단계를 수행하여 언더라이딩 토큰을 상환하고 이익을 남기고 시장을 떠납니다.
$100로 650만 달러를 활용하는 방법
공격 후 X의 @tonyke_bot 사용자는 0x0a284cd 트랜잭션에서 1,144개의 VELO 토큰을 soVELO 컨트랙트에 약정함으로써 0.00000011 VELO 토큰을 발행했습니다. 이 트랜잭션은 총공급량과 soVELO에 보유된 VELO 토큰 수, 총현금, 총공급량 증가가 총현금 증가보다 교환 비율 계산에 더 큰 영향을 미치기 때문에 추가 공격을 방지할 수 있습니다. 총 공급량의 증가가 총 현금의 증가보다 교환 비율 계산에 더 큰 영향을 미치므로 교환 비율이 작아지고 공격자는 공격을 수행할 때 더 이상 정밀도 손실을 사용하여 soVELO를 얻을 수 없으므로 공격을 수행 할 수 없게됩니다.
자금 추적
공격자들은 불법 수익금을 확보한 직후 자금을 이체했으며, 대부분은 다른 주소에서 공격을 계속하거나 자금 세탁을 위해 다음 네 주소로 이동했습니다.
0x4ab93fc50b82d4dc457db85888dfdae28d29b98d
공격자들은 이 주소로 198 WETH를 전송한 후 동일한 공격 기법을 사용하여 다음 거래에서 불법적인 이득을 얻었습니다:
공격이 끝난 후, 이 주소는 위의 불법 이득을 0x5d0d99e9886581ff8fcb01f35804317f5ed80bbb로 전송했습니다. .
0x5d0d99e9886581ff8fcb01f35804317f5ed80bbb
공격자들이 송금한 금액은 724277 USDC, 2353 VELO를 이 주소로 이체하고 USDC를 이더로 전환했습니다. 그 직후 일부 자금이 스타게이트 크로스체인 브리지로 이체되어 대부분의 불법 자금이 이 주소에 남아있게 되었습니다:
<>< strong>0xbd18100a168321701955e348f03d0df4f517c13b
공격자는 해당 주소로 33 WETH를 송금하고 필 체인을 사용하여 자금 세탁을 시도했습니다. The link is as follows:
0xbd18100a168321701955e348f03d0df4f517c13b -> 0x7e97b74252b6df53caf386fb4c54d4fb59cb6928 -> 0xc521bde5e53f537ff208970152b75a003093c2b4 -> 0x9f09ec563222fe52712dc413d0b7b66cb5c7c795.
0x4fac0651bcc837bf889f6a7d79c1908419fe1770
공격자는 이 주소로 563 WETH를 이 주소로 전송한 후 0x1915F77A116dcE7E9b8F4C4E43CDF81e2aCf9C68로 전송했으며 현재 추가 동작은 없습니다.
이번 공격자의 자금 세탁 수법은 상대적으로 더 전문적이며, 수법이 다양해지는 추세를 보이고 있습니다. 따라서 우리 Web3 참여자들은 보안 측면에서 자금세탁 방지 능력을 지속적으로 향상시켜야 하며, KYT, AML 및 기타 관련 블록체인 거래 보안 제품을 통해 Defi 프로젝트의 보안을 강화해야 합니다.
보안 권장 사항
정확성 손실에 주의가 필요합니다. 정확도 손실은 무수히 많은 보안 문제를 야기하며, 특히 정확도 손실이 심각한 재정적 손실로 이어지는 Defi 프로젝트에서는 더욱 그렇습니다. 프로젝트 소유자와 보안 감사자는 정확도 손실이 존재하는 프로젝트의 코드를 주의 깊게 검토하고 테스트를 잘 수행하여 취약점을 우회할 수 있도록 노력하는 것이 좋습니다.
공격자에 의해 운영되어 환율이 조작되는 것을 방지하기 위해 컴파운드에서 cToken과 유사한 마켓의 생성 및 최초 담보 캐스팅 작업은 권한 있는 사용자가 수행할 것을 권장합니다.
컨트랙트에 "this.balance" 또는 "token.balanceOf()" 값에 의존하는 키 변수가 있는 경우, 해당 키 변수를 변경할 수 있는 조건, 예를 들어 네이티브 코인이나 토큰을 컨트랙트로 전송하여 변경할 수 있는지 또는 특정 함수를 호출해야만 변경할 수 있는지 등을 신중하게 고려해야 합니다. 또는 특정 함수를 호출해야만 변수를 변경할 수 있는지 여부입니다.