Hook
Ngày 12 tháng 3 năm 2025, một giao thức cross-chain bridge (tạm gọi là ChainLinker) mất 23 triệu USD trong 6 block. Điều đáng chú ý không phải số tiền, mà là vector tấn công: kẻ tấn công đã khai thác giả định tin cậy trong sequencer của chain nguồn. Tôi đã fork code của giao thức này và phát hiện ra logic kiểm tra trạng thái thiếu hụt nghiêm trọng. Đây không phải lỗi reentrancy hay oracle thông thường, mà là một lỗ hổng kiến trúc mà các đội ngũ thường bỏ qua khi "mở rộng quy mô".
Context
Cross-chain bridge hoạt động dựa trên cơ chế lock-mint hoặc burn-mint. Ở phía chain nguồn, người dùng gửi token vào contract bridge, sau đó sequencer của giao thức (một node duy nhất chạy bởi đội ngũ) sẽ xác nhận giao dịch và gửi message đến chain đích qua một relayer. Sequencer có quyền lực tối thượng: nó ký lên trạng thái của chain nguồn và quyết định giao dịch nào được relay. Trong ChainLinker, sequencer sử dụng một EOA (Externally Owned Account) đơn giản để ký, không có multisig hay threshold signature.
Điều mà các dev không nói với bạn: sequencer trong hầu hết các bridge hiện nay là một điểm tập trung đơn lẻ, và "phi tập trung hóa sequencer" mới chỉ dừng ở PowerPoint.
Core
Hãy cùng trace execution path:
- User gửi 100 USDC vào contract bridge trên Ethereum.
- Contract bridge emit event
Locked(user, 100, chainId). - Sequencer (chạy node lắng nghe sự kiện) đọc event này và tạo message
{action: 'mint', recipient: user, amount: 100, nonce: 1234}. - Sequencer ký message bằng private key của nó.
- Relayer gửi message đến chain đích, contract bridge trên chain đích kiểm tra chữ ký sequencer và mint 100 USDC cho user.
Vấn đề: trong bước 3, sequencer có thể tùy ý sửa đổi nonce hoặc amount trước khi ký. Nhưng lần này lỗ hổng nằm ở chỗ sequencer không kiểm tra tính hợp lệ của event. Kẻ tấn công deploy một contract độc hại gọi hàm lock() với lượng token rất nhỏ (1 wei), nhưng contract của hắn emit event giả mạo với amount 1 triệu USDC. Sequencer không phân biệt được event thật từ contract bridge hợp lệ và event giả từ contract lạ, vì nó chỉ lắng nghe tất cả các event có signature giống nhau từ bất kỳ địa chỉ nào.
Giả định tin cậy họ đang đặt ra: tất cả các event phát ra từ contract nào đó đều được coi là valid. Họ quên mất rằng bất kỳ contract nào cũng có thể emit event cùng signature.
Lỗ hổng này có thể được fix bằng cách lọc địa chỉ contract nguồn trong sequencer, nhưng đội ngũ vì vội vàng ship sản phẩm đã không làm điều đó. Tôi đã thấy pattern này ít nhất 5 lần trong các audit của mình.
Phân tích chi tiết code:
// Contract bridge (simplified)
function lock(uint256 amount) external {
require(token.transferFrom(msg.sender, address(this), amount));
emit Locked(msg.sender, amount, block.chainid);
}
Sequencer script (Python-like): ``python for event in web3.eth.get_logs(from_block=last_block): if event['event'] == 'Locked': user, amount, chainId = event['args'] sign_and_relay(user, amount, chainId) ``
Đây là lỗ hổng kiến trúc: sequencer không xác thực event emitter. Hacker deploy contract sau:
contract FakeBridge {
function fakeLock(address user, uint256 amount) external {
emit Locked(user, amount, block.chainid);
}
}
Gọi fakeLock(user, 1000000e18) → sequencer relay amount 1 triệu USDC.
Điều tinh tế (và đáng sợ) trong thiết kế này là sequencer không lưu trạng thái nonce, nên hacker có thể gọi nhiều lần, mỗi lần nonce tăng lên, làm tràn ngập chain đích với các mint giả.
Contrarian
Phần lớn phân tích sai về cross-chain bridge security. Mọi người thường tập trung vào oracle hay validator set, nhưng điểm yếu thực sự lại nằm ở layer relay: sequencer đơn lẻ với quá nhiều đặc quyền. Ngay cả khi bạn có multisig, nếu logic phía sau không kiểm tra nguồn event, multisig cũng vô dụng.
Hầu hết các bài viết về cross-chain đều hô hào 'decentralized bridges' nhưng quên mất rằng bridge là chain ngắn nhất từ người dùng đến sự tập trung.
Một góc nhìn phản trực giác khác: giải pháp không nên là làm sequencer phi tập trùng bằng zk proof cho mọi thứ, vì điều đó tăng latency và cost. Thay vào đó, hãy giữ sequencer đơn giản nhưng thêm một lớp xác thực phía chain đích: contract đích nên kiểm tra rằng event được emit từ contract bridge đã đăng ký trước (whitelist). Cơ chế này đã tồn tại từ năm 2020, nhưng các dự án mới vẫn mắc lỗi tương tự.
Takeaway
Khi bạn nghe một dự án bridge nói 'chúng tôi có sequencer decentralized', hãy hỏi: 'Ai kiểm tra source của event?'. Câu trả lời thường là sự im lặng. Cho đến khi hệ thống bị tấn công, họ mới nhận ra rằng bài toán không nằm ở ai ký, mà nằm ở cái gì được ký.
Dự báo lỗ hổng: trong 6 tháng tới, sẽ có ít nhất 3 vụ tấn công bridge khác dựa trên cùng vector này. Hãy chuẩn bị sẵn forensic scripts.