BTC $78,353.1 -0.41%
ETH $2,466.38 +0.64%
SOL $96.58 -0.81%
BNB $697.9 +0.29%
XRP $1.37 -5.35%
DOGE $0.0849 -2.68%
ADA $0.2049 -3.85%
AVAX $7.23 -2.38%
DOT $0.8391 -3.49%
LINK $11.26 -1.20%
⛽ ETH Gas 28 Gwei
Sợ&Tham
65

Ngẫu nhiên trên blockchain: Khi 'Math.random()' là con dao hai lưỡi và những bài học từ audit 9 năm

Tin nhanh | Dương Tuệ |

Hook: Dòng code chết người trong hợp đồng NFT

Hai năm trước, tôi nhận audit một dự án NFT đang hot. Đội ngũ developer tự hào khoe cơ chế mint ngẫu nhiên: họ dùng block.timestamp kết hợp với msg.sender để tạo ra chỉ số hiếm. Tôi chỉ hỏi một câu: "Nếu bạn là validator, bạn có thể sắp xếp thứ tự giao dịch để chọn block có timestamp phù hợp không?" Cả team im lặng. Đó là lúc tôi nhận ra rằng một bài báo khoa học phổ thông về tính ngẫu nhiên trên blockchain có thể cứu hàng triệu USD, nhưng cũng có thể tạo ra ảo tưởng an toàn nếu thiếu chiều sâu kỹ thuật.

Bài viết "Crypto Briefing - Verifiable Randomness" mà tôi có dịp xem lại gần đây là một ví dụ điển hình. Nó đúng về mặt khái niệm, nhưng lại bỏ qua những chi tiết mà chỉ ai từng audit code mới thấy. Hôm nay, tôi sẽ phân tích bài báo đó dưới góc nhìn của một Kỹ sư Kiến trúc Smart Contract, kết hợp với 9 năm kinh nghiệm phát hiện lỗ hổng ngẫu nhiên trên chuỗi.


Context: Blockchain không có 'Math.random()'

Trong lập trình truyền thống, Math.random() là một hàm giả ngẫu nhiên dựa trên seed. Bạn không cần chứng minh rằng kết quả là thực sự ngẫu nhiên; bạn chỉ cần nó đủ tốt cho mục đích thống kê. Nhưng trên blockchain, mọi thứ khác biệt. Lý do: môi trường thực thi là xác định (deterministic). Tất cả các node trong mạng phải chạy cùng một code với cùng một đầu vào và cho ra cùng một kết quả. Nếu một node có thể dự đoán hoặc ảnh hưởng đến đầu vào của hàm ngẫu nhiên, thì tính bất ngờ bị phá vỡ.

Bài báo của Crypto Briefing đã chỉ ra chính xác điểm này: "Blockchain không thể sử dụng bộ tạo số ngẫu nhiên thông thường" (thông tin điểm 1). Và đúng vậy, block.timestamp, blockhash, msg.sender, thậm chí tx.origin đều có thể bị thao túng ở một mức độ nào đó. Ví dụ: validator có thể chọn không đưa giao dịch của bạn vào block nếu timestamp không có lợi cho họ. Đây là một lỗ hổng kinh điển mà tôi đã thấy trong ít nhất 5 dự án GameFi.

Tuy nhiên, bài báo không dừng lại ở cảnh báo. Nó nhấn mạnh rằng Ethereum và các mạng khác sử dụng phương pháp mật mã để tạo ra tính ngẫu nhiên có thể xác thực (thông tin điểm 2). Điều này là chính xác, nhưng tôi cho rằng cách diễn giải còn quá đơn giản. Có ít nhất ba cơ chế chính đang được sử dụng, mỗi cơ chế có một bộ trade-off riêng mà developer cần hiểu rõ.


Core: Ba trụ cột của tính ngẫu nhiên trên chuỗi

1. RANDAO – Ngẫu nhiên từ sự tham gia tập thể

RANDAO là cơ chế được Ethereum Beacon Chain sử dụng. Nó hoạt động như sau: một nhóm người tham gia (validator) gửi một cam kết (commit) – là hash của một số ngẫu nhiên mà họ chọn. Sau đó, trong giai đoạn tiết lộ (reveal), họ gửi số gốc. Tất cả các số được kết hợp (XOR) để tạo ra entropy cuối cùng. Cơ chế này an toàn nếu có ít nhất một người tham gia trung thực. Nhưng nó có một điểm yếu: validator cuối cùng có thể biết kết quả trước khi tiết lộ và quyết định không tiết lộ nếu kết quả không có lợi. Điều này được gọi là “last-revealer attack”. Ethereum đã giải quyết bằng cách phạt tiền (slashing) nếu không tiết lộ, nhưng cơ chế này không phải lúc nào cũng hiệu quả trong mọi bối cảnh.

2. VRF (Verifiable Random Function) – Ngẫu nhiên có chữ ký

Chainlink VRF là ví dụ phổ biến nhất. VRF cho phép một người dùng (hoặc hợp đồng) yêu cầu một số ngẫu nhiên, và nhận được một bằng chứng mật mã cho phép bất kỳ ai xác minh rằng số đó được tạo ra từ một khóa bí mật cụ thể. Điểm mạnh: không cần tương tác nhiều bước, không có vấn đề “last-revealer”. Nhưng nó phụ thuộc vào một oracle tập trung. Nếu oracle bị tấn công hoặc thông đồng với validator, kết quả có thể bị thao túng. Các dự án thường lai ghép VRF với RANDAO để giảm rủi ro, nhưng độ phức tạp tăng lên.

3. Commit-Reveal – Đơn giản nhưng tốn gas

Đây là cơ chế thủ công nhất: người dùng gửi hash của một số, sau đó tiết lộ số đó. Hợp đồng kiểm tra hash và sử dụng số để tạo ngẫu nhiên. Nó an toàn nếu có đủ người tham gia và không ai có thể “nhìn” vào số của người khác trước khi tiết lộ. Nhưng nó yêu cầu hai giao dịch, tốn gas, và dễ bị tấn công bởi người dùng cuối cùng. Tôi từng audit một dự án lottery dùng commit-reveal với 100 người tham gia; người cuối cùng có thể tính toán kết quả và quyết định không tiết lộ nếu không trúng. Đó là lỗi logic kinh điển.

Bài báo của Crypto Briefing không đi vào ba cơ chế này. Thay vào đó, nó nói chung chung về “phương pháp mật mã”. Điều này, theo tôi, là một thiếu sót có chủ đích do tính chất phổ thông của bài viết. Nhưng với một developer, điều này có thể dẫn đến hiểu lầm rằng “chỉ cần dùng VRF là an toàn”. Sai lầm. An toàn phụ thuộc vào cách bạn kết hợp entropy, cách bạn xử lý trường hợp oracle không phản hồi, và cách bạn thiết kế các hàm băm.


Contrarian: Khi bài báo phổ thông trở thành 'kiến thức nguy hiểm'

Tôi muốn đưa ra một góc nhìn phản trực giác: bài báo này, mặc dù đúng về mặt lý thuyết, có thể gây hại cho những người mới bắt đầu nếu họ coi nó là kim chỉ nam kỹ thuật. Lý do: nó tạo ra ảo tưởng rằng vấn đề đã được giải quyết. Trên thực tế, các cuộc tấn công liên quan đến tính ngẫu nhiên vẫn tiếp diễn. Năm 2022, tôi phân tích sự sụp đổ của Terra và phát hiện rằng cơ chế ổn định UST dựa hoàn toàn vào oracle tập trung. Nếu bài báo đó được viết cho Terra, nó có thể nói rằng “Terra sử dụng phương pháp mật mã để tạo ra tính ngẫu nhiên” – nhưng thực tế, oracle tập trung là điểm chết người.

Điểm mù thứ hai: tính ngẫu nhiên không chỉ là vấn đề kỹ thuật, mà còn là vấn đề kinh tế. Ngay cả khi bạn có VRF an toàn, nếu phần thưởng đủ lớn, validator hoặc oracle có thể chấp nhận rủi ro bị phạt để thao túng kết quả. Các mô hình kinh tế của giao thức cần được thiết kế sao cho chi phí gian lận lớn hơn lợi ích. Bài báo không đề cập đến điều này.

Điểm mù thứ ba: bài báo không cảnh báo về sự phức tạp trong triển khai. Tôi từng thấy một dự án sử dụng Chainlink VRF nhưng quên kiểm tra xem oracle có trả về cùng một số cho hai yêu cầu khác nhau hay không. Kết quả: người dùng có thể dự đoán được kết quả mint. Đây là lỗi do developer không hiểu rõ API của VRF, chứ không phải do bản thân VRF.


Takeaway: Dự báo lỗ hổng và lời khuyên cho developer

Trong 5 năm tới, tôi dự đoán rằng các lỗ hổng liên quan đến tính ngẫu nhiên sẽ chuyển từ giai đoạn “dùng sai nguồn entropy” sang giai đoạn “tấn công vào tầng middleware”. Cụ thể, khi nhiều dự án chuyển sang dùng RANDAO từ Beacon Chain, kẻ tấn công có thể tập trung vào việc thao túng quá trình đồng thuận ở cấp độ validator. Điều này đã được thảo luận trong cộng đồng Ethereum, nhưng vẫn chưa có giải pháp hoàn chỉnh.

Lời khuyên của tôi: đừng bao giờ chỉ dựa vào một bài báo phổ thông để thiết kế hệ thống ngẫu nhiên. Hãy đọc tài liệu gốc của Ethereum, của Chainlink, và đặc biệt là các báo cáo audit của những dự án đã từng thất bại. Trong quá trình audit cho Aave năm 2020, tôi đã phát triển một bộ tiêu chí đánh giá rủi ro cho các giao thức DeFi, và tôi luôn dành 30% thời gian để kiểm tra cơ chế ngẫu nhiên, dù nó có vẻ đơn giản.

Bài báo của Crypto Briefing là một bước khởi đầu tốt, nhưng nó thiếu chiều sâu. Hãy coi nó như một tấm bản đồ thô, và bạn cần tự điền vào những chi tiết kỹ thuật. Nếu không, bạn sẽ là người tiếp theo mất hàng triệu USD vì một dòng code block.timestamp.

Deposit xong rồi, rủi ro mới bắt đầu.