Tác giả: Cara của ZAN Team (tài khoản X @Cara6289) và XiG (tài khoản X @SHXiGi)
Vào ngày 15 tháng 5 năm 2024, Sonne Finance đã bị tấn công trên chuỗi Optimism. 20 triệu USD.
Sau cuộc tấn công, người dùng @tonyke_bot đã kiếm được khoảng 6,5 triệu USD.
(https://twitter.com/tonyke_bot/status/1790547461611860182)
Sau khi dự án Sonne Finance phát hiện ra cuộc tấn công, nó đã nhanh chóng đình chỉ tất cả các thị trường dựa trên Optimism và tuyên bố rằng Base Các thị trường trên đều an toàn.
(https://twitter.com/SonneFinance/status/1790535383005966554)
Mô tả ngắn gọn về cuộc tấn công
Sonne Finance is Optimism là một nhánh của Hợp chất V2, một giao thức cho vay phi tập trung cho phép các cá nhân, tổ chức và giao thức truy cập các dịch vụ tài chính. Giao thức Sonne Finance tổng hợp tài sản mã thông báo của người dùng để tạo thành nhóm thanh khoản cho vay, cung cấp cho người dùng hoạt động cho vay giống như ngân hàng. Giống như Hợp chất, những người tham gia giao thức có thể thế chấp mã thông báo của họ vào nhóm thanh khoản cho vay của Sonne Finance và nhận được chứng chỉ soToken (giống như cToken). SoToken là chứng chỉ tài sản sinh lãi, sẽ tạo ra một lượng thu nhập nhất định khi khối phát triển và cũng sẽ nhận được các ưu đãi về mã thông báo SONE. Người tham gia cũng có thể vay các token khác từ nhóm tài sản cho vay Sonne với soToken trong tay. Ví dụ: người tham gia có thể thế chấp một số tiền USDC nhất định để có được chứng chỉ soUSDC, sau đó cho mượn WETH để lưu hành tiếp. Cho vay thế chấp trong giao thức Sonne Finance có thể là mối quan hệ nhiều-nhiều tài sản. Trong quá trình cho vay thế chấp, giao thức sẽ tự động tính toán hệ số sức khỏe (Yếu tố sức khỏe) của địa chỉ của người tham gia. việc thế chấp địa chỉ Sản phẩm sẽ hỗ trợ thanh lý và người thanh lý cũng có thể nhận được một số phần thưởng thanh lý nhất định.
Mối quan hệ giữa số lượng token cơ bản được người dùng gửi và số soToken được đúc chủ yếu liên quan đến một biến có tên là ExchangeRate. Biến này có thể được sử dụng đại khái để cho biết mỗi soToken có giá trị bao nhiêu token cơ bản. Công thức tính cho ExchangeRate như sau:
Trong công thức trên, TotalCash đề cập đến số lượng mã thông báo cơ bản được nắm giữ bởi soToken, TotalBorrows đề cập đến số lượng mã thông báo cơ bản được cho vay trong một thị trường nhất định và TotalReserves đề cập đến tổng số dự trữ (bao gồm cả các khoản vay được trả), tổng nguồn cung đề cập đến số lượng soTokens được đúc.
Khi quy đổi, người dùng có thể chỉ định số lượng mã thông báo cơ bản cần quy đổi, RedeemTokens, để tính toán số lượng SoTokens cần hủy, RedeemTokens. Phương thức tính toán đại khái là "redeemTokens = RedemptionAmount / ExchangeRat. ", < strong>Lưu ý rằng việc mất độ chính xác không được xử lý ở đây.
Bản chất của cuộc tấn công này là khi thị trường (soToken) được tạo ra, kẻ tấn công đã thực hiện hoạt động đúc thế chấp đầu tiên và đúc một lượng nhỏ soToken cùng với một lượng nhỏ mã thông báo cơ bản, dẫn đến " Giá trị "totalSupply" quá nhỏ. Sau đó, kẻ tấn công khai thác lỗ hổng mất độ chính xác của hợp đồng Solidity, sau đó gửi mã thông báo cơ bản trực tiếp đến hợp đồng soToken (soToken sẽ không được đúc, có nghĩa là "totalSupply" không thay đổi và "totalCash" trở nên lớn hơn) thay vì phương thức đặt cược + truyền để gửi mã thông báo cơ bản. Thao tác như vậy làm cho biến "totalCash" trong hợp đồng trở nên lớn hơn, nhưng "totalSupply" vẫn không thay đổi, khiến ExchangeRate trở nên lớn hơn. Cuối cùng, khi kẻ tấn công đổi mã thông báo cơ bản, số soToken cần bị tiêu hủy sẽ ít hơn soToken được tạo ra trong quá trình thế chấp. Kẻ tấn công sử dụng soToken kiếm được để cho các soToken khác mượn mã thông báo cơ bản WETH và USDC. , soUSDC), và cuối cùng thu được Lợi nhuận lên tới 20 triệu USD.
Các địa chỉ chính liên quan đến cuộc tấn công
Giao dịch chuẩn bị tấn công:
https://optimistic. etherscan.io/tx/0x45c0ccfd3ca1b4a937feebcb0f5a166c409c9e403070808835d41da40732db96
Tấn công các giao dịch có lợi nhuận:
https://optimistic.etherscan.io/ tx /0x9312ae377d7ebdf3c7c3a86f80514878deb5df51aad38b6191d55db53e42b7f0
Địa chỉ liên quan đến tấn công EOA:
0x5d0d99e9886581ff8fcb0 1f358043 17f5ed80bbb
< blockquote>
0xae4a7cde7c99fb98b0d5fa414aa40f0300531f43
Địa chỉ liên quan đến kẻ tấn công (hợp đồng):
0xa78aefd483ce3919c0ad55c8a2e5c97cbac1caf8< /p>
0x02fa2625825917e9b1f8346a465de1bbc150c5b9
mã thông báo cơ bản (Mã thông báo VELO V2):
0x9560e827af36c94d2ac33a39bce1fe78631088db
Hợp đồng dễ bị tổn thương (soVELO, tương tự như cToken của Hợp chất):
0xe3b81318b1b6776f0877c3770afddff97b9f5 fe5< /p>
@tonyke_bot giao dịch giải cứu người dùng trên /p>
Phân tích quá trình tấn công
Tóm tắt sơ bộ< /strong>
Bên dự án Sonne Finance gần đây đã thông qua đề xuất bổ sung thị trường VELO vào Sonne Finance (https://twitter.com/SonneFinance/status/1786871066075206044) và sắp xếp năm giao dịch thông qua ví đa chữ ký để thực hiện hai ngày sau đó (https://optimistic.etherscan.io/tx/0x18ebeb958b50579ce76528ed812025949dfcff8c2673eb0c8bc78b12ba6377b7), năm giao dịch này được sử dụng để tạo ra thị trường VELO ( hợp đồng soVELO) và thiết lập một số cấu hình chính của thị trường, chẳng hạn như thiết lập mô hình lãi suất, đặt ra lời tiên đoán về giá, đặt hệ số thế chấp, v.v. Sau khi thị trường VELO được tạo, người dùng có thể gửi token VELO để đúc token soVELO, sau đó có thể sử dụng token này để vay các soToken khác.
Chuẩn bị tấn công
Giai đoạn chuẩn bị tấn công chủ yếu là để kẻ tấn công tạo thị trường VELO (hợp đồng soVELO), đặt cấu hình chính và đúc mã thông báo soVELO bằng cách thế chấp token VELO vào hợp đồng soVELO, đồng thời, họ cũng gửi trực tiếp token VELO của mình đến hợp đồng soVELO để tăng ExchangeRate, chuẩn bị cho các cuộc tấn công kiếm lợi nhuận tiếp theo.
Các bước cụ thể như sau:
Sau khi thời gian khóa hai ngày kết thúc, kẻ tấn công sẽ đầu tiên Hoạt động của bốn giao dịch được đóng gói thành một giao dịch (giao dịch 0x45c0cc), được sử dụng để tạo thị trường VELO (hợp đồng soVELO) và đặt cấu hình chính. Khi thị trường VELO được khởi tạo, ExchangeRate được đặt thành "200.000.000.000.000.000.000.000.000".
Kẻ tấn công gọi chức năng "đúc" của hợp đồng soVELO để gửi mã thông báo VELO và đúc mã thông báo soVELO. Kẻ tấn công chỉ định "mintAmount" là "400.000.001" (số mã thông báo VELO của đồng xu). Như có thể thấy từ hàm "exchangeRateStoredInternal", vì "_totalSuppl" của mã thông báo soVELO là 0 tại thời điểm này, ExchangeRate là giá trị được đặt ở bước 1. Theo công thức "mintTokens = RealMintAmount / ExchangeRate", số lượng token soVELO được tính toán sẽ được đúc vào thời điểm này là 2. Tóm lại, ở bước này, kẻ tấn công gửi mã thông báo VELO có giá trị "400.000.001" vào hợp đồng soVELO và kẻ tấn công nhận được mã thông báo soVELO có giá trị là 2.
soVELO.mint:
Kẻ tấn công đã gửi mã thông báo VELO với giá trị "2.552.964.259.704.265.837.526" đến hợp đồng soVELO bằng cách gửi trực tiếp mã thông báo VELO. Tại thời điểm này, mã thông báo VELO do bên nắm giữ Hợp đồng soVELO tăng, nhưng do không có token soVELO mới nào được tạo ra nên tổng nguồn cung vẫn không thay đổi, điều đó có nghĩa là ExchangeRate được tính theo công thức tính ExchangeRate sẽ trở nên lớn hơn vào thời điểm này.
Kẻ tấn công đã chuyển mã thông báo soVELO được giữ nhiều lần, cuối cùng sang một cuộc tấn công khác EOA 0xae4a.
Khả năng sinh lợi khi tấn công
Giai đoạn tấn công lợi nhuận chủ yếu là khi kẻ tấn công thực hiện giao dịch thứ năm của đề xuất và chuyển Flash các khoản vay cho hợp đồng soVELO vay token VELO trực tiếp để tăng thêm ExchangeRate. Sau đó, kẻ tấn công đã sử dụng mã thông báo soVELO có giá trị 2 trong tay để mượn các mã thông báo cơ bản như WETH và USDC từ các hợp đồng soToken khác (chẳng hạn như soWETH, soUSDC, v.v.) và những phần này trở thành lợi nhuận của kẻ tấn công. Sau đó, kẻ tấn công đã đổi mã thông báo cơ bản của mình trong hợp đồng soVELO. Do tỷ lệ trao đổi tăng lên và mất độ chính xác trong việc tính toán mã thông báo soVELO cần bị hủy để đổi, kẻ tấn công cuối cùng chỉ sử dụng mã thông báo soVELO có giá trị là. 1. Hầu như tất cả các token VELO đã gửi trước đó đã được đổi, có thể hiểu là kẻ tấn công sử dụng các token soVELO bổ sung có giá trị là 1 để kiếm các token cơ bản như WETH và USDC bằng cách vay từ các soToken khác. Kẻ tấn công đã sử dụng kỹ thuật tương tự để lặp lại cuộc tấn công nhiều lần và cuối cùng thu được lợi nhuận khổng lồ.
Các bước cụ thể như sau:
Kẻ tấn công thực hiện đòn thứ năm trong câu hỏi Giao dịch, đặt hệ số vay được chỉ định trong đề xuất.
Kẻ tấn công đã cho mượn nhanh mã thông báo VELO với giá trị "35.469.150.965.253.049.864.450.449" từ nhóm VolatileV2 AMM - USDC/VELO, điều này đã kích hoạt chức năng hook của kẻ tấn công. Trong chức năng hook, kẻ tấn công tiếp tục thực hiện thao tác tấn công.
Kẻ tấn công gửi mã thông báo VELO mà hắn nắm giữ tới hợp đồng soVELO để tăng thêm ExchangeRate. Hiện tại, có tổng số token VELO có giá trị là "35.471.703.929.512.754.530.287.976" trong hợp đồng soVELO (tổng số token VELO được kẻ tấn công chuyển ba lần).
Kẻ tấn công tạo một hợp đồng mới 0xa16388a6210545b27f669d5189648c1722300b8b Trong hàm tạo, hắn chuyển 2 mã thông báo soVELO mà hắn nắm giữ vào hợp đồng mới được tạo. (sau đây gọi là kẻ tấn công 0xa163).
Kẻ tấn công 0xa163 đã sử dụng token soVELO mà hắn nắm giữ để vay WETH với giá trị "265.842.857.910.985.546.929" từ soWETH.
Kẻ tấn công 0xa163 gọi hàm "redeemUnderlying" của soVELO, chỉ định giá trị của token VELO đã đổi là "35,471,603,929,512,754,530,287,976" (hầu hết tất cả những kẻ tấn công trước đó đã chuyển nhượng hoặc thế chấp vào soVELO Số lượng Token VELO trong hợp đồng). Tại thời điểm này, số lượng token soVELO cần bị hủy để quy đổi cần được tính theo công thức "redeemTokens = RedeeAmountIn / ExchangeRate".
Như có thể thấy từ hàm "exchangeRateStoredInternal", vì _totalSupply là 2 thay vì 0 tại thời điểm này, nên giá trị của ExchangeRate cần được tính, được tính thông qua công thức "exchangeRate = (totalCash + TotalBorrows - TotalReserves) / TotalSupply" Sàn giao dịch hiện tại trên là "17,735,851,964,756,377,265,143,988,000,000,000,000,000,000,000,000,000,000,000,000,000".
Giá trị của " RedemptionTokens " được tính toán dựa trên ExchangeRate mới là " 1,99 " Do đặc tính làm tròn xuống của Solidity, giá trị của " RedemptionTokens " cuối cùng là 1. Điều này có nghĩa là kẻ tấn công 0xa163 đã sử dụng mã thông báo soVELO có giá trị 1 để đổi gần như tất cả mã thông báo VELO đã gửi trước đó. Đồng thời, kẻ tấn công 0xa163 cũng kiếm được WETH với giá trị “265.842.857.910.985.546.929” mượn từ soWETH.
soVELO.redeemCơ bản:
soVELO.exchangeRateStoredInternal:
Kẻ tấn công 0xa163 đã chuyển tất cả WETH đã mượn và đổi mã thông báo VELO cho kẻ tấn công cấp cao hơn, sau đó tự hủy .
Kẻ tấn công gọi hàm "liquidateBorrow" của soWETH để thanh lý một phần tài sản vay từ hợp đồng mới tạo 0xa163 nhằm lấy lại soVELO bị khóa có giá trị 1 Token. Hiện tại kẻ tấn công chỉ nắm giữ mã thông báo soVELO có giá trị là 1.
Kẻ tấn công gọi lại chức năng "đúc" của soVELO, thế chấp và tạo ra các token soVELO, với mục đích thu thập các token soVELO có giá trị là 2, sau đó thực hiện lại bước 3 ở trên -8 bước để kiếm lợi nhuận từ các token không bị che giấu khác.
Kẻ tấn công thực hiện bước 9 nhiều lần, hoàn trả khoản vay nhanh và thu về lợi nhuận.
Cách tận dụng 6,5 triệu đô la với 100 đô la
Sau cuộc tấn công, người dùng @tonyke_bot trên X đã vượt qua giao dịch 0x0a284cd 1144 Token VELO đã được thế chấp vào hợp đồng soVELO và 0,00000011 soVELO đã được đúc. Lý do tại sao hoạt động này có thể ngăn kẻ tấn công khỏi các cuộc tấn công tiếp theo là vì giao dịch này thay đổi kích thước của TotalSupply trong soVELO và số lượng token VELO TotalCash được giữ và tác động của sự tăng trưởng của TotalSupply đối với việc tính toán ExchangeRate lớn hơn tác động của sự tăng trưởng của TotalCash Do đó, ExchangeRate trở nên nhỏ hơn, do đó khi kẻ tấn công tấn công, anh ta không còn có thể tận dụng sự mất đi độ chính xác để kiếm soVELO, khiến cuộc tấn công không thể thực hiện được nữa.
Theo dõi quỹ
Kẻ tấn công đã chuyển tiền ngay sau khi lấy được số tiền bất hợp pháp. Hầu hết số tiền đã được chuyển đến 4 địa chỉ sau. Một số đã thay đổi địa chỉ để tiếp tục cuộc tấn công. và một số dùng để rửa tiền:
0x4ab93fc50b82d4dc457db85888dfdae28d29b98d
< /li> ol>Kẻ tấn công đã chuyển 198 WETH đến địa chỉ này và sau đó địa chỉ này sử dụng phương thức tấn công tương tự để thu được lợi nhuận bất hợp pháp trong các giao dịch sau:
0x5d0d99e9886581ff8fcb01f35804317f5ed80bbb.
0x5d0d99e9886581ff8fcb01f35804317f5ed80bbb
< p>Kẻ tấn công đã chuyển 724277 USDC và 2353 VELO đến địa chỉ này và đổi USDC lấy Ether. Sau đó, một số tiền ngay lập tức được chuyển đến cầu nối chuỗi Stargate và hầu hết số tiền bất hợp pháp vẫn ở địa chỉ này:
0xbd18100a168321701955e348f03d 0d f4f517c13b  ; em>
Kẻ tấn công đã chuyển 33 WETH đến địa chỉ này và sử dụng phương pháp peel chain để cố gắng rửa tiền. sau:
0xbd18100a168321701955e348f03d0df4f517c13b -> ; 0xc521bde5e53f537ff208970152b75a003093c2b4 -> ; 0x9f09ec563222fe52712dc413d0b7b66cb5c7c795.
0x4fac0651bcc837bf889f6a7d79c1908419fe1770
< p>Kẻ tấn công đã chuyển 563 WETH đến địa chỉ này, sau đó chuyển nó sang 0x1915F77A116dcE7E9b8F4C4E43CDF81e2aCf9C68. Phương thức rửa tiền của kẻ tấn công lần này tương đối chuyên nghiệp và các phương thức này có xu hướng đa dạng. Do đó, đối với những người tham gia Web3 như chúng tôi, chúng tôi phải tiếp tục cải thiện khả năng chống rửa tiền về mặt bảo mật và cải thiện tính bảo mật của các dự án Defi thông qua KYT, AML và các sản phẩm bảo mật giao dịch blockchain liên quan khác.
Khuyến nghị về an toàn
Việc mất độ chính xác cần được xem xét nghiêm túc
mạnh>. Các vấn đề bảo mật do mất độ chính xác xuất hiện không ngừng, đặc biệt là trong các dự án Defi, nơi việc mất độ chính xác thường dẫn đến tổn thất tài chính nghiêm trọng. Các bên tham gia dự án và kiểm toán viên bảo mật nên xem xét cẩn thận mã bị mất độ chính xác trong dự án và tiến hành kiểm tra để tránh lỗ hổng này càng nhiều càng tốt.
Chúng tôi khuyến nghị rằng việc tạo thị trường tương tự như cToken trong Complex và hoạt động chuyển thế chấp đầu tiên phải được thực hiện bởi những người dùng có đặc quyền để tránh bị những kẻ tấn công điều hành và từ đó thao túng sàn giao dịch tỷ lệ.
Khi có một biến khóa trong hợp đồng phụ thuộc vào giá trị của " this.balance " hoặc " token.balanceOf() ", bạn cần xem xét cẩn thận các điều kiện đối với việc thay đổi biến chính, chẳng hạn như Có được phép thay đổi trực tiếp giá trị của biến này bằng cách chuyển tiền bản địa hoặc mã thông báo sang hợp đồng hay chỉ có thể thay đổi giá trị của biến này bằng cách gọi một hàm cụ thể.