Bởi: 九九
lý lịch
Vào ngày 5 tháng 12 năm 2023, nền tảng phát triển cơ bản Web3 Thirdweb tuyên bố rằng đã tìm thấy vấn đề bảo mật trong hợp đồng thông minh dựng sẵn và tất cả các mã thông báo ERC20, ERC721 và ERC1155 được triển khai bằng hợp đồng thông minh dựng sẵn đều bị ảnh hưởng. (Đối với các phiên bản mã hợp đồng bị ảnh hưởng cụ thể, vui lòng tham khảo: https://blog.thirdweb.com/security-vulnerability/)

Theo thông tin tình báo từ nhóm bảo mật SlowMist, vào ngày 7 tháng 12 năm 2023, mã thông báo Time trên mạng chính ETH đã bị tấn công chính xác vì lỗ hổng này và kẻ tấn công đã kiếm được khoản lãi khoảng 190.000 USD. Vẫn còn nhiều hợp đồng token có lỗ hổng bị tấn công. Nhóm bảo mật SlowMist đã ngay lập tức can thiệp vào phân tích và chia sẻ kết quả như sau:
Kiến thức tiên quyết
1. ERC-2771 là tiêu chuẩn cho các giao dịch meta. Người dùng có thể ủy quyền thực hiện giao dịch cho Forwarder bên thứ ba, thường được gọi là rơle hoặc Forwarder.
Thông thường, địa chỉ của người gọi trực tiếp trong hợp đồng được lấy bằng msg.sender, nhưng trong trường hợp sử dụng ERC-2771, nếu msg.sender là vai trò chuyển tiếp, dữ liệu cuộc gọi đến sẽ bị cắt bớt và 20 từ cuối cùng sẽ được lấy phần . làm địa chỉ người gọi trực tiếp của giao dịch.

2. Multicall là thư viện hợp đồng thông minh cho phép thực hiện nhiều lệnh gọi chức năng theo đợt, từ đó giảm chi phí giao dịch. Thư viện này thường được sử dụng để tối ưu hóa hiệu suất và trải nghiệm người dùng của DApps, đặc biệt khi yêu cầu nhiều thao tác đọc.
Như có thể thấy từ mã, thư viện Multicall được hợp đồng dễ bị tấn công sử dụng trong dự án web thứ ba sẽ thực thi các chức năng khác trong hợp đồng tham chiếu đến thư viện bằng cách gọi hàm DelegateCall theo chu kỳ.

nguyên nhân gốc rễ
Nguyên nhân sâu xa của lỗ hổng là hợp đồng token sử dụng cả thư viện ERC-2771 và Multicall. Kẻ tấn công gọi hàm multicall của hợp đồng token thông qua hàm thực thi của hợp đồng Forwarder để thực thi các chức năng khác trong hợp đồng (chẳng hạn như đốt token). Phương thức này đã vượt qua thành công phán đoán isTrustedForwarder của ERC-2771 và cuối cùng giải quyết lệnh gọi hàm thành 20 byte cuối cùng của dữ liệu cuộc gọi độc hại. Do đó, kẻ tấn công đã lừa dối thành công hợp đồng khi nghĩ rằng người gọi là địa chỉ của một người dùng khác, từ đó dẫn đến việc đốt token của người dùng khác.
Phân tích các bước tấn công
Ở đây chúng tôi lấy giao dịch tấn công 0xecdd11...f6b6 làm ví dụ để phân tích:
1. Kẻ tấn công lần đầu tiên sử dụng 5 WETH để đổi lấy 345.539.9346 mã thông báo Thời gian trong nhóm Uniswap V2.

2. Sau đó gọi hàm thực thi của hợp đồng Forwarder để xây dựng dữ liệu độc hại để gọi hàm multicall của hợp đồng token. Lúc này, hợp đồng token sẽ ủy quyềnGọi để thực thi chức năng ghi của hợp đồng token dựa trên dữ liệu độc hại được truyền vào. bởi kẻ tấn công, đốt cháy địa chỉ nhóm 62.227.259.510 Mã thông báo thời gian.

3. Vì bước trước đã đốt một số lượng lớn mã thông báo Thời gian trong nhóm, khiến giá mã thông báo Thời gian tăng ngay lập tức, kẻ tấn công cuối cùng có thể đảo ngược việc hoán đổi mã thông báo Thời gian thu được ở bước đầu tiên, làm cạn kiệt 94 WETH.

Phân tích nguyên tắc tấn công
Trong chức năng thực thi của hợp đồng Forward, sau khi xác minh chữ ký của req.from, lệnh gọi sẽ được sử dụng để tương tác với req.to (địa chỉ token). Req.data được kẻ tấn công truyền vào là


Vì 0xac9650d8 là chữ ký hàm của hàm multicall, nên hàm multicall của hợp đồng mã thông báo sẽ được gọi và giá trị dữ liệu được truyền vào bởi hàm multicall là 0x42966c68000000000000000000000000000000000000000c9112ec16d958e8da8180000760dc 1 e043d99394a10605b2fa08f123d60faf84.
Tại sao không có req.from trong giá trị dữ liệu được truyền vào hàm multicall? Điều này là do lớp dưới cùng EVM sẽ cắt bớt giá trị được yêu cầu dựa trên phần bù khi xử lý cuộc gọi. Giá trị offset được đặt trong giá trị calldata được kẻ tấn công truyền là 38 và độ dài giá trị là 1 nên nó chỉ chặn giá trị dữ liệu là. 42966c6800000000000000000000000000000000000000000c9112ec16d958e8da8180000760dc1e043d99394a10605b2fa08f123d60faf84.

Để biết chi tiết, vui lòng tham khảo mô tả cuộc gọi trong opcode EVM (https://www.evm.codes/?fork=shanghai).

Vì 0x42966c68 là chữ ký hàm của hàm ghi, nên hàm ghi của hợp đồng mã thông báo sẽ được gọi thông qua delegatecall dựa trên giá trị dữ liệu do kẻ tấn công tạo ra.

Hàm _msgSender() bị thư viện ERC-2771 ghi đè.

Vì multicall được gọi thông qua delegatecall, nên msg.sender được truyền vào bởi isTrustedForwarder thực sự là địa chỉ của hợp đồng Forward, do đó sẽ chuyển phán quyết và cuối cùng giá trị được trả về bởi _msgSender() là 20 byte cuối cùng của dữ liệu cuộc gọi được truyền vào. Đó là, địa chỉ của nhóm là 0x760dc1e043d99394a10605b2fa08f123d60faf84.
Tóm lại là
Nguyên nhân sâu xa của cuộc tấn công này là do hợp đồng tham chiếu cả Multicall và ERC2771Context. Kẻ tấn công có thể chèn dữ liệu cuộc gọi độc hại vào yêu cầu chuyển tiếp, sử dụng chức năng delegatecall của Multicall để vượt qua phán quyết của người chuyển tiếp đáng tin cậy và thao túng _msgSender() trong cuộc gọi phụ. Phân tích, để bất kỳ mã thông báo nào của người dùng đều có thể bị thao túng.
Nhóm bảo mật SlowMist khuyến nghị các bên tham gia dự án không nên sử dụng Multicall và ERC2771Context cùng lúc khi viết hợp đồng mã thông báo. Nếu nhu cầu dự kiến yêu cầu tham chiếu đồng thời, bạn phải kiểm tra xem độ dài dữ liệu cuộc gọi có đáp ứng mong đợi hay không hoặc sử dụng phiên bản chính thức mới nhất của Multicall và openzeppelin. Hợp đồng ERC2771Context.
thẩm quyền giải quyết
Địa chỉ kẻ tấn công: 0xfde0d1575ed8e06fbf36256bcdfa1f359281455a
Hợp đồng tấn công: 0x6980a47bee930a4584b09ee79ebe46484fbdbdd0
Các giao dịch tấn công liên quan: https://etherscan.io/tx/0xecdd111a60debfadc6533de30fb7f55dc5ceed01dfadd30e4a7ebdb416d2f6b6
Chi tiết phiên bản bị ảnh hưởng: https://blog.thirdweb.com/security-vulnerability/
Công cụ giảm thiểu: https://mitigate.thirdweb.com/
