Phân tích tấn công chi tiêu gấp đôi "Máy in tiền ảo" Popsicle Finance
BlockSec
2021-08-04 13:10
本文约3499字,阅读全文需要约14分钟
​Vào lúc 6 giờ sáng ngày 4 tháng 8 năm 2021, giờ Bắc Kinh (khối 12955063), nhiều nhóm thông minh thuộc dự án Popsicle Finance đã bị tấn công, gây thiệt hại hơn 20 triệu đô la Mỹ, đây là khoản thiệt hại

Vào lúc 6 giờ sáng ngày 4 tháng 8 năm 2021, giờ Bắc Kinh (khối 12955063), nhiều nhóm thông minh thuộc dự án Popsicle Finance đã bị tấn công, gây thiệt hại hơn 20 triệu đô la Mỹ, đây là thiệt hại lớn nhất cho đến nay trong lĩnh vực DeFi một trong những cuộc tấn công. sau khi phân tíchgiao dịch tấn côngVà mã dự án Chúng tôi nhận thấy rằng cuộc tấn công này là một cuộc tấn công khai thác lỗ hổng kế toán của dự án để thực hiện nhiều lần rút tiền (Phần thưởng yêu cầu nhân đôi). Dưới đây chúng tôi phân tích cuộc tấn công thông qua mã và quá trình tấn công.

phân tích mã

Popsicle Finance là một Nền tảng tối ưu hóa năng suất liên quan đến nhiều chuỗi.

Trước tiên, người dùng gọi chức năng gửi tiền để gửi một lượng thanh khoản nhất định vào Smart Pool và nhận được Mã thông báo Popsicle LP (sau đây gọi là Mã thông báo PLP) làm bằng chứng chia sẻ khoản tiền gửi. Popsicle Finance sẽ gửi thanh khoản do người dùng cung cấp vào các nhóm cơ bản như Uniswap và kiếm thu nhập.

Người dùng cũng có thể gọi chức năng rút tiền để rút thanh khoản từ nhóm thông minh theo chia sẻ thanh khoản được đại diện bởi Mã thông báo PLP do người dùng nắm giữ. Popsicle Finance sẽ lấy thanh khoản tương ứng với Mã thông báo PLP từ các nhóm cơ bản như Uniswap cho người dùng.

Cuối cùng, thanh khoản do người dùng ký gửi trong nhóm thông minh sẽ tạo ra một khoản lợi tức (Yield) nhất định theo thời gian, số tiền này sẽ được tích lũy trong trạng thái người dùng của hợp đồng. Người dùng có thể gọi hàm CollectFees để lấy lại một phần tiền thưởng khi gửi tiền.

Chức năng cốt lõi của cuộc tấn công này là chức năng CollectFees. Hãy phân tích từng bước mã của nó. Trước tiên, hãy lấy trạng thái người dùng được lưu trữ trong userInfo. token0Rewards và token1Rewards ở trạng thái người dùng là phần thưởng được tích lũy do tiền gửi của người dùng.

Tiếp theo, tính toán Số dư của cặp Token tương ứng với Smart Pool trong hợp đồng. Nếu có đủ Số dư trong hợp đồng, Phần thưởng sẽ được trả cho người dùng theo số tiền; nếu không, pool.burnExactLiquidity sẽ được gọi để lấy thanh khoản từ nhóm cơ bản và trả lại cho người dùng.

Cuối cùng, trạng thái Phần thưởng được ghi trong userInfo được cập nhật. Nhìn thấy điều này, việc triển khai mã của nhóm súng máy là khá logic. Nhưng ở phần đầu của hàm chúng ta tìm thấy modifier updateVault, hàm này sẽ chạy trước phần thân hàm của collFees, lỗ hổng có thể nằm ở hàm liên quan đến updateVault.

Trên đây là việc thực hiện các chức năng liên quan đến updateVault. Quá trình này như sau:

  • Lần đầu tiên gọi _earnFees để nhận Phí tích lũy từ nhóm cơ bản;

  • Sau đó gọi _tokenPerShare để cập nhật các tham số token0PerShareStored và token1PerShareStored Hai tham số này biểu thị số lượng token0 và token1 được đại diện bởi mỗi chia sẻ trong nhóm, tức là số lượng cặp Token được đại diện bởi mỗi chia sẻ trong nhóm thông minh;

  • Cuối cùng, hãy gọi phí0Earned và phí1Earned để cập nhật Phần thưởng tiền gửi tương ứng với người dùng này (tức là user.token0Rewards và user.token1Rewards).

Trên đây là cách thực hiện của hàm fee0Earned và hàm fee1Earned, hai hàm này có cách thực hiện giống nhau và cả hai đều thực hiện một công thức như vậy (lấy _fee0Earned làm ví dụ):

user.token0Rewards += PLP.balanceOf(account) * (fee0PerShare - user.token0PerSharePaid) / 1e18

Điều đó có nghĩa là, chức năng này sẽ tính toán phần Phí sẽ được cấp cho người dùng dựa trên user.token0Rewards ban đầu và số lượng Mã thông báo PLP mà người dùng sở hữu.

Nhưng chúng tôi nhận thấy rằng chức năng này là tăng dần, tức là ngay cả khi người dùng không giữ Mã thông báo PLP (PLP.balanceOf(tài khoản) bằng 0), chức năng này vẫn sẽ trả về phần thưởng tiền gửi được lưu trữ trong user.token0Rewards.

Vì vậy, đối với toàn bộ hợp đồng, chúng tôi đã tìm thấy hai lỗ hổng logic quan trọng:

  • Phần thưởng tiền gửi của người dùng được ghi lại trong user.token0Rewards và user.token1Rewards và không bị ràng buộc với bất kỳ Mã thông báo PLP nào hoặc những thứ khác dưới mọi hình thức.

  • Chức năng collFees được sử dụng để truy xuất thu nhập tiền gửi chỉ phụ thuộc vào trạng thái của user.token0Rewards và user.token1Rewards của sổ sách kế toán. Ngay cả khi người dùng không giữ Mã thông báo PLP, phần thưởng tiền gửi tương ứng vẫn có thể được rút.

Chúng tôi tưởng tượng một quá trình tấn công:

  • Kẻ tấn công gửi một lượng thanh khoản nhất định vào nhóm súng máy và lấy một phần Mã thông báo PLP.

  • Kẻ tấn công gọi collFees(0, 0), cập nhật phần thưởng tiền gửi của kẻ tấn công, nghĩa là giá trị của biến trạng thái user.token0Rewards, nhưng không thực sự truy xuất phần thưởng tiền gửi.

  • Kẻ tấn công chuyển Mã thông báo PLP sang các hợp đồng khác dưới sự kiểm soát của anh ta, sau đó gọi collFees(0, 0) để cập nhật biến trạng thái user.token0Rewards. Điều đó có nghĩa là, bằng cách liên tục luân chuyển Mã thông báo PLP và gọi collFees(0, 0), kẻ tấn công đã sao chép phần thưởng tiền gửi tương ứng với các Mã thông báo PLP này.

  • Cuối cùng, kẻ tấn công gọi hàm CollectFees từ các địa chỉ trên để lấy phần thưởng thực. Mặc dù không có Mã thông báo PLP nào trong các tài khoản này vào thời điểm này, nhưng kẻ tấn công đã có thể rút nhiều phần thưởng vì tài khoản không được cập nhật trong user.token0Rewards.

Lấy một ví dụ trong cuộc sống thực để mô tả cuộc tấn công này, nó tương đương với việc gửi tiền vào ngân hàng và ngân hàng đã đưa cho tôi một chứng chỉ tiền gửi, nhưng chứng chỉ này không có biện pháp chống làm giả và không bị ràng buộc với tôi. các bản sao của chứng chỉ và gửi cho những người khác nhau, mỗi người trong số họ đã rút tiền lãi từ ngân hàng nhờ chứng từ này.

Phân tích quá trình tấn công

Thông qua phân tích mã ở trên, chúng tôi đã tìm thấy lỗ hổng trong việc triển khai nhóm thông minh của Popsicle Finance. Tiếp theo, chúng tôi tiến hành phân tích chuyên sâu về giao dịch tấn công để xem cách kẻ tấn công khai thác lỗ hổng này.

Luồng tổng thể của kẻ tấn công như sau:

  • Kẻ tấn công đã tạo ba hợp đồng giao dịch. Một trong số chúng được sử dụng để bắt đầu giao dịch tấn công và hai cái còn lại được sử dụng để nhận Mã thông báo PLP và gọi chức năng CollectFees của Popsicle Finance Smart Pool để lấy phần thưởng tiền gửi.

  • Cho vay một lượng lớn thanh khoản từ AAVE thông qua các khoản vay chớp nhoáng. Kẻ tấn công đã chọn nhiều nhóm thông minh trong dự án Popsicle Finance và cho AAVE vay sáu loại thanh khoản tương ứng với các nhóm thông minh này.

  • Thực hiện chu kỳ Gửi tiền-Rút tiền-Thu phí. Kẻ tấn công đã thực hiện tổng cộng 8 vòng, lần lượt tấn công nhiều nhóm thông minh thuộc dự án Popsicle Finance và lấy đi một lượng lớn thanh khoản.

  • Trả lại các khoản vay nhanh cho AAVE và rửa lợi nhuận thông qua Tornado Cash.

Giao dịch tấn công này chủ yếu bao gồm một số vòng Gửi tiền-Rút tiền-Thu phí và sơ đồ của mỗi vòng được hiển thị trong hình trên. Theo phân tích của chúng tôi, logic như sau:

  • Trước tiên, kẻ tấn công gửi thanh khoản đã vay từ khoản vay flash vào nhóm súng máy và lấy một lượng Mã thông báo PLP nhất định.

  • Kẻ tấn công chuyển Mã thông báo PLP sang hợp đồng tấn công 2.

  • Tấn công hợp đồng 2 và gọi hàm collFees(0, 0) của SmartGun Pool để đặt trạng thái user.token0Rewards và user.token1Rewards tương ứng của hợp đồng 2.

  • Hợp đồng tấn công 2 chuyển PLP Token sang hợp đồng tấn công 3.

  • Tương tự như hoạt động của hợp đồng tấn công 2, hợp đồng tấn công 3 gọi hàm collFees(0, 0) của nhóm thông minh và đặt trạng thái user.token0Rewards và user.token1Rewards tương ứng của hợp đồng 2.

  • Hợp đồng tấn công 2 chuyển Mã thông báo PLP trở lại hợp đồng tấn công, hợp đồng này gọi chức năng rút tiền của nhóm súng máy để đốt Mã thông báo PLP và lấy lại thanh khoản.

  • Hợp đồng tấn công 2 và hợp đồng tấn công 3 gọi chức năng CollectFees để truy xuất phần thưởng tiền gửi với trạng thái tokenRewards sai.

Theo hệ thống trực quan theo dõi giao dịch Ethereum của chúng tôi (https://tx.blocksecteam.com/), sơ đồ cuộc gọi giao dịch như sau và một số giao dịch quan trọng được đánh dấu màu đỏ:

[Máy in tiền ảo] Phân tích tấn công chi tiêu gấp đôi của Popsicle Finance

Phân tích lợi nhuận

Tổng lợi nhuận từ cuộc tấn công này: 2,56 nghìn WETH, 96,2 WBTC, 160 nghìn DAI, 5,39 triệu USDC, 4,98 triệu USDT, 10,5 nghìn UNI, tổng cộng hơn 20.000.000 USD.

Sau cuộc tấn công này, trước tiên, kẻ tấn công đã đổi tất cả các mã thông báo khác thu được trong cuộc tấn công để lấy ETH thông qua Uniswap và WETH, sau đó sử dụng Tornado.Cash nhiều lần để rửa ETH.

Được thúc đẩy bởi công nghệ bảo mật cốt lõi, nhóm BlockSec từ lâu đã quan tâm đến bảo mật DeFi, chống rửa tiền kỹ thuật số và lưu ký tài sản kỹ thuật số dựa trên điện toán bảo mật, cung cấp dịch vụ bảo mật hợp đồng và bảo mật tài sản kỹ thuật số cho các bên dự án DApp. Nhóm đã xuất bản hơn 20 bài báo học thuật về bảo mật hàng đầu (CCS, USENIX Security, S&P) và các đối tác của nhóm đã giành được danh hiệu học giả về quyền riêng tư và bảo mật có ảnh hưởng nhất trên thế giới của AMiner (xếp thứ sáu trên thế giới trong giai đoạn 2011-2020). Các kết quả nghiên cứu đã được CCTV, Tân Hoa xã và các báo cáo phương tiện truyền thông nước ngoài trao giải thưởng. Đã độc lập phát hiện hàng tá lỗ hổng bảo mật và mối đe dọa DeFi, đồng thời giành vị trí đầu tiên trên thế giới trong Cuộc thi Điện toán Quyền riêng tư của Viện Y tế Quốc gia năm 2019 (SGX Track). Được thúc đẩy bởi công nghệ, nhóm tuân thủ khái niệm cởi mở và đôi bên cùng có lợi, đồng thời làm việc với các đối tác cộng đồng để xây dựng một hệ sinh thái DeFi an toàn.

Quét mã QR để chú ý đến nhiều điều thú vị hơn

https://www.blocksecteam.com/

contact@blocksecteam.com

BlockSec
作者文库