Phân tích lỗ hổng biên dịch Solidity: Tác động, trường hợp và chiến lược đối phó

Phân tích lỗ hổng trình biên dịch Solidity và các chiến lược ứng phó

Trình biên dịch là một trong những thành phần cốt lõi của hệ thống máy tính hiện đại. Nó chuyển đổi ngôn ngữ lập trình cấp cao dễ hiểu cho con người thành các lệnh cấp thấp có thể thực thi bởi máy tính. Mặc dù các nhà phát triển và chuyên gia an ninh thường quan tâm đến tính bảo mật của mã ứng dụng, nhưng vấn đề an ninh của chính trình biên dịch cũng không thể bị bỏ qua. Lỗ hổng trong trình biên dịch có thể gây ra nguy cơ an ninh nghiêm trọng trong một số trường hợp.

Lấy trình duyệt làm ví dụ, khi phân tích và thực thi mã JavaScript, lỗ hổng trong engine JavaScript có thể dẫn đến việc người dùng bị tấn công thực thi mã từ xa khi truy cập vào trang web độc hại, cuối cùng khiến kẻ tấn công kiểm soát trình duyệt của nạn nhân thậm chí cả hệ điều hành. Ngoài ra, lỗi trong trình biên dịch C++ cũng có thể gây ra những hậu quả nghiêm trọng như thực thi mã từ xa.

Trình biên dịch Solidity cũng không phải là ngoại lệ, có nhiều phiên bản đều tồn tại lỗ hổng bảo mật. Chức năng của trình biên dịch Solidity là chuyển đổi mã hợp đồng thông minh thành mã bytecode EVM( của máy ảo Ethereum), những mã này cuối cùng sẽ được thực thi trong EVM. Cần lưu ý rằng, lỗ hổng của trình biên dịch Solidity khác với lỗ hổng của chính EVM. Lỗ hổng EVM chỉ ra các vấn đề bảo mật khi máy ảo thực thi các lệnh, có thể ảnh hưởng đến toàn bộ mạng Ethereum. Còn lỗ hổng của trình biên dịch Solidity là các vấn đề phát sinh khi chuyển đổi Solidity thành mã EVM.

Một trong những nguy cơ của lỗ hổng trình biên dịch Solidity là mã EVM được tạo ra có thể không khớp với mong đợi của nhà phát triển. Vì hợp đồng thông minh thường liên quan đến tài sản tiền điện tử của người dùng, nên bất kỳ lỗi nào do trình biên dịch gây ra đều có thể dẫn đến mất mát tài sản của người dùng, hậu quả rất nghiêm trọng. Các nhà phát triển và kiểm toán viên thường tập trung vào việc thực hiện logic hợp đồng và các lỗ hổng phổ biến, trong khi lỗ hổng trình biên dịch cần được phân tích kết hợp với phiên bản cụ thể và mô hình mã.

Dưới đây là một số ví dụ thực tế để trình bày các hình thức, nguyên nhân và tác hại cụ thể của lỗ hổng trình biên dịch Solidity.

Phân tích lỗ hổng trình biên dịch Solidity và biện pháp đối phó

SOL-2016-9 HighOrderByteCleanStorage

Lỗ hổng này tồn tại trong các phiên bản trước của trình biên dịch Solidity (>=0.1.6 <0.4.4).

Xem xét mã sau:

độ vững hợp đồng C { uint32 a = 0x12345678; uint32 b = 0; hàm f() công cộng { a = a + 1; } function run() public view returns (uint32) { return b; } }

Biến b không bị thay đổi, hàm run() lẽ ra phải trả về giá trị mặc định là 0. Nhưng trong mã được tạo bởi trình biên dịch phiên bản lỗi, run() sẽ trả về 1.

Sự không nhất quán này rất khó phát hiện qua việc kiểm tra mã đơn giản. Mặc dù mã mẫu có ảnh hưởng hạn chế, nhưng nếu biến b được sử dụng cho xác thực quyền hoặc ghi chép tài sản, hậu quả sẽ rất nghiêm trọng.

Nguyên nhân gây ra vấn đề này là do EVM sử dụng các phần tử ngăn xếp kích thước 32 byte, trong khi mỗi slot trong storage cũng có kích thước 32 byte. Solidity hỗ trợ các kiểu dữ liệu nhỏ hơn 32 byte như uint32, và trình biên dịch cần phải xóa các bit cao khi xử lý các kiểu này để đảm bảo tính chính xác của dữ liệu. Trong trường hợp này, sau khi tràn số trong phép cộng, trình biên dịch không xóa đúng các bit cao của kết quả, dẫn đến 1 bit bị tràn được ghi vào storage, ghi đè lên biến b.

SOL-2022-4 Tác động bên cạnh bộ nhớ InlineAssembly

Lỗ hổng này tồn tại trong các phiên bản biên dịch từ 0.8.13 đến 0.8.15. Xem xét mã sau:

solid hợp đồng C { function f() public pure returns (uint) { lắp ráp { mstore(0, 0x42) } uint x; lắp ráp { x := mload(0) } trả về x; } }

Trình biên dịch Solidity sẽ thực hiện phân tích luồng điều khiển và dữ liệu sâu sắc trong quá trình tối ưu hóa để giảm kích thước mã nguồn và tối ưu hóa tiêu thụ gas. Mặc dù việc tối ưu hóa này rất phổ biến, nhưng do tình huống phức tạp, nó dễ dàng gây ra lỗi hoặc lỗ hổng bảo mật.

Vấn đề của đoạn mã trên xuất phát từ loại tối ưu hóa này. Trình biên dịch cho rằng nếu một chức năng sửa đổi dữ liệu tại vị trí bộ nhớ 0, nhưng không sử dụng dữ liệu đó sau đó, thì có thể loại bỏ lệnh sửa đổi để tiết kiệm gas. Tuy nhiên, loại tối ưu hóa này chỉ được áp dụng trong một khối assembly đơn lẻ.

Trong ví dụ này, việc ghi và truy cập vào bộ nhớ 0 diễn ra trong hai khối assembly khác nhau. Trình biên dịch chỉ phân tích các khối assembly riêng lẻ, cho rằng việc ghi trong khối đầu tiên là dư thừa, do đó đã loại bỏ nó, gây ra lỗi. Trong phiên bản có lỗ hổng, hàm f() sẽ trả về 0, trong khi giá trị trả về đúng phải là 0x42.

Phân tích lỗ hổng trình biên dịch Solidity và các biện pháp đối phó

SOL-2022-6 AbiReencodingHeadOverflowWithStaticArrayCleanup

Lỗ hổng này ảnh hưởng đến các phiên bản biên dịch từ 0.5.8 đến 0.8.16. Xem xét mã sau:

solidity hợp đồng C { function f(string) calldata a( external pure returns [1]string memory) { return abi.decode(abi.encode)a(, (string)([1]); } }

Trong trường hợp bình thường, mã này nên trả về giá trị của biến a là "aaaa". Nhưng trong phiên bản có lỗ hổng, nó sẽ trả về chuỗi rỗng "".

Vấn đề là khi Solidity thực hiện thao tác abi.encode trên mảng kiểu calldata, nó đã sai lầm trong việc dọn dẹp một số dữ liệu, dẫn đến việc thay đổi dữ liệu liền kề, gây ra sự không nhất quán giữa dữ liệu đã mã hóa và giải mã.

Cần lưu ý rằng, khi thực hiện gọi bên ngoài và phát sự kiện, Solidity sẽ ngầm định mã hóa tham số bằng abi.encode, vì vậy phạm vi ảnh hưởng của lỗ hổng này có thể lớn hơn dự kiến.

Đề xuất an toàn

Dựa trên phân tích lỗ hổng của trình biên dịch Solidity, đề xuất các khuyến nghị sau cho các nhà phát triển và nhân viên an ninh:

Dành cho các nhà phát triển:

  • Sử dụng phiên bản biên dịch Solidity mới hơn. Phiên bản mới có thể gây ra một số vấn đề mới, nhưng thường ít có các vấn đề bảo mật đã biết.
  • Hoàn thiện kiểm tra đơn vị. Hầu hết các lỗi ở cấp trình biên dịch sẽ dẫn đến kết quả thực thi không phù hợp với mong đợi, những vấn đề này rất khó phát hiện qua việc xem xét mã, nhưng dễ dàng bị lộ ra trong các bài kiểm tra. Tăng cường độ phủ sóng mã có thể tối đa hóa việc tránh các vấn đề như vậy.
  • Tránh sử dụng lắp ráp nội tuyến, mã hóa và giải mã abi phức tạp, không mù quáng sử dụng các tính năng mới và các chức năng thử nghiệm. Hầu hết các lỗ hổng lịch sử liên quan đến những thao tác phức tạp này.

Đối với nhân viên an ninh:

  • Trong quá trình kiểm toán, không được bỏ qua những rủi ro an ninh có thể do trình biên dịch gây ra. Mục kiểm tra tương ứng trong Smart Contract Weakness Classification)SWC[0] là SWC-102: Phiên bản trình biên dịch lỗi thời.
  • Trong quy trình phát triển SDL, thúc giục nhóm phát triển nâng cấp phiên bản biên dịch, xem xét việc đưa vào kiểm tra tự động phiên bản biên dịch trong CI/CD.
  • Không cần quá lo lắng về lỗ hổng của trình biên dịch. Hầu hết các lỗ hổng chỉ được kích hoạt trong các kiểu mã cụ thể, việc sử dụng hợp đồng được biên dịch bằng phiên bản có lỗ hổng không nhất thiết phải tồn tại rủi ro, cần đánh giá dựa trên tình huống cụ thể.

Một số tài nguyên hữu ích:

  • Cảnh báo an ninh do đội ngũ Solidity phát hành định kỳ
  • Danh sách lỗi được cập nhật định kỳ từ kho chính thức của Solidity
  • Danh sách lỗi biên dịch viên các phiên bản, có thể được sử dụng để kiểm tra tự động trong CI/CD
  • Biểu tượng cảnh báo ở góc trên bên phải trang mã hợp đồng Etherscan có thể cho biết các lỗ hổng bảo mật hiện có trong phiên bản biên dịch.

Phân tích lỗ hổng trình biên dịch Solidity và biện pháp ứng phó

Tóm tắt

Bài viết này giới thiệu khái niệm về lỗ hổng của trình biên dịch Solidity, phân tích các rủi ro an ninh có thể phát sinh trong phát triển Ethereum, và cung cấp các lời khuyên an ninh thiết thực cho các nhà phát triển và nhân viên an ninh. Mặc dù lỗ hổng của trình biên dịch không phổ biến, nhưng chúng có ảnh hưởng sâu rộng, xứng đáng được các đội ngũ phát triển và an ninh chú trọng.

ETH2.56%
SOL4.62%
Xem bản gốc
Trang này có thể chứa nội dung của bên thứ ba, được cung cấp chỉ nhằm mục đích thông tin (không phải là tuyên bố/bảo đảm) và không được coi là sự chứng thực cho quan điểm của Gate hoặc là lời khuyên về tài chính hoặc chuyên môn. Xem Tuyên bố từ chối trách nhiệm để biết chi tiết.
  • Phần thưởng
  • 5
  • Chia sẻ
Bình luận
0/400
0xInsomniavip
· 07-24 15:11
Lỗ hổng ở tầng dưới, tầng trên không cứu nữa.
Xem bản gốcTrả lời0
0xSunnyDayvip
· 07-24 06:35
Ai còn dám nói rằng trình biên dịch an toàn?
Xem bản gốcTrả lời0
BankruptcyArtistvip
· 07-24 06:29
Mỗi ngày đều tìm kiếm lỗ hổng, mỗi ngày đều trong tình trạng phá sản.
Xem bản gốcTrả lời0
bridge_anxietyvip
· 07-24 06:23
Hệ số độ khó khai thác lỗ hổng tăng vọt.
Xem bản gốcTrả lời0
TokenDustCollectorvip
· 07-24 06:13
Lỗ hổng bảo mật là khởi đầu cho việc đồ ngốc mất tiền.
Xem bản gốcTrả lời0
  • Ghim
Giao dịch tiền điện tử mọi lúc mọi nơi
qrCode
Quét để tải xuống ứng dụng Gate
Cộng đồng
Tiếng Việt
  • 简体中文
  • English
  • Tiếng Việt
  • 繁體中文
  • Español
  • Русский
  • Français (Afrique)
  • Português (Portugal)
  • Bahasa Indonesia
  • 日本語
  • بالعربية
  • Українська
  • Português (Brasil)