BTC
ETH
HTX
SOL
BNB
Xem thị trường
简中
繁中
English
日本語
한국어
ภาษาไทย
Tiếng Việt

Hiểu biết sâu sắc về các lỗ hổng tấn công reentrancy

Bài viết này có khoảng 3101 từ, đọc toàn bộ bài viết mất khoảng 5 phút
Bắt đầu từ bốn khía cạnh của phương thức truyền, chức năng dự phòng, mã lỗ hổng và phân tích mã nguồn, phân tích chuyên sâu về nguyên nhân của cuộc tấn công vào lại và giải thích chi tiết về
Tóm tắt AI
Bắt đầu từ bốn khía cạnh của phương thức truyền, chức năng dự phòng, mã lỗ hổng và phân tích mã nguồn, phân tích chuyên sâu về nguyên nhân của cuộc tấn công vào lại và giải thích chi tiết về

lời tựa

lời tựa

Khái niệm hợp đồng thông minh (tiếng Anh: Smart contract) lần đầu tiên được đề xuất bởi Nick Szabo vào năm 1995. Nó là một giao thức máy tính được thiết kế để phổ biến, xác minh hoặc thực hiện hợp đồng theo cách thức giao dịch tin cậy, có thể theo dõi và không thể đảo ngược. Tuy nhiên, hợp đồng thông minh không an toàn.Lỗ hổng tấn công Re-Entrance là một trong những phương thức tấn công trong Ethereum.Ngay từ năm 2016, sự cố DAO đã gây ra một đợt hard fork của Ethereum.

tiêu đề cấp đầu tiên

tổng quan về lỗ hổng

  • Trong Ethereum, hợp đồng thông minh có thể gọi mã của các hợp đồng bên ngoài khác.Vì hợp đồng thông minh có thể gọi hợp đồng bên ngoài hoặc gửi Ether, các hoạt động này yêu cầu hợp đồng gửi lệnh gọi bên ngoài, vì vậy kẻ tấn công có thể sử dụng các lệnh gọi bên ngoài này để gây ra các cuộc tấn công. hợp đồng được thực hiện lại ở bất kỳ vị trí nào, bỏ qua các hạn chế trong mã gốc, do đó xảy ra các cuộc tấn công vào lại. Các cuộc tấn công vào lại về cơ bản tương tự như các cuộc gọi đệ quy trong lập trình, vì vậy chúng có thể xảy ra khi một hợp đồng gửi ether đến một địa chỉ không xác định.

  • Nói một cách đơn giản, có hai điều kiện để xảy ra lỗ hổng tấn công vào lại:

Hợp đồng bên ngoài được gọi và hợp đồng không an toàn

Một ví dụ về đoạn mã đơn giản được đưa ra dưới đây:

Đoạn mã trên là thao tác rút tiền đơn giản nhất, tiếp theo chúng ta sẽ phân tích chi tiết nguyên nhân của cuộc tấn công vào lại.

tiêu đề cấp đầu tiên

phân tích lỗ hổng

Trước khi chính thức phân tích các cuộc tấn công vào lại, hãy giới thiệu một số kiến ​​thức chính.

.transfer(),01 Phương thức chuyển khoảnVì cuộc tấn công vào lại sẽ được gửi trong quá trình chuyển, nên phương thức chuyển thường được sử dụng trong Solidity là
  • .gửi() và
  • .gas().call.vale()(), ba phương thức truyền được mô tả bên dưới:
  • .transfer(): Chỉ 2300 gas sẽ được gửi cho cuộc gọi. Khi chuyển không thành công, ném sẽ được sử dụng để thực hiện thao tác khôi phục, do đó ngăn chặn các cuộc tấn công vào lại.

.send(): Chỉ 2300 gas sẽ được gửi để gọi và giá trị Boolean false sẽ được trả về khi gửi không thành công, do đó ngăn chặn các cuộc tấn công vào lại.

Không có chức năng nào phù hợp khi gọi hợp đồng;
Hàm dự phòng: Hàm dự phòng là một và chỉ một hàm không có tên trong mỗi hợp đồng và hàm này không có tham số và không có giá trị trả về, như minh họa bên dưới:

Hàm dự phòng được thực thi trong các trường hợp sau:

  • Không có chức năng nào phù hợp khi gọi hợp đồng;

  • Không có dữ liệu nào được truyền đi;

  • Hợp đồng thông minh nhận ether (để chấp nhận ether, chức năng dự phòng phải được đánh dấu là phải trả).

Không có dữ liệu nào được truyền đi;

Hợp đồng thông minh nhận ether (để chấp nhận ether, chức năng dự phòng phải được đánh dấu là phải trả).

03 Mã lỗ hổng

Đoạn mã sau có một cuộc tấn công vào lại. Nó thực hiện một hợp đồng tương tự như ví công khai. Tất cả người dùng có thể sử dụng Deposit() để gửi vào hợp đồng Reentrance hoặc sử dụng rút tiền() để rút khỏi hợp đồng Reentrance. Tất nhiên, mọi người cũng có thể sử dụng balanceof() để truy vấn số dư của chính họ hoặc của những người khác trong hợp đồng.

Trước tiên, hãy sử dụng tài khoản (0x5B38Da6a701c568545dCfcB03FcB875f56beddC4) để đóng vai nạn nhân và nhấp vào nút Triển khai để triển khai hợp đồng trong Remix IDE.

Sau khi triển khai thành công hợp đồng, hãy điền số 5 vào hộp cài đặt GIÁ TRỊ, thay đổi đơn vị thành ether và nhấp vào gửi tiền để gửi 5 ether.

Nhấp vào ví để xem số dư của hợp đồng và thấy rằng số dư là 5 ether, cho biết rằng khoản tiền gửi của chúng tôi đã thành công.

Đoạn mã sau là một cuộc tấn công chống lại hợp đồng dễ bị tấn công ở trên:

Sử dụng một tài khoản khác (0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2) để đóng vai kẻ tấn công, sao chép địa chỉ hợp đồng dễ bị tấn công vào hộp Cài đặt triển khai và nhấp vào Triển khai để triển khai hợp đồng tấn công ở trên.

Sau khi triển khai thành công, trước tiên hãy gọi hàm wallet() để kiểm tra xem số dư của hợp đồng tấn công có bằng 0 không.

Gọi lại chức năng ví của hợp đồng để kiểm tra số dư của hợp đồng dễ bị tổn thương và thấy rằng nó đã trở thành 6 ether.

Kẻ tấn công (0xAb8483F64d9C6d1EcF9b849Ae677dD3315835cb2) gọi chức năng tấn công của hợp đồng tấn công để mô phỏng cuộc tấn công, sau đó gọi chức năng ví của hợp đồng bị tấn công để kiểm tra số dư của hợp đồng và thấy rằng nó đã trở về 0. Lúc này, hãy đi quay lại hợp đồng tấn công để kiểm tra số dư và thấy rằng 6 ether trong hợp đồng bị tấn công Tất cả tiền đã được rút vào hợp đồng của kẻ tấn công, điều này gây ra một cuộc tấn công vào lại.

04 Phân tích mã nguồn

tiêu đề cấp đầu tiên

Các trường hợp liên quan

chữ

Vào ngày 17 tháng 6 năm 2016, dự án TheDAO đã bị tấn công vào lại, dẫn đến hơn 3 triệu Ethereum bị tách khỏi nhóm tài sản TheDAO và kẻ tấn công đã sử dụng chức năng splitDAO() trong hợp đồng thông minh TheDAO để tái sử dụng Tài sản DAO của chính mình để thực hiện lại các cuộc tấn công vào, liên tục tách tài sản DAO khỏi nhóm tài sản của dự án TheDAO và chuyển chúng vào tài khoản của chính họ.

Mã sau đây là một phần của hàm splitDAO(), có mã nguồn nằm trong TokenCreation.sol, chuyển mã thông báo từ DAO gốc sang DAO con. Mảng số dư uint fundToBeMoved = (balances[msg.sender] * p.splitData[0].splitBalance) / p.splitData[0].totalSupply xác định số lượng mã thông báo sẽ được di chuyển.

payOut[_account] += bonus Biến trạng thái được cập nhật được đặt sau lệnh gọi hàm payOut trong mã sự cố.

Thực hiện lệnh gọi .call.value tới _recipient, chuyển _amount Wei và lệnh gọi .call.value sẽ sử dụng tất cả gas còn lại hiện tại theo mặc định.

Giải pháp

Qua những phân tích về tấn công vào lại ở trên, chúng ta có thể thấy rằng điểm mấu chốt của lỗ hổng tấn công vào lại là việc sử dụng các chức năng như dự phòng để gọi lại chính nó để gây ra các cuộc gọi đệ quy để thực hiện các hoạt động chuyển vòng, do đó, có các giải pháp sau đến lỗ hổng tấn công reentrancy.

tiêu đề phụ

01 Sử dụng các chức năng truyền tải khác

Sử dụng chức năng transfer() tích hợp của Solidity khi gửi chuyển Ethereum đến các địa chỉ bên ngoài, vì transfer() sẽ chỉ gửi 2300 gas để gọi, sẽ không đủ để gọi một hợp đồng khác, hãy sử dụng transfer() để viết lại bản gốc Rút tiền ( ) của hợp đồng như sau:

02 Sửa biến trạng thái trước

Phương pháp này nhằm đảm bảo rằng việc sửa đổi biến trạng thái diễn ra sớm hơn thao tác chuyển, nghĩa là chế độ kiểm tra-hiệu ứng-tương tác (kiểm tra-hiệu ứng-tương tác) được Solidity chính thức khuyến nghị.

03 Sử dụng một mutex

Có một hợp đồng bảo mật dành riêng cho các cuộc tấn công vào lại trong thư viện OpenZeppelin chính thức:

https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/security/ReentrancyGuard.sol

người giới thiệu

tiêu đề cấp đầu tiên
https://zhuanlan.zhihu.com/p/111446792
người giới thiệu
https://blog.csdn.net/henrynote/article/details/82119116
1. Một số hard fork của Ethereum:
https://blog.csdn.net/Flyhps/article/details/83095036


ETH
Sự an toàn
hợp đồng thông minh
Chào mừng tham gia cộng đồng chính thức của Odaily
Nhóm đăng ký:
https://t.me/Odaily_News
Nhóm trò chuyện:
https://t.me/Odaily_GoldenApe
Tài khoản chính thức:
https://twitter.com/OdailyChina