Giải thích chi tiết về lỗ hổng hợp đồng thông minh Opyn của nền tảng DeFi: Kẻ tấn công trắng tay
PeckShield
2020-08-06 06:32
本文约1846字,阅读全文需要约7分钟
Trước tiên, kẻ tấn công xảo quyệt sẽ thực hiện một giao dịch trá hình cho chính mình và sử dụng tính năng có thể tái sử dụng của ETH này để bắt đầu chuyển lại cho người dùng của người bán

Vào ngày 5 tháng 8 năm 2020, theo giờ Bắc Kinh, hợp đồng thông minh Opyn ETH Put của nền tảng tùy chọn DeFi Opyn đã bị hack, dẫn đến thiệt hại khoảng 370.000 đô la Mỹ.

Opyn là một thỏa thuận quyền chọn chung, đã được chuyển đổi thành một nền tảng bảo hiểm vào tháng 2 năm nay.

Sau khi biết nền tảng Opyn bị tấn công, nhóm bảo mật PeckShield đã nhanh chóng xác định được mấu chốt của vấn đề:

Kẻ tấn công phát hiện ra rằng giao diện thực hiện (bài tập) hợp đồng thông minh Opyn có một số lỗi trong quá trình xử lý ETH nhận được và hợp đồng của nó không kiểm tra số tiền giao dịch theo thời gian thực của người giao dịch, để kẻ tấn công có thể bắt đầu giao dịch thực trên Sau đó, tự mình chèn một giao dịch giả mạo để lừa đảo tài sản kỹ thuật số đã thế chấp của người bán, rồi trắng tay.

Nói một cách đơn giản, bởi vì chức năng thực hiện Exercise() trong hợp đồng thông minh Opyn ETH Put không thực hiện xác minh thời gian thực ETH của người giao dịch. Theo logic kinh doanh của nền tảng Opyn, người mua quyền chọn bán chuyển giá trị tương ứng của ETH cho người bán để lấy tài sản kỹ thuật số được thế chấp bởi người bán. Trước tiên, kẻ tấn công xảo quyệt sẽ thực hiện một giao dịch trá hình cho chính mình và sử dụng tính năng có thể tái sử dụng của ETH này để bắt đầu chuyển lại cho người dùng của người bán, do đó lừa gạt người bán tài sản kỹ thuật số đã thế chấp.

tiêu đề phụ

Phân tích quy trình chi tiết lỗ hổng

Trước tiên tôi xin nói về logic kinh doanh của nền tảng Opyn: khi người dùng sử dụng hợp đồng Opyn để thực hiện, nghĩa là mua và bán hợp đồng tương lai (thực hiện), người mua cần chuyển một lượng ETH hoặc Mã thông báo ERC20 tương ứng cho người bán, sau đó hợp đồng sẽ hủy oToken tương ứng của người mua, sau đó Người mua sẽ nhận được tài sản mà người bán đã thế chấp.

Mô tả hình ảnh

Hình 1. Danh sách các địa chỉ vault được truyền vào được lặp lại trong hàm Exercise()

Mô tả hình ảnh

Hình 2. Tái sử dụng ETH được chuyển vào hợp đồng để lấy tài sản thế chấp

Khi chức năng xử lý Mã thông báo ERC20, giống như hầu hết các dự án DeFi, hãy sử dụng transferFrom(), như được hiển thị trong dòng 1882 của mã, để chuyển tiền từ msg.sender đến địa chỉ(this).

Nhưng khi tài sản được xử lý bởi chức năng là ETH, phương thức xử lý hoàn toàn khác. Vì trong Solidity, msg.value có nghĩa là số lượng ETH được người gọi hợp đồng chuyển vào hợp đồng khi gọi giao diện thanh toán, chỉ là một giá trị, vì vậy trong dòng 1879 của mã hợp đồng, hãy kiểm tra msg.value == amtUnderlyingToPay chỉ đảm bảo rằng hợp đồng đã thực sự nhận được số lượng ETH của amtUnderlyingToPay và sẽ không có bất kỳ tác động nào đến giá trị của msg.value.

Nhưng như đã đề cập ở trên, hàm _exercise() sẽ được gọi theo chu kỳ trong tập thể dục(), dẫn đến việc mặc dù hợp đồng thực sự chỉ nhận ETH một lần nhưng nó có thể được sử dụng lại trong suốt vòng lặp.

Mô tả hình ảnh

Hình 3. Phân tích giao dịch tấn công

Trong Hình 3, chúng tôi hiển thị quá trình tấn công thông qua quá trình gọi được hiển thị bởi trình duyệt Bloxy. Vì kẻ tấn công đã tiêu thụ nhiều đơn đặt hàng, chúng tôi sẽ lấy một trong các giao dịch làm ví dụ để cho bạn thấy logic tấn công:

1. Đầu tiên, kẻ tấn công đã mua 75 oETH từ Uniswap để chuẩn bị cho việc thực hiện chức năng gọi tiếp theo;

2. Kẻ tấn công đã tạo một địa chỉ Vault với tư cách là một người bán quyền chọn bán khống và thế chấp 24.750 USDC để đúc 75 oETH, nhưng không bán các quyền chọn này, nghĩa là anh ta đã mua quyền bán 75 ETH với giá 330 cùng một lúc ;

tiêu đề phụ

đề xuất sửa chữa

Nhóm bảo mật PeckShield gợi ý rằng trong Solidity, hợp đồng có thể sử dụng biến cục bộ msgValue để lưu trữ ETH nhận được (tức là giá trị của msg.value). Theo cách này, bằng cách vận hành msgValue trong các bước tiếp theo, có thể đánh dấu chính xác số lượng ETH đã được chi tiêu, do đó tránh việc tài sản bị tái sử dụng. Ngoài ra, chúng ta cũng có thể sử dụng address(this).balance để kiểm tra số dư hợp đồng nhằm tránh rủi ro msg.value bị sử dụng lại.

PeckShield
作者文库