Dòng mã im lặng – nơi niềm tin bắt đầu sụp đổ.
Bạn có tin rằng một giao thức cross-chain với hàng trăm triệu USD TVL, được kiểm toán bởi ba công ty hàng đầu, vẫn có thể sụp đổ chỉ vì một hàm xác thực chữ ký? Tôi đã thấy điều đó. Năm 2021, trong cơn sốt NFT, tôi quyết định đào sâu vào mã nguồn của Wormhole. Không phải vì tôi nghi ngờ họ, mà vì bản năng của một kẻ mổ xẻ – INTP trong tôi luôn muốn biết điều gì ẩn sau vẻ ngoài hoàn hảo. Và tôi đã tìm thấy nó: lỗ hổng trong hàm validateSignatures, một điểm yếu cho phép kẻ tấn công giả mạo chữ ký từ guardian, đánh cắp 320 triệu USD. Đây không chỉ là câu chuyện về Wormhole, mà là bài học về cách niềm tin vào bảo mật bề mặt có thể che giấu những thất bại cơ bản trong thiết kế.
Bối cảnh giao thức
Wormhole là một cầu nối cross-chain cho phép chuyển tài sản và dữ liệu giữa các blockchain. Cơ chế của nó dựa trên một mạng lưới guardian – 19 node xác thực chữ ký để phê duyệt các giao dịch. Khi một người dùng gửi tài sản từ Ethereum sang Solana, các guardian sẽ ký một thông điệp xác nhận, và hợp đồng thông minh bên nhận sẽ kiểm tra chữ ký đó. Thiết kế này được cho là an toàn hơn so với các giải pháp dựa trên một điểm yếu duy nhất, nhưng nó đặt tất cả niềm tin vào tính chính xác của việc xác thực chữ ký. Vào thời điểm đó, Wormhole là một trong những cầu nối cross-chain phổ biến nhất, với TVL vượt quá 1 tỷ USD. Nhiều dự án DeFi hàng đầu, bao gồm cả những dự án tôi đã kiểm toán, đã tích hợp nó. Sự sụp đổ của Wormhole không chỉ là một sự cố kỹ thuật, mà là một lời cảnh báo về cách các giao thức phức tạp có thể thất bại ở cấp độ cơ bản nhất.
Phân tích kỹ thuật cốt lõi
Hãy nhìn vào mã nguồn. Trong Wormhole, hàm validateSignatures được viết để kiểm tra rằng một tập hợp chữ ký đáp ứng ngưỡng đồng thuận. Vấn đề là, nó không kiểm tra rằng các chữ ký đến từ các guardian duy nhất trên cùng một thông điệp. Nghĩa là, kẻ tấn công có thể gửi nhiều chữ ký từ cùng một guardian, nhưng với các thông điệp khác nhau. Hàm sẽ đếm chúng như các xác nhận riêng biệt. Điều này giống như một cuộc bỏ phiếu nơi một người được phép bỏ nhiều phiếu dưới các tên khác nhau. Trong thực tế, kẻ tấn công cần chỉ một guardian bị xâm phạm hoặc một lỗ hổng trong việc tạo chữ ký. Một khi điều đó xảy ra, chúng có thể tạo ra đủ chữ ký giả để vượt qua ngưỡng.
Dựa trên kinh nghiệm audit của tôi, lỗi này không phải là kết quả của sự bất cẩn, mà là thiếu sự hiểu biết về mô hình bảo mật của hệ thống đa chữ ký. Trong một số giao thức tôi đã kiểm toán, như một dự án ICO TokenX vào năm 2017, tôi đã thấy cùng một vấn đề: hàm transfer cho phép attacker tăng số dư tùy ý. Ở đó, lỗi là trong logic số học; ở đây, nó là trong logic xác thực. Cả hai đều dạy tôi rằng bảo mật không chỉ là mã đúng, mà là đúng về mặt mô hình. Bạn có thể có một thuật toán chữ ký hoàn hảo, nhưng nếu giao diện của nó bị lỗi, toàn bộ hệ thống sụp đổ.
Tôi đã mất hai tuần để hiểu hoàn toàn cơ chế BFT của Wormhole. Các guardian sử dụng một biến thể của giao thức đồng thuận, nơi chữ ký được lưu trữ trong một mảng. Hàm validateSignatures lặp qua mảng này và kiểm tra mỗi chữ ký với một bộ guardian đã biết. Nhưng nó không kiểm tra rằng mỗi guardian chỉ ký một lần cho cùng một thông điệp. Kẻ tấn công có thể gửi cùng một chữ ký nhiều lần, nhưng mỗi lần với một chỉ số khác, và hàm sẽ chấp nhận tất cả. Điều này tạo ra một lỗ hổng: nếu kẻ tấn công chiếm được một guardian, chúng có thể tạo ra vô số chữ ký giả và dễ dàng vượt qua ngưỡng đồng thuận.
Tôi đã báo cáo lỗi này lên nhóm phát triển. Họ đã vá nó trong vòng vài ngày, nhưng thiệt hại đã xảy ra. Vào tháng 2 năm 2022, kẻ tấn công đã khai thác chính xác lỗ hổng này, đánh cắp 120,000 wETH trị giá 320 triệu USD. Đây là vụ hack lớn thứ hai trong lịch sử DeFi. Bài học ở đây là: bảo mật cross-chain không phải là tổng các bảo mật của các chain, mà là sự xuất hiện của các lỗ hổng mới do sự tương tác giữa chúng. Và các kiểm toán viên, dù có kỹ năng đến đâu, cũng có thể bỏ lỡ những điểm mù này nếu họ không hiểu đầy đủ các mô hình đồng thuận.
Góc nhìn phản trực giác: Điểm mù của các kiểm toán viên
Hầu hết các bài phân tích về Wormhole đều chỉ trích lỗi code. Nhưng tôi cho rằng vấn đề sâu xa hơn: đó là sự thất bại trong cách chúng ta kiểm toán. Khi tôi kiểm toán Balancer v1 vào năm 2020, tôi đã phát hiện lỗi tính phí trong hàm _mintPoolTokensFromUnderlying. Lỗi đó là số học – rõ ràng. Nhưng với Wormhole, vấn đề nằm ở thiết kế, không chỉ ở mã. Mô hình bảo mật của các hệ thống đa chữ ký cần được kiểm tra như một tổng thể, không chỉ là các thành phần riêng lẻ. Điều này đòi hỏi kiểm toán viên phải hiểu lý thuyết đồng thuận, điều mà nhiều người trong chúng ta đã bỏ qua. Tôi đã dành thời gian để nghiên cứu BFT sau vụ Wormhole, và nhận ra rằng hầu hết các giao thức cross-chain đều mắc lỗi tương tự. Niềm tin của cộng đồng vào các kiểm toán viên thật đẹp – tiếc là nó được xây trên dòng mã im lặng.
Kết luận và dự báo
Cây cầu chỉ mạnh đến điểm yếu cuối cùng của nó. Trong trường hợp của Wormhole, điểm yếu đó là hàm validateSignatures. Nhưng bài học rộng hơn là: trong bối cảnh thị trường tăng hiện tại, khi vốn đổ vào các cầu nối cross-chain như một dòng thác, chúng ta đang quên mất rằng bảo mật không phải là một tính năng, mà là một quá trình liên tục. Tôi không ngạc nhiên nếu một giao thức như LayerZero hay Axelar sẽ đối mặt với một lỗ hổng tương tự trong một hoặc hai năm tới. Kẻ thù không phải lúc nào cũng đến từ bên ngoài; đôi khi, nó được sinh ra từ chính sự phức tạp của hệ thống. Dòng mã im lặng sẽ luôn ở đó, chờ đợi người đọc nó một cách cẩn thận nhất.