Phân tích sự cố zkLend Finance

Bài viết này được dịch máy
Xem bản gốc

Vào ngày 12 tháng 2 năm 2025, giao thức tài chính zkLend đã bị khai thác, dẫn đến mất khoảng 9,5 triệu USD.

zkLend là một giao thức cho vay phi tập trung hoạt động trên chuỗi Starknet. Nó cho phép người dùng cho vay và vay tài sản, tương tự như các giao thức như Aave hoặc Compound.

Cuộc tấn công nhắm vào hợp đồng zkLend Market (cụ thể là thị trường wstETH), đây là hợp đồng chính cho phép người dùng cho vay và vay tài sản.

Thông tin chính

Phân tích lỗ hổng

Nhìn vào địa chỉ của kẻ tấn công, chúng ta có thể thấy rằng đã có nhiều giao dịch diễn ra trong thời gian xảy ra cuộc tấn công.

Để hiểu cuộc tấn công, trước tiên chúng ta cần xem xét giao dịch gọi runwithfirstdep, vì nó dường như là quan trọng nhất.

Trong giao dịch runwithfirstdep, chúng ta có thể thấy nhiều lệnh depositwithdraw liên tiếp đến hợp đồng zkLend Market. Hãy xem xét chi tiết của một lệnh deposit trước.

Rõ ràng là số lượng trong các lệnh depositwithdraw không giống nhau, cho thấy đây không phải là một giao dịch gửi và rút đơn giản. Ở đây, chúng ta thấy rằng kẻ tấn công chỉ gửi 4.069 wstETH nhưng rút 6.103 wstETH. Do đó, chúng ta cần xem xét mã của các hàm depositwithdraw để hiểu cuộc tấn công.

Đi qua mã của hàm deposit, chúng ta có thể thấy rằng nó nhận amount của token đầu vào và đúc một lượng tương ứng của zToken. Điều tương tự cũng áp dụng cho hàm withdraw. Tuy nhiên, tại sao kẻ tấn công có thể đốt nhiều zToken hơn họ nên làm? Điều này dẫn chúng ta đến việc xem xét cách thực hiện của hàm burn trong hợp đồng zToken.

Từ cách thực hiện của hàm burn, chúng ta có thể thấy rằng số lượng thực tế bị đốt là scaledDownAmount. Ngoài ra, bằng cách xem xét hàm safe_math::sub(), chúng ta có thể xác định rằng công thức tính scaledDownAmountamount * SCALE / accumulator.

Vì vậy, cách dễ nhất để kiểm tra giá trị này là kiểm tra các giá trị này từ giao dịch tấn công. Và chúng ta có các giá trị sau:

  • amount: 6103946859077466029 (lệnh rút)

  • accumulator: 4069297906051644020000000000000000000000000000

  • SCALE: 1000000000000000000000000000

Từ những giá trị này, chúng ta có thể tính scaledDownAmount như sau:

scaledDownAmount = amount * SCALE / accumulator

= 6103946859077466029 * 1000000000000000000000000000 / 4069297906051644020000000000000000000000000000

= 1

Vì vậy, bây giờ rõ ràng rằng giá trị này đã được kẻ tấn công lựa chọn cẩn thận để vượt qua kiểm tra của scaled_down_amount.is_non_zero(). Giao dịch deposit trước giao dịch runwithfirstdep được sử dụng để thao túng kết quả của hàm get_lending_accumulator() để làm cho giá trị này lớn hơn nhiều và hiệu quả làm cho scaled_down_amount trở thành 1.

Phân tích sau cuộc tấn công

Sau cuộc tấn công, số tiền bị đánh cắp đã được chuyển từ Starknet sang chuỗi Ethereum. Sau đó, kẻ tấn công đã cố gắng rửa tiền bằng cách gửi chúng vào các bể Railgun, nhưng đã bị ngăn chặn bởi các chính sách của giao thức. Việc cố gắng rửa tiền thất bại này nhấn mạnh tầm quan trọng của việc cân bằng giữa quyền riêng tư và minh bạch trong không gian DeFi.

Bài học kinh nghiệm

Sự cố này nhấn mạnh tầm quan trọng của việc kiểm tra cẩn thận các giá trị đầu vào trong các hợp đồng thông minh, đặc biệt là khi xử lý các hoạt động tài chính phức tạp và nhạy cảm. Bằng cách học hỏi từ các sự cố như thế này, cộng đồng DeFi có thể xây dựng các hệ thống bền vững hơn và bảo vệ tốt hơn các khoản tiền của người dùng.

Nguồn
Tuyên bố từ chối trách nhiệm: Nội dung trên chỉ là ý kiến của tác giả, không đại diện cho bất kỳ lập trường nào của Followin, không nhằm mục đích và sẽ không được hiểu hay hiểu là lời khuyên đầu tư từ Followin.
Thích
Thêm vào Yêu thích
Bình luận