Somalisan

Lỗ hổng reentrancy: Tại sao 90% dự án DeFi mới vẫn chết vì 'căn bệnh' 2016?

Hồ Việt Quan điểm

Một dòng require không đảm bảo an toàn — đó là câu nói tôi lặp lại với mọi đội ngũ khởi nghiệp đến xin audit.

Tuần trước, tôi nhận được mã nguồn từ một dự án lending mới trên Base chain. Họ đã huy động được 3 triệu USD từ quỹ đầu tư mạo hiểm. Hợp đồng thông minh nhìn sạch sẽ, giao diện đẹp, roadmap hứa hẹn. Tôi mở file LendingPool.sol, dòng 89:

function withdraw(uint256 amount) external {
    require(balanceOf[msg.sender] >= amount, "Insufficient balance");
    (bool success, ) = msg.sender.call{value: amount}("");
    require(success, "Transfer failed");
    balanceOf[msg.sender] -= amount;
}

Đây là lỗi reentrancy cổ điển — giống hệt vụ DAO hack năm 2016. Tất cả những gì kẻ tấn công cần làm là deploy một hợp đồng callback, gọi withdraw trong hàm receive(), và rút toàn bộ pool trước khi số dư được cập nhật.

Tôi gửi PoC cho đội ngũ. Họ phản hồi trong 2 giờ: "Chúng tôi đã đọc qua OpenZeppelin, nhưng không nghĩ điều này áp dụng cho cơ chế của chúng tôi."

Không, họ nghĩ rằng require(success) là đủ. Nó không đủ. Trong smart contract, không có gọi là "kiểm tra đầy đủ" — chỉ có "kiểm tra đúng thứ tự".

Context: Tại sao reentrancy vẫn là vấn đề số một trong 2024?

Khi tôi bắt đầu audit vào năm 2017, reentrancy là lỗ hổng được nói đến nhiều nhất. Seven năm sau, nó vẫn đứng đầu danh sách lý do các giao thức DeFi mất tiền. Theo báo cáo của Immunefi, reentrancy chiếm 45% tổng số vụ hack trong Q1 2024, với tổng thiệt hại hơn 200 triệu USD.

Tại sao? Bởi vì mỗi thế hệ developer mới đều tự tin rằng họ "hiểu" vấn đề, nhưng không ai thực sự test edge cases. Họ đọc OpenZeppelin, thấy pattern Checks-Effects-Interactions, và nghĩ: "À, mình biết rồi." Nhưng khi triển khai, họ vẫn đặt call trước khi cập nhật state.

Có ba lý do kỹ thuật chính khiến reentrancy sống dai:

Lỗ hổng reentrancy: Tại sao 90% dự án DeFi mới vẫn chết vì 'căn bệnh' 2016?

  1. Sự phức tạp của cross-contract calls: Khi một hợp đồng gọi hợp đồng khác, đặc biệt qua delegatecall, việc theo dõi flow trở nên khó khăn. Một lỗi nhỏ trong logic callback có thể mở ra vector tấn công.
  1. Flash loan cho phép tái sử dụng vốn: Kẻ tấn công không cần có sẵn tiền. Họ vay triệu USD từ Aave, thực hiện reentrancy, trả nợ — tất cả trong một block. Điều này làm tăng scale của tấn công.
  1. Tối ưu hóa gas sai lầm: Nhiều developer cố gắng giảm gas bằng cách gộp các thao tác. Họ move require ra ngoài, đặt call trước state update, và nghĩ rằng mình đang "smart". Họ không phải. Họ đang mở cửa cho hacker.

Core: Phân tích mã nguồn từ góc nhìn audit

Tôi đã decompile 15 hợp đồng bị hack trong 6 tháng qua. Pattern lặp lại giống nhau đến mức nhàm chán. Hãy xem một ví dụ thực tế từ dự án tôi audit tuần trước:

function flashLoan(address token, uint256 amount) external {
    uint256 balanceBefore = IERC20(token).balanceOf(address(this));
    IERC20(token).transfer(msg.sender, amount);

IFlashLoanReceiver(msg.sender).executeOperation{gas: gasleft()}(token, amount, fee); uint256 balanceAfter = IERC20(token).balanceOf(address(this)); require(balanceAfter >= balanceBefore + fee, "Not enough repayment"); } ```

Lỗ hổng reentrancy: Tại sao 90% dự án DeFi mới vẫn chết vì 'căn bệnh' 2016?

Lỗi ở đây là gì? transfer được thực hiện trước khi executeOperation. Nếu executeOperation gọi lại flashLoan, token sẽ được chuyển nhiều lần. Dự án này đã mất 1.2 triệu USD trong testnet.

Lỗ hổng reentrancy: Tại sao 90% dự án DeFi mới vẫn chết vì 'căn bệnh' 2016?

Giải pháp? Sử dụng reentrancy guard từ OpenZeppelin — không phải tự viết. nonReentrant modifier đã được test hàng nghìn lần. Đừng sáng tạo lại bánh xe.

Tôi cũng khuyên sử dụng pattern Checks-Effects-Interactions một cách nghiêm ngặt. Nghĩa là: kiểm tra điều kiện → cập nhật state → tương tác bên ngoài. call luôn ở cuối cùng.

Contrarian: Điểm mù bảo mật mà kiểm toán viên thường bỏ qua

Tôi sẽ nói điều mà ít người trong ngành muốn nghe: Kiểm toán không phải là vé an toàn. Đa số kiểm toán viên chỉ chạy Slither và Mythril, đọc qua báo cáo, và ký tên. Họ không test trên môi trường thực tế với các điều kiện edge case.

Một điểm mù phổ biến là cross-function reentrancy. Khi hàm A gọi hàm B, và B có thể gọi lại A trước khi A kết thúc. Các công cụ tự động thường bỏ lỡ điều này. Chỉ có audit thủ công với test case cụ thể mới phát hiện được.

Ví dụ: Tôi từng gặp một hợp đồng staking, nơi hàm stake gọi _mint (mint token ERC-20), và _mint trigger transfer callback đến người nhận. Trong callback, kẻ tấn công có thể gọi unstake — rút tiền trước khi stake được hoàn tất. Kết quả: họ nhận cả token staking lẫn token gốc.

Điểm mù thứ hai là reentrancy qua delegatecall. Khi một proxy contract gọi implementation qua delegatecall, nếu implementation có lỗ hổng reentrancy, proxy cũng bị ảnh hưởng. Nhưng vì proxy không xử lý logic trực tiếp, nhiều developer nghĩ rằng nó an toàn. Sai.

Takeaway: Dự báo lỗ hổng sẽ xuất hiện ở đâu?

Tôi dự đoán trong 12 tháng tới, reentrancy sẽ tấn công mạnh vào các giao thức cross-chain messagingintent-based architecture. Khi message từ chain A đến chain B được xử lý, nếu không có reentrancy guard, kẻ tấn công có thể gọi lại bridge contract trước khi message được xác nhận.

Cụ thể: Wormhole và LayerZero đã từng bị hack vì vấn đề này. Các fork của chúng sẽ tiếp tục lặp lại sai lầm.

Câu hỏi tôi để lại cho bạn đọc: Khi bạn deploy contract tiếp theo, bạn có chắc rằng require của bạn đủ mạnh để chống lại reentrancy không? Hay bạn chỉ đang fork cái chết của người khác?

Giá thị trường

Tiền điện tử Giá 24h
BTC Bitcoin
$63,060.2 -0.04%
ETH Ethereum
$1,881.35 -0.01%
SOL Solana
$75.45 +0.19%
BNB BNB Chain
$605.4 -0.98%
XRP XRP Ledger
$1 -0.18%
DOGE Dogecoin
$0.0698 -0.37%
ADA Cardano
$0.1770 -1.45%
AVAX Avalanche
$6.34 -4.45%
DOT Polkadot
$0.7606 -1.36%
LINK Chainlink
$9.36 -0.27%

Sợ & Tham

34

Sợ hãi

Tâm lý thị trường

Tin nhanh 7x24h

Thêm >
{{快讯列表(10)}} {{loop}}
{{快讯时间}}

{{快讯内容}}

{{快讯标签}}
{{/loop}} {{/快讯列表}}

Lịch sự kiện blockchain

{{年份}}
18
03
unlock Mở khóa token Sui

Phần đội ngũ và nhà đầu tư sớm được giải phóng

15
04
halving Bitcoin Halving

Phần thưởng khối giảm xuống 3,125 BTC

22
03
unlock Mở khóa Optimism

Lượng cung lưu hành tăng khoảng 2%

10
05
upgrade Nâng cấp Ethereum Pectra

Tăng giới hạn validator và trừu tượng hóa tài khoản

08
04
upgrade Solana Firedancer

Trình xác thực độc lập ra mắt trên mainnet

28
03
unlock Mở khóa token Arbitrum

Giải phóng 92 triệu ARB

12
05
halving BCH Halving

Sự kiện giảm một nửa phần thưởng khối

30
04
upgrade Nâng cấp Celestia Mainnet

Cải thiện hiệu quả lấy mẫu tính khả dụng dữ liệu

🧮 Công cụ

Tất cả →

Chỉ số mùa altcoin

44

Mùa Bitcoin

Sự thống trị BTC Mùa altcoin

Theo dõi phí Gas

Ethereum 28 Gwei
BNB Chain 3 Gwei
Polygon 42 Gwei
Arbitrum 0.5 Gwei
Optimism 0.3 Gwei

Vốn hóa thị trường

Tất cả →
# Tiền điện tử Giá
1
Bitcoin BTC
$63,060.2
1
Ethereum ETH
$1,881.35
1
Solana SOL
$75.45
1
BNB Chain BNB
$605.4
1
XRP Ledger XRP
$1
1
Dogecoin DOGE
$0.0698
1
Cardano ADA
$0.1770
1
Avalanche AVAX
$6.34
1
Polkadot DOT
$0.7606
1
Chainlink LINK
$9.36

🐋 Theo dõi cá voi

🟢
0x27c8...7dd9
6 giờ trước
Chuyển vào
1,494,873 USDT
🟢
0xadab...309f
12 phút trước
Chuyển vào
1,532,473 USDT
🔴
0x3a92...fe34
12 giờ trước
Chuyển ra
1,307.25 BTC

💡 Smart Money

0x7fd0...cce7
Nhà đầu tư sớm
-$0.7M
62%
0xe072...ec48
Nhà giao dịch on-chain dày dặn
+$1.8M
95%
0xc0c5...76c0
Bot chênh lệch giá
+$1.4M
75%