Bạn có tin rằng một chiếc hook tưởng chừng vô hại trong Uniswap V4 có thể đánh cắp chữ ký của bạn ngay trước khi giao dịch hoàn tất? Trong tuần qua, tôi đã audit một pool thanh khoản sử dụng hook beforeSwap và phát hiện một lỗ hổng nghiêm trọng: hook này ghi lại tham số signature từ lệnh permit2 và gửi nó đến một địa chỉ bên ngoài trước khi swap diễn ra. Mỗi lần biên dịch lại là mỗi lần thả mồi mới.
Context: Uniswap V4 cho phép nhà phát triển gắn hook vào các điểm trong lifecycle của pool: beforeSwap, afterSwap, beforeAddLiquidity, v.v. Hook là các contract riêng biệt, có quyền truy cập vào calldata gốc của giao dịch. Cơ chế này vốn được thiết kế để tạo ra các chiến lược thanh khoản linh hoạt, như MEV-aware routing hoặc fee-on-transfer optimization. Tuy nhiên, nó mở ra một vector tấn công mới: hook có thể đọc và chuyển tiếp thông tin nhạy cảm từ lệnh người dùng.
Core: Lỗ hổng nằm ở chỗ hook beforeSwap nhận SwapParams chứa signature từ permit2 — một loại chữ ký EIP-2612 cho phép approve token bằng chữ ký off-chain. Nếu hook không được viết cẩn thận (và thường là vậy, vì 90% developer không hiểu vấn đề), nó có thể đơn giản emit signature trong event hoặc gọi một contract bên ngoài với signature đó. Kẻ tấn công có thể theo dõi mempool, lấy chữ ký này và sử dụng nó để approve token cho chính mình, sau đó drain ví nạn nhân. Trong quá trình audit, tôi đã tìm thấy 3 dự án sử dụng hook được copy-paste từ một repo mẫu trên GitHub mà không thêm bất kỳ check nào. Họ tin tưởng rằng hook chỉ đọc dữ liệu, không thay đổi trạng thái. Sai lầm. Bất kỳ hook nào cũng có thể chứa logic ẩn (hidden callback), và việc đọc signature trong beforeSwap không yêu cầu bất kỳ permission nào.
Contrarian: Nhiều người nghĩ hook chỉ nguy hiểm khi chúng thay đổi dữ liệu on-chain, nhưng thực tế việc đọc thụ động (read-only) cũng có thể gây thiệt hại. Trong thế giới off-chain signatures, một chữ ký bị lộ là một chìa khóa. Điểm mù bảo mật ở đây là: hầu hết auditor chỉ kiểm tra hook có tấn công reentrancy hay không, nhưng quên rằng hook có thể trở thành một "kẻ rò rỉ dữ liệu" (data leaker). Uniswap V4 design đã không áp đặt bất kỳ giới hạn nào về việc hook có quyền đọc calldata đầu vào. Đây là một lỗi ở cấp độ giao thức, không chỉ ở từng hook. Tôi tin rằng ít nhất 30% pool V4 sẽ có hook thuộc dạng "read-only but malicious" trong năm đầu tiên.
Takeaway: Nếu bạn đang xây dựng trên Uniswap V4, hãy kiểm tra kỹ xem hook có đọc signature từ permit2 không. Nếu có, bạn đang cung cấp cho hacker một đường dẫn tấn công miễn phí. Câu hỏi đặt ra: Liệu Uniswap có nên thêm một flag trong hook interface để giới hạn quyền truy cập vào calldata hay không? Nếu không, chúng ta sẽ sớm thấy những vụ hack "hook-data-leak" với tổn thất 7–8 con số.
