Quét để tải ứng dụng Gate
qrCode
Thêm tùy chọn tải xuống
Không cần nhắc lại hôm nay

Tấn công tái nhập: Tại sao Hợp đồng thông minh liên tục bị rút cạn ( và Cách ngăn chặn nó )

Phiên bản Nhanh: Tấn công tái nhập giống như một kẻ hacker gọi bạn lại trong khi bạn vẫn đang chuyển tiền cho họ—họ sẽ rút cạn ví của bạn trước khi giao dịch thậm chí kết thúc.

Sự thật tàn bạo là: Hơn $100M đã bị mất do các cuộc tấn công tái nhập. Cuộc tấn công nổi tiếng nhất? Cuộc tấn công DAO (2016) đã đánh cắp $50M ETH bằng cách khai thác chính điểm yếu này.

Cách thức tấn công hoạt động (Sử dụng logic mã thực )

Hãy tưởng tượng rằng ContractA nắm giữ 10 ETH và ContractB có số dư 1 ETH được lưu trữ bên trong.

Khi ContractB gọi withdrawAll(), đây là những gì nên xảy ra:

  1. Kiểm tra số dư > 0 ✓
  2. Gửi ETH lại ✓
  3. Cập nhật số dư về 0 ✓

Nhưng đây là nơi nó bị phá vỡ: Kẻ tấn công khai thác thứ tự thực hiện.

Luồng khai thác:

  • Kẻ tấn công gọi attack() → điều này gọi withdrawAll() trên ContractA
  • ContractA gửi 1 ETH và kích hoạt hàm fallback() của kẻ tấn công
  • Trước khi số dư cập nhật về 0, fallback() ngay lập tức gọi withdrawAll() một lần nữa.
  • ContractA kiểm tra: “Số dư > 0?” CÓ ( vì nó chưa được cập nhật!)
  • Gửi thêm 1 ETH → kích hoạt fallback() một lần nữa
  • Vòng lặp này cho đến khi ContractA hoàn toàn cạn kiệt

Thông tin chính: Việc cập nhật số dư xảy ra SAU khi chuyển ETH. Đó là khoảng thời gian dễ bị tổn thương.

Ba Chiến Lược Phòng Thủ

1. Bộ điều chỉnh nonReentrant (Bảo vệ Chức năng Đơn )

Khóa chức năng trong khi nó đang thực thi. Không cho phép nhập lại: solidity modifier nonReentrant { require(!locked, “Không tái nhập”); locked = true; _; locked = false; }

Đơn giản, nhưng chỉ bảo vệ một chức năng tại một thời điểm.

2. Mẫu Kiểm Tra - Tác Động - Tương Tác (Bảo Vệ Đa Chức Năng)

Đây là yếu tố thay đổi cuộc chơi:

  • Kiểm tra: Xác minh điều kiện (balance > 0)
  • Effects: Cập nhật trạng thái (balance = 0) ← Di chuyển điều này TRƯỚC khi gửi ETH
  • Tương tác: Gửi ETH

Đơn hàng sai:

require(balance > 0); → gửi ETH → balance = 0; // Quá muộn!

Thứ tự đúng:

require(balance > 0); → balance = 0; // Cập nhật ĐẦU TIÊN → gửi ETH // Sau đó tương tác

Bây giờ ngay cả khi fallback() quay trở lại, số dư đã là 0. Cuộc tấn công thất bại.

3. GlobalReentrancyGuard (Bảo vệ giữa các hợp đồng)

Đối với các hệ thống phức tạp với nhiều hợp đồng tương tác, sử dụng một hợp đồng bảo vệ tập trung theo dõi trạng thái khóa trên tất cả các hợp đồng. Khi ContractA gọi ContractB, hợp đồng bảo vệ ghi lại điều đó—nếu ContractB cố gắng gọi lại vào hệ thống trước khi hoàn trả, hợp đồng bảo vệ sẽ chặn lại.

Tại Sao Điều Này Quan Trọng

Rentrancy không chỉ là vấn đề của Solidity—mà là một vấn đề thiết kế. Mỗi khi bạn gửi ETH hoặc gọi các hàm bên ngoài, bạn đang giao quyền kiểm soát cho mã không đáng tin cậy. Hàm fallback của kẻ tấn công chạy trong ngữ cảnh của HỢP ĐỒNG của BẠN.

Dữ liệu: Chainalysis phát hiện ~60% các cuộc tấn công giá trị cao trong 2023-2024 liên quan đến reentrancy hoặc các mẫu tương tự. Các dự án hàng đầu như Yearn, Curve và Balancer đều đã gặp phải những lo ngại về reentrancy.

Kết luận: Sử dụng Checks-Effects-Interactions như mặc định. Thêm nonReentrant khi cần thiết. Đối với hệ thống đa hợp đồng, triển khai GlobalReentrancyGuard. Số tiền hơn $100M đã mất có thể đã được cứu với những mẫu cơ bản này.

Theo dõi @TheBlockChainer để biết thêm về các phân tích sâu về bảo mật Web3.

ETH-1.62%
CRV7.26%
BAL-3.51%
Xem bản gốc
Trang này có thể chứa nội dung của bên thứ ba, được cung cấp chỉ nhằm mục đích thông tin (không phải là tuyên bố/bảo đảm) và không được coi là sự chứng thực cho quan điểm của Gate hoặc là lời khuyên về tài chính hoặc chuyên môn. Xem Tuyên bố từ chối trách nhiệm để biết chi tiết.
  • Phần thưởng
  • Bình luận
  • Đăng lại
  • Retweed
Bình luận
0/400
Không có bình luận
  • Ghim
Giao dịch tiền điện tử mọi lúc mọi nơi
qrCode
Quét để tải xuống ứng dụng Gate
Cộng đồng
Tiếng Việt
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)