Vào lại chuỗi chéo
Nhiều hợp đồng với các phiên bản khác nhau phải được xem xét đồng thời trong bảo mật chuỗi chéo, mô hình này đưa ra những thách thức khái niệm mới. Những gì chúng tôi có thể coi là an toàn trong một chuỗi có thể là một vi phạm bảo mật nghiêm trọng trong giao thức chuỗi chéo. Một số ví dụ cổ điển là chữ ký và tấn công phát lại.
Trong bài đăng này, chúng tôi sẽ xem xét một vectơ tấn công được tìm thấy trong một trong các cuộc kiểm toán của chúng tôi có thể bị khai thác trong cài đặt chuỗi chéo chuyển thông điệp. Cuộc tấn công đã được tìm thấy bằng cách xem xét thủ công và nó đã được thử nghiệm.
nội dung:
- Xây dựng hợp đồng NFT chuỗi chéo
- trừu tượng cầu
- thư viện an toàn
- Khai thác cuộc gọi bên ngoài không an toàn
- Ví dụ về hợp đồng của kẻ tấn công trong Solidity
Xây dựng hợp đồng NFT chuỗi chéo
Làm cách nào để có thể thực hiện việc thu thập NFT chuỗi chéo và chúng ta nên tính đến những biện pháp phòng ngừa nào?
Giả sử chúng ta muốn tạo một bộ sưu tập NFT có thể được sử dụng trong 2 chuỗi khác nhau, hãy gọi chúng là chainA và chainB.
Chúng ta có thể thực hiện điều đó một cách rất đơn giản bằng cách triển khai hợp đồng NFT trong cả hai chuỗi và duy trì một phiên bản duy nhất bằng cách sử dụng cầu nối để thực hiện lệnh gọi giữa các chuỗi. Điều này đảm bảo rằng chỉ có một chủ sở hữu cho một ID nhất định và ngăn việc tạo nhiều bản sao của cùng một ID, điều này sẽ dẫn đến mã thông báo có thể thay thế được. Chúng tôi cũng yêu cầu chức năng chuyển mã thông báo giữa các chuỗi được hỗ trợ.
Trong ví dụ này, tên bộ sưu tập NFT là crossChainWarriors. Nếu người dùng sở hữu một chiến binh trong chainA và muốn chuyển nó sang chainB, một cách đơn giản để làm như vậy là đốt nó trong chainA và đúc nó trong chainB bằng cách sử dụng phép thuật và sự an toàn của cây cầu.
trừu tượng cầu
Một sơ đồ nhỏ sẽ giúp chúng ta hiểu mình đang đứng ở đâu.
Như chúng ta thấy trong sơ đồ, việc thực hiện chuyển giao chuỗi chéo trong chainA sẽ kích hoạt một sự kiện được trình xác nhận cầu lắng nghe. Sau đó, họ gọi hợp đồng đích với dữ liệu đã truy xuất.
thư viện an toàn
Hãy xem chức năng đúc của crossChainWarriors:
Tất cả đều bình thường nhưng hãy khám phá _safeMint làm gì :
Hàm này có logic tương tự như _mint nhưng nó thực hiện kiểm tra bổ sung để đảm bảo rằng người nhận có thể xử lý chức năng ERC721. Điều này quan trọng khi người nhận không phải là EOA.
Nhưng _checkOnERC721Received đang làm gì?
Đây là một đoạn mã lớn nhưng chúng ta hãy chỉ chú ý đến phần này:
Điều quan trọng cần lưu ý là một cuộc gọi bên ngoài tới người nhận đang được thực hiện. Nếu bạn đang nghĩ về các cuộc tấn công vào lại, các cuộc gọi bên ngoài là cửa hậu cho tin tặc.
Cuộc gọi bên ngoài này được sử dụng để hỏi người nhận xem anh ta có thể xử lý ERC721 hay không, chính xác hơn là nó có triển khai giao diện bộ thu IERC721 hay không. Người nhận phải trả lại IERC721Receiver.onERC721Received.selector để vượt qua kiểm tra, nhưng trước đó, hợp đồng cũng có thể thực hiện các giao dịch khác.
Hợp đồng đơn giản nhất biết về giao diện máy thu ERC721 sẽ là:
Như đã thấy trong mã bên dưới, trước khi trả lại bộ chọn, bạn có thể làm bất cứ điều gì bạn muốn, chỉ cần đừng quên trả lại bộ chọn ở cuối.
Tuy nhiên, hợp đồng này có xử lý chuyển khoản ERC721 không?
Câu trả lời đơn giản là không, NFT được gửi đến hợp đồng này sẽ bị mất mãi mãi.
Nói một cách đơn giản, ý tưởng đằng sau _safeMint là cung cấp một biện pháp kiểm tra bổ sung để bảo vệ người dùng khỏi bị mất mã thông báo của họ. Nhưng kiểm tra này chỉ xác minh rằng người nhận biết IERC721Receiver và không đảm bảo rằng người nhận có thể xử lý ERC721. Ngoài ra, nó đi kèm với chi phí bổ sung của một cuộc gọi bên ngoài không an toàn.
Bây giờ là lúc xem xét cách cuộc gọi bên ngoài không an toàn có thể được sử dụng để thỏa hiệp hợp đồng
Khai thác cuộc gọi bên ngoài không an toàn
Hãy quay lại hàm đúc ban đầu chỉ tập trung vào dòng thứ 3.
Bây giờ hãy xem xét điều này:
Quá trình thực thi có thể bị gián đoạn ở dòng 3, cho phép thực hiện lệnh gọi bên ngoài trước khi cập nhật các biến trạng thái. Hãy chú ý đến các biến trạng thái được sửa đổi trong chức năng này và nơi chúng đang được sửa đổi.
tokenIds.increment()
Cách tiếp cận ban đầu tự nhiên sẽ là gọi lại mint()
nhưng chức năng bên trong ERC721 _mint sẽ không thành công vì id mã thông báo không được tăng lên và đã tồn tại.
require(!_exists(tokenId), "ERC721: token already minted");
Những chức năng nào khác có thể được gọi từ hợp đồng của kẻ tấn công?
- crossChainTransfer():
Một con đường tấn công có thể có thể là:
- Gọi mint() trong chainA với hợp đồng kẻ tấn công là người nhận
- Nhập lại hợp đồng và gọi crossChainTransfer để chuyển id mới sang chainB.
- gọi lại mint() trên chainA
Bây giờ chúng ta đã đi đến bước cuối cùng, bao gồm việc viết hợp đồng cho kẻ tấn công và thử nghiệm cuộc tấn công bằng cách sử dụng mạng thử nghiệm Goerli và Mumbai. Nếu bạn không quan tâm đến phần này, hãy nhảy đến phần kết luận.
Ví dụ về hợp đồng của kẻ tấn công trong Solidity
Đây sẽ là hợp đồng kẻ tấn công của chúng tôi:
Chúng tôi sẽ sử dụng các địa chỉ này:
- 0x1491a65c4DE0fEe28f8bFEB185eD76fAB49c5a56 làm trình xác thực cầu nối
- 0x0011fCC414149402DFd8629D71b8823f52d7Ca0B với tư cách là tin tặc
- 0xb6Fa6b5Ac9C88AE7a422ac479E798978186B1B60 làm hợp đồng kẻ tấn công
- 0x50287aFea592863C2f30eacFBca54aaC6e85BF02 dưới dạng
hợp đồng CrossChainWarriors trong Goerli (chainA) - 0xCB0fc01dE73aa06F5A443d9F7b682d583E9Aa684 dưới dạng
hợp đồng CrossChainWarriors ở Mumbai (chainB)
Trong chainA, cuộc tấn công dường như đã thành công. Id #1 đã được đúc sau đó được ghi để chuyển và được đúc lại.
Hãy kiểm tra sự kiện CrossChainTransfer:
Trình xác thực lấy địa chỉ và thông báo từ sự kiện để thực hiện giao dịch trong chainB:
tin nhắn: (96 byte)
0x000000000000000000000000000000000000000000000000000000000000000000000000000000000000b6fa6b5ac9c88ae7a422ac479e798978186 b1b600000000000000000000000000011fcc414149402dfd8629d71b8823f52d7ca0b
Giao dịch của trình xác thực trên chainB :
Ta có thể thấy dữ liệu đầu vào của giao dịch tương ứng với thông báo của sự kiện (96 byte):
Cuộc tấn công đã thành công, địa chỉ 0x0011fCC414149402DFd8629D71b8823f52d7Ca0B là chủ sở hữu của id #1 trong cả hai chuỗi.
Các giải pháp?
Nếu ID mã thông báo được tăng lên trước cuộc gọi bên ngoài thì cuộc tấn công này sẽ không thể thực hiện được.
Một giải pháp khả thi khác là sử dụng mô-đun hợp đồng ReentrancyGuard của OpenZeppelin.
Phần kết luận
Chúng ta đã thấy chức năng cơ bản của hợp đồng NFT đa chuỗi và bề mặt tấn công của cài đặt chuỗi chéo chuyển thông điệp, tập trung vào các cuộc gọi bên ngoài được thực hiện bởi các thư viện an toàn. Cuộc tấn công này sẽ không thể thực hiện được trong môi trường một chuỗi.
Thực hành bảo mật tốt phải được biết và hiểu. Luôn kiểm tra mã của bạn, mã an toàn thường xuyên đi kèm với việc mở rộng bề mặt tấn công, đừng dựa vào tên thư viện.
Báo cáo gốc:
https://quantumbrief.io/#trusted-by

![Dù sao thì một danh sách được liên kết là gì? [Phần 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)



































