Alpha Web3 & AI
Trang chủ › Phát Triển Web3

Bảo mật Smart Contract: Những lỗ hổng phổ biến cần tránh

Ban biên tập Alpha Web3 & AI · · Cập nhật
Bảo mật Smart Contract: Những lỗ hổng phổ biến cần tránh

Smart contract một khi đã triển khai lên blockchain thường không thể sửa, và nó trực tiếp nắm giữ tài sản có giá trị, nên một lỗi nhỏ có thể dẫn đến mất tiền không thể đảo ngược. Những lỗ hổng phổ biến nhất gồm reentrancy, lỗi kiểm soát truy cập, thao túng giá từ oracle, xử lý sai giá trị trả về và các vấn đề liên quan đến thứ tự giao dịch. Bài viết giải thích từng loại ở mức khái niệm và cách phòng tránh từ góc nhìn của người viết và người kiểm tra hợp đồng.

Vì sao bảo mật smart contract khác phần mềm thông thường

Với ứng dụng web, bạn phát hiện lỗi, vá và triển khai lại trong vài giờ. Smart contract trên Ethereum và các chuỗi tương thích EVM có những đặc điểm khiến bảo mật trở nên khắt khe hơn:

  • Bất biến: mã đã triển khai không sửa được, trừ khi được thiết kế sẵn cơ chế nâng cấp, và chính cơ chế nâng cấp cũng là một bề mặt rủi ro.
  • Công khai: bytecode, và thường cả mã nguồn đã xác minh, ai cũng đọc được. Kẻ tấn công có thời gian phân tích không giới hạn.
  • Giữ tài sản trực tiếp: hợp đồng không chỉ xử lý dữ liệu mà nắm giữ token, tiền mã hóa.
  • Giao dịch không đảo ngược: không có ngân hàng để hoàn tiền khi bị tấn công.
  • Kết hợp tùy ý: hợp đồng của bạn có thể bị gọi bởi bất kỳ hợp đồng nào khác, kể cả hợp đồng độc hại được viết riêng để khai thác.

Các nhóm lỗ hổng phổ biến

1. Reentrancy (gọi lại)

Reentrancy xảy ra khi hợp đồng gọi ra bên ngoài, ví dụ gửi ETH cho người dùng, trước khi cập nhật trạng thái nội bộ. Nếu bên nhận là một hợp đồng, nó có thể gọi ngược vào hàm ban đầu trong khi số dư chưa được trừ, lặp lại việc rút tiền. Sự cố The DAO năm 2016, dẫn đến việc Ethereum hard fork và tách ra Ethereum Classic, là ví dụ nổi tiếng nhất của loại lỗi này.

Phòng tránh: tuân thủ mẫu Checks-Effects-Interactions: kiểm tra điều kiện, cập nhật trạng thái, rồi mới tương tác bên ngoài. Bổ sung khóa chống gọi lại như ReentrancyGuard của OpenZeppelin cho các hàm nhạy cảm. Lưu ý reentrancy có thể xảy ra giữa nhiều hàm hoặc nhiều hợp đồng, không chỉ trong một hàm.

2. Lỗi kiểm soát truy cập

Hàm quản trị như rút tiền, đổi chủ sở hữu, đúc token mới quên giới hạn quyền, hoặc hàm khởi tạo có thể bị gọi lại bởi bất kỳ ai. Đây là nhóm lỗi đơn giản nhưng gây thiệt hại lớn.

Phòng tránh: dùng thư viện đã được kiểm chứng như Ownable hoặc AccessControl; rà soát kỹ mọi hàm public và external; với hợp đồng nâng cấp được, đảm bảo hàm initialize chỉ chạy một lần. Quyền quản trị nên nằm trong ví đa chữ ký kèm timelock thay vì một khóa riêng duy nhất.

3. Thao túng oracle và giá

Nhiều giao thức DeFi cần biết giá tài sản. Nếu hợp đồng đọc giá trực tiếp từ một pool trên sàn phi tập trung tại thời điểm giao dịch, kẻ tấn công có thể dùng flash loan, khoản vay không thế chấp phải trả trong cùng giao dịch, để làm lệch giá tạm thời, rồi khai thác giá sai đó.

Phòng tránh: dùng oracle phi tập trung tổng hợp nhiều nguồn, giá trung bình theo thời gian (TWAP), kiểm tra độ lệch và độ mới của dữ liệu giá. Hiểu rõ cơ chế này rất quan trọng nếu bạn tham gia các giao thức được mô tả trong bài tài chính phi tập trung DeFi.

4. Lỗi số học và độ chính xác

Trước Solidity 0.8, phép cộng trừ có thể tràn số mà không báo lỗi. Từ phiên bản 0.8, trình biên dịch tự kiểm tra tràn số, nhưng khối unchecked và lỗi làm tròn vẫn là nguồn rủi ro. Chia trước nhân sau làm mất độ chính xác; làm tròn có lợi cho người dùng thay vì cho giao thức có thể bị khai thác lặp lại.

5. Không kiểm tra giá trị trả về và gọi cấp thấp

Một số token ERC-20 cũ không trả về giá trị boolean theo chuẩn. Lời gọi cấp thấp như call trả về trạng thái thành công mà nếu bỏ qua, hợp đồng tưởng giao dịch đã thành công. Dùng thư viện SafeERC20 và luôn kiểm tra kết quả.

6. Front-running và MEV

Giao dịch chờ trong mempool là công khai. Người khác có thể thấy giao dịch của bạn và chèn giao dịch của họ trước hoặc sau để hưởng lợi, ví dụ tấn công "sandwich" vào lệnh hoán đổi trên sàn phi tập trung. Phòng tránh: cho phép người dùng đặt mức trượt giá tối đa và hạn chót giao dịch; dùng cơ chế commit-reveal cho thao tác cần giữ bí mật.

7. Nguồn ngẫu nhiên yếu

Dùng dấu thời gian khối hay hash khối làm số ngẫu nhiên có thể bị dự đoán hoặc ảnh hưởng. Với xổ số, trò chơi hay phân phối NFT ngẫu nhiên, cần nguồn ngẫu nhiên có thể kiểm chứng (VRF) từ oracle.

8. Từ chối dịch vụ

Vòng lặp qua mảng không giới hạn có thể vượt giới hạn gas khi dữ liệu lớn dần, khiến hàm không bao giờ chạy được. Mẫu "đẩy" tiền tới nhiều người trong một giao dịch có thể bị chặn nếu một bên nhận cố tình từ chối. Ưu tiên mẫu "kéo": người dùng tự rút phần của mình.

Bảng tóm tắt lỗ hổng và biện pháp

Lỗ hổngBiện pháp chính
ReentrancyChecks-Effects-Interactions, khóa chống gọi lại
Kiểm soát truy cậpThư viện phân quyền chuẩn, đa chữ ký, timelock
Thao túng oracleOracle phi tập trung, TWAP, kiểm tra độ lệch
Số họcSolidity 0.8+, thận trọng với unchecked, thứ tự phép tính
Front-runningGiới hạn trượt giá, hạn chót, commit-reveal
Ngẫu nhiên yếuVRF từ oracle
Từ chối dịch vụTránh vòng lặp không giới hạn, mẫu rút tiền kéo

Danh sách SWC Registry và các tài liệu của cộng đồng như Smart Contract Security Verification Standard là nguồn tham khảo hữu ích để rà soát đầy đủ hơn.

Quy trình phát triển an toàn

  1. Thiết kế đơn giản: mỗi dòng mã thêm vào là thêm bề mặt tấn công. Tách logic phức tạp, giới hạn đặc quyền.
  2. Dùng thư viện đã kiểm chứng: OpenZeppelin Contracts cho token, phân quyền, nâng cấp thay vì tự viết.
  3. Kiểm thử kỹ: unit test cho mọi nhánh, fuzz testing và kiểm thử bất biến với Foundry hoặc Echidna để tìm trường hợp biên mà con người không nghĩ ra.
  4. Phân tích tĩnh: chạy Slither hoặc công cụ tương tự trong pipeline.
  5. Kiểm toán độc lập: thuê đơn vị kiểm toán có uy tín trước khi triển khai hợp đồng giữ giá trị lớn; kiểm toán giảm rủi ro chứ không đảm bảo tuyệt đối.
  6. Bug bounty: khuyến khích người tìm lỗi báo cáo có trách nhiệm thay vì khai thác.
  7. Giám sát sau triển khai: theo dõi giao dịch bất thường, có cơ chế tạm dừng khẩn cấp với quy trình rõ ràng.

Nếu bạn đang học viết hợp đồng, hãy áp dụng những nguyên tắc này ngay từ bài tập đầu tiên trong hướng dẫn lập trình smart contract thực hành.

Khi sự cố đã xảy ra

Ngay cả hợp đồng được kiểm toán vẫn có thể bị khai thác. Đội phát triển cần chuẩn bị trước kịch bản ứng phó: ai có quyền kích hoạt tạm dừng, cách liên lạc với sàn giao dịch và cộng đồng, cách thu thập bằng chứng trên chuỗi. Nguyên tắc chung của quy trình phục hồi sau sự cố tấn công như khoanh vùng, điều tra nguyên nhân, khôi phục và rút kinh nghiệm vẫn áp dụng, dù bối cảnh blockchain có những giới hạn riêng như không thể hoàn tác giao dịch.

Lời khuyên cho người dùng

Người dùng không viết mã cũng nên biết rằng một giao thức có báo cáo kiểm toán chưa chắc đã an toàn tuyệt đối. Kiểm tra quyền quản trị nằm ở đâu, có timelock không, hợp đồng đã hoạt động bao lâu, và chỉ đưa vào số tài sản bạn chấp nhận mất. Thu hồi quyền chi tiêu token (approval) không còn dùng là thói quen bảo vệ đơn giản.

Câu hỏi thường gặp

Kiểm toán smart contract có đảm bảo hợp đồng an toàn không?

Không. Kiểm toán giảm đáng kể rủi ro nhưng chỉ đánh giá phiên bản mã tại thời điểm kiểm tra trong phạm vi nhất định. Nhiều vụ khai thác xảy ra với hợp đồng đã được kiểm toán, thường do thay đổi sau kiểm toán hoặc tương tác với giao thức khác.

Hợp đồng nâng cấp được có an toàn hơn không?

Nó cho phép vá lỗi, nhưng tạo thêm rủi ro: người nắm quyền nâng cấp có thể thay đổi logic, và cơ chế proxy có những lỗi riêng như xung đột vùng lưu trữ. Nên kết hợp đa chữ ký và timelock để người dùng có thời gian phản ứng trước khi thay đổi có hiệu lực.

Người mới nên học bảo mật smart contract bắt đầu từ đâu?

Nắm vững Solidity và EVM trước, sau đó đọc tài liệu bảo mật của OpenZeppelin, làm các bộ bài tập thực hành dạng thử thách như Ethernaut, và đọc báo cáo kiểm toán công khai để hiểu cách chuyên gia phân tích mã.

Flash loan có phải là lỗ hổng không?

Flash loan bản thân là một tính năng hợp lệ. Nó trở thành công cụ tấn công khi giao thức khác có lỗ hổng như đọc giá dễ bị thao túng, vì flash loan cho phép kẻ tấn công huy động vốn lớn trong một giao dịch mà không cần sở hữu tài sản.

Bài liên quan